This article is part of the Salesforce Admin Git & sf CLI series, a complete guide to version control and metadata management for Salesforce admins. Articles are standalone; no need to read in order.
TL;DR
- Retrieve all Flows:
sf project retrieve start --metadata Flow --target-org myorg - Retrieve one specific Flow:
sf project retrieve start --metadata "Flow:My_Flow_API_Name" --target-org myorg - List automation components before retrieving:
sf org list metadata --metadata-type Flow --target-org myorg - Flow XML is deeply nested and hard to read. Store it in version control anyway. Knowing when it changed is worth more than being able to read the raw XML at a glance.
What You'll Learn
- How to retrieve Flow, WorkflowRule, FlowDefinition (Process Builder), and ApprovalProcess metadata
- How to list automation components in your org before retrieving
- The difference between source format and MDAPI format for automation metadata
- How to use package.xml for repeatable multi-type retrieves
- Why Flow XML is hard to read but essential to version-control
- Notes on Flow vs Process Builder deprecation timeline
The Problem
Your org is full of Flows, maybe some old Workflow Rules, and approval processes no one has documented. Without version control you can't see what changed, when, or why. This article shows you how to pull all your automation metadata out of Salesforce and onto your hard drive.
Common questions this article answers:
- How do I retrieve all my Flows using sf CLI?
- How do I get Process Builder flows vs screen flows vs autolaunched flows?
- What does Flow XML look like on disk?
- Can I retrieve WorkflowRules? Are they still supported?
- How do I get ApprovalProcess metadata?
Quick Answer
If you just need to get started, here are the three commands you'll use most:
# 1. List what's in your org — see exact API names before retrieving
sf org list metadata --metadata-type Flow --target-org myorg
# 2. Retrieve all Flows at once
sf project retrieve start --metadata Flow --target-org myorg
# 3. Retrieve one specific Flow by its API name
sf project retrieve start --metadata "Flow:My_Flow_API_Name" --target-org myorg
The pattern is the same for every automation type. Swap Flow for WorkflowRule, FlowDefinition, or ApprovalProcess and the commands work the same way. The sections below go deeper: file locations, package.xml, MDAPI format, and what to do when things go wrong.
Section 1: List Automation Components First
Before you retrieve, it helps to know exactly what's in your org. The sf org list metadata command queries Salesforce and returns a list of all deployed components for a given metadata type. This is how you get the exact API names you need for targeted retrieves.
# List all Flows in the org
sf org list metadata --metadata-type Flow --target-org myorg
# List all Workflow Rules
sf org list metadata --metadata-type WorkflowRule --target-org myorg
# List FlowDefinitions (Process Builder — legacy)
sf org list metadata --metadata-type FlowDefinition --target-org myorg
# List Approval Processes
sf org list metadata --metadata-type ApprovalProcess --target-org myorg
The output includes a fullName column. This is the value you pass to --metadata for a targeted retrieve.
The format of fullName differs by type:
| Metadata type | Example fullName |
|---|---|
| Flow | My_Account_Onboarding_Flow |
| WorkflowRule | Account.Send_Welcome_Email |
| FlowDefinition | My_Opportunity_Process |
| ApprovalProcess | Opportunity.My_Approval_Process |
For WorkflowRule and ApprovalProcess, the fullName includes the object name as a prefix, separated by a dot. You need this full value when retrieving a specific component: --metadata "WorkflowRule:Account.Send_Welcome_Email".
Section 2: Retrieve in Source Format (Default)
Source format is the default output when you run sf project retrieve start. It produces one file per component and is the right choice for git: each file is a self-contained unit, diffs are scoped to a single component, and you can track changes at the individual Flow level.
# Retrieve ALL Flows
sf project retrieve start --metadata Flow --target-org myorg
# Retrieve a specific Flow by API name
sf project retrieve start --metadata "Flow:My_Flow_API_Name" --target-org myorg
# Retrieve ALL WorkflowRules
sf project retrieve start --metadata WorkflowRule --target-org myorg
# Retrieve a specific Workflow Rule
sf project retrieve start --metadata "WorkflowRule:Account.My_Rule" --target-org myorg
# Retrieve Process Builder flows (FlowDefinition)
sf project retrieve start --metadata FlowDefinition --target-org myorg
# Retrieve a specific FlowDefinition
sf project retrieve start --metadata "FlowDefinition:My_Process" --target-org myorg
# Retrieve ALL ApprovalProcesses
sf project retrieve start --metadata ApprovalProcess --target-org myorg
# Retrieve a specific ApprovalProcess
sf project retrieve start --metadata "ApprovalProcess:My_Approval" --target-org myorg
# Retrieve multiple automation types at once
sf project retrieve start --metadata Flow WorkflowRule ApprovalProcess --target-org myorg
Managed package components: If you see Flow API names with a namespace prefix (e.g.,
mypkg__My_Flow), those come from a managed package. You can retrieve them to inspect the XML, but they are read-only. You cannot modify and deploy managed package metadata back to the org. Never commit namespace-prefixed automation metadata as if it were your own.
# Retrieve Flows from a specific installed package (by package name)
sf project retrieve start --metadata Flow --package-name "MyPackageName" --target-org myorg
Use this only to inspect what a package contains. Managed package components retrieved this way are read-only.
# Retrieve into a custom output directory (source format, not MDAPI)
sf project retrieve start --metadata Flow --target-org myorg --output-dir ./my-backup
--output-dir changes where source-format files land. It does NOT produce MDAPI format; that requires --target-metadata-dir (covered in Section 3).
Each flag explained:
--metadata Flow: the metadata type to retrieve. You can pass multiple types separated by spaces.--metadata "Flow:My_Flow_API_Name": retrieve a single component. The colon separates the type from the API name.--target-org myorg: the org alias you set when you connected the org withsf org login. Replacemyorgwith your actual alias.
No output directory flag means files land in your project's default source path, typically force-app/main/default/.
Section 3: Retrieve in MDAPI Format
MDAPI format is an older layout that produces a ZIP file containing a flat folder structure and a package.xml manifest. You might use it for integrations, tooling that expects the older format, or when handing off a ZIP to someone who isn't using sf CLI.
# Retrieve Flow in MDAPI format (produces ZIP, then extracts it)
sf project retrieve start --metadata Flow --target-org myorg --target-metadata-dir mdapi-output --unzip
# Retrieve WorkflowRule in MDAPI format
sf project retrieve start --metadata WorkflowRule --target-org myorg --target-metadata-dir mdapi-output --unzip
Flag breakdown:
--target-metadata-dir mdapi-output: write output to this directory in MDAPI format rather than source format. If the directory doesn't exist, sf CLI creates it.--unzip: the raw MDAPI retrieve produces a ZIP file. This flag extracts it automatically so you get a folder rather than a.zip.
Source format vs MDAPI format: what lands on disk:
| Format | Path | Notes |
|---|---|---|
| Source format | force-app/main/default/flows/My_Flow.flow-meta.xml |
One file per Flow |
| MDAPI format | mdapi-output/unpackaged/flows/My_Flow.flow |
Slightly different extension, flat structure |
For git purposes, source format wins. One file per Flow means each commit touches only the Flows that actually changed. With MDAPI format, all Flows would be inside a single directory, but you still get one file per Flow. The main difference is the extension and the package.xml that ships alongside.
Section 4: Retrieve Using package.xml
A package.xml manifest lets you define exactly what you want to retrieve once, then re-run the same retrieve as many times as you need. Useful for setting up a repeatable baseline retrieve or automating retrieves in a script.
sf project retrieve start --manifest package.xml --target-org myorg
Example package.xml for all automation types:
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<types>
<members>*</members>
<name>Flow</name>
</types>
<types>
<members>*</members>
<name>WorkflowRule</name>
</types>
<types>
<members>*</members>
<name>FlowDefinition</name>
</types>
<types>
<members>*</members>
<name>ApprovalProcess</name>
</types>
<version>62.0</version>
</Package>
<members>*</members> is the wildcard: retrieve everything for that type. You can replace * with a specific API name to retrieve only that component:
<types>
<members>My_Account_Onboarding_Flow</members>
<name>Flow</name>
</types>
Keep your package.xml in version control alongside your metadata. It documents exactly what you've chosen to track and makes it easy for anyone else on the team to run the same retrieve.
Section 5: What Files Look Like on Disk
After a source format retrieve, your project folder looks like this:
force-app/
└── main/
└── default/
├── flows/
│ ├── My_Screen_Flow.flow-meta.xml
│ ├── My_Autolaunched_Flow.flow-meta.xml
│ └── My_Record_Triggered_Flow.flow-meta.xml
├── workflows/
│ └── Account.workflow-meta.xml ← ALL workflow rules for Account in one file
└── approvalProcesses/
└── Opportunity.My_Approval_Process.approvalProcess-meta.xml
A few things to note about how these differ:
Flows: each Flow gets its own .flow-meta.xml file. The filename is the Flow's API name. This is the cleanest layout for git because git diff on a single Flow only shows changes to that Flow.
WorkflowRules: unlike Flows, all Workflow Rules for a given object are bundled into a single file. Account.workflow-meta.xml contains every rule on the Account object. If someone changes any rule on Account, the entire file shows up as changed in your diff.
ApprovalProcesses: similar to Flows, each approval process gets its own file. The filename format is ObjectName.ProcessApiName.approvalProcess-meta.xml.
What Flow XML looks like:
Flow XML is deeply nested. Here's a small snippet to give you a sense of it:
<?xml version="1.0" encoding="UTF-8"?>
<Flow xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>62.0</apiVersion>
<decisions>
<name>Check_Account_Type</name>
<label>Check Account Type</label>
<locationX>176</locationX>
<locationY>288</locationY>
<defaultConnectorLabel>Default Outcome</defaultConnectorLabel>
<rules>
<name>Is_Customer</name>
<conditionLogic>and</conditionLogic>
<conditions>
<leftValueReference>Account.Type</leftValueReference>
<operator>EqualTo</operator>
<rightValue>
<stringValue>Customer</stringValue>
</rightValue>
</conditions>
<label>Is Customer</label>
</rules>
</decisions>
<processType>Flow</processType>
<start>
<locationX>50</locationX>
<locationY>0</locationY>
<connector>
<targetReference>Check_Account_Type</targetReference>
</connector>
</start>
<status>Active</status>
</Flow>
Even this short snippet is not easy to scan. A complex Flow with dozens of elements, assignments, loops, and connectors can run to hundreds or thousands of lines. The XML does not reflect the visual canvas layout in any human-readable way: element positions are stored as x/y coordinates rather than as a logical sequence.
This is fine. You don't need to read the XML to get value from version control. What you get is:
- A record of when the Flow changed (every git commit is timestamped)
- The ability to compare two versions with
git diffand see exactly which elements changed, which conditions were added, which field references were updated - A restore point: if a Flow breaks in production, you can look back at older committed versions
Store the Flow XML in git even if you can't interpret it at a glance. The historical record is the value.
Section 6: Flow vs Process Builder Deprecation Note
If your org has been around a while, you probably have some Process Builder automations alongside your Flows. Here is where things stand:
Flow (--metadata Flow): the current metadata type for all modern Salesforce automation: screen flows, autolaunched flows, record-triggered flows, and scheduled flows. If you built it in Flow Builder after roughly 2020, it is a Flow. This is what you should be building with.
FlowDefinition (--metadata FlowDefinition): the metadata type for Process Builder automations. Process Builder was deprecated in Spring '23. Salesforce strongly recommends migrating all Process Builder automations to Flows. However, many orgs still have active Process Builders that have never been touched, and you can still retrieve them.
WorkflowRule (--metadata WorkflowRule): legacy automation from before Process Builder existed. Workflow Rules are point-and-click rules that trigger field updates, email alerts, and outbound messages. They are still active in many orgs but are not being enhanced. Record-triggered Flows cover the same use cases with more flexibility.
What to do with legacy types:
- Retrieve them. If they're active in your org, they affect your business logic.
- Store them in version control. You want visibility when someone changes or deactivates a legacy rule.
- Plan migration when the time is right. That's a separate project. Version-controlling them first gives you a baseline to work from.
Section 7: Preview Before Retrieving
If you want to see what sf CLI will retrieve before it actually pulls anything, use the preview command:
sf project retrieve preview --target-org myorg
This outputs a table showing which components would be retrieved and whether they are new, changed, or the same as what you already have locally. No files are written. It is a safe, read-only check.
Useful when:
- Your org has a large number of Flows and you want a count before committing to the full retrieve
- You want to confirm that the components you expect are actually going to be pulled
- You've made local edits and want to see which files would be overwritten
Troubleshooting
"No such metadata type: Flow"
The type name is case-sensitive. It must be Flow, not flow or FLOW. Same for WorkflowRule, FlowDefinition, and ApprovalProcess. All follow PascalCase.
Flow retrieved but shows old version
sf project retrieve start retrieves the currently active (deployed) version of a Flow. If someone is editing a Flow in Flow Builder and has saved it as a draft without activating it, you will get the previously activated version, not the draft. Check Flow Manager in Setup to see if a draft version exists.
WorkflowRule retrieved but file seems empty
If an object has no active Workflow Rules, the .workflow-meta.xml file may contain just an empty shell element. This is expected behaviour: the file represents the object, and if there are no rules, the file is nearly empty.
"Component not found: Flow:My Flow"
Flow API names use underscores, not spaces. The display label in Setup might say "My Flow" but the API name is My_Flow. Run sf org list metadata --metadata-type Flow --target-org myorg to see the exact fullName for every Flow in your org.
ApprovalProcess not showing up in list Approval Processes require the "View Setup and Configuration" permission to retrieve. If you get an empty result or a permission error, check that your Salesforce user profile or permission set includes this permission.
Frequently Asked Questions
Q: How do I tell if a Flow is a Screen Flow, Autolaunched Flow, or Record-Triggered Flow from the file name?
You can't tell from the file name alone. The file name is just the API name of the Flow. The Flow type is stored inside the XML. Open the .flow-meta.xml file in a text editor and search for <processType>. Common values:
| processType value | Flow type |
|---|---|
Flow |
Screen Flow |
AutoLaunchedFlow |
Autolaunched Flow |
RecordTriggeredFlow |
Record-Triggered Flow |
Workflow |
Process Builder (legacy) |
CustomEvent |
Platform Event-triggered Flow |
Q: Does retrieving a Flow also retrieve its version history?
No. sf project retrieve start retrieves only the currently active (deployed) version. Salesforce does not expose historical Flow versions through the metadata API. Only the active version is accessible. This is exactly why committing to git after each retrieve is valuable: your commit history becomes the version history that Salesforce doesn't give you.
Q: What happens if I have 200 Flows in my org?
sf project retrieve start --metadata Flow --target-org myorg retrieves all of them in a single command. Large orgs may take a minute or two as Salesforce packages everything up on their end. Run sf project retrieve preview --target-org myorg first to see the count before committing to the full retrieve.
Q: Can I retrieve a Flow that is in Draft (not yet activated)?
No. A Draft Flow exists only inside the Flow Builder UI and is not accessible via the metadata API. To retrieve a Flow, it must be activated. Once activated, sf project retrieve start will pull it.
Q: WorkflowRules vs Flows: should I still version-control WorkflowRules?
Yes. If a Workflow Rule is active in your org, it is running business logic. It belongs in version control regardless of its legacy status. The goal is to have a complete picture of what is running in your org, not just the modern parts. You want to know if someone changes or deactivates a Workflow Rule. Without version control, that change is invisible.
Key Takeaways
- List first:
sf org list metadata --metadata-type Flow --target-org myorggives you exact API names before you retrieve anything - Flow is the type for modern automation:
Flowcovers screen flows, autolaunched flows, record-triggered flows, and scheduled flows - FlowDefinition for Process Builder: legacy type, still retrievable, use
--metadata FlowDefinition - Source format: one
.flow-meta.xmlfile per Flow, best for git diffs even though the XML is hard to read at a glance - WorkflowRules are per-object files: all rules for one object land in a single
Account.workflow-meta.xmlfile, not one file per rule - Active version only: sf CLI retrieves the currently active Flow; draft flows are not accessible via the metadata API
What's Next?
Recommended Reading:
- Article 6: Fetching Security Metadata: Profile, PermissionSet, Role
- Article 4: Fetching Custom Configuration Metadata: CustomObject, CustomField, Layout
- Article 10: Git Basics for Salesforce Admins: commit your Flows to version control
- Article 11: Deploying Metadata Back to Salesforce: deploy Flow changes between orgs
Action Items:
- Run
sf org list metadata --metadata-type Flow --target-org myorgto see all Flows in your org - Retrieve one Flow:
sf project retrieve start --metadata "Flow:YourFlowApiName" --target-org myorg - Open the
.flow-meta.xmlfile and find the<processType>element to identify what kind of Flow it is
Resources & References
- Salesforce Metadata API Developer Guide: Flow
- Salesforce Flow Deprecation: Process Builder Migration
- sf CLI Reference: sf project retrieve start
- Salesforce Metadata Coverage Report
About This Guide: Part of the Salesforce Admin Git & sf CLI series.
Tags: #salesforce #sfcli #flow #automation #versioncontrol