ESC

AI-powered search across all blog posts and tools

DevOps · March 1, 2026

30 Salesforce CLI Commands Every Developer Needs

The definitive reference of sf CLI commands organized by category — from org management to deployments — with real examples and expected output.

☕ 10 min read 📅 March 1, 2026
  • The sf CLI (v2+) replaces sfdx — all commands use the sf prefix and shorter flag names
  • sf org open --path /lightning/n/YourApp lets you deep-link directly into any Salesforce page from the terminal
  • sf apex run test --synchronous blocks until results are available — ideal for CI pipelines

I spend a lot of time in the terminal. Over the years the Salesforce CLI has become the single most-used tool in my daily workflow — more than VS Code extensions, more than workbench, more than any browser plugin. If you’re still clicking through Setup to do things that a one-liner can handle, this post is for you.

This is a living reference I keep bookmarked. I’ve organized it by the task category I’m usually in when I reach for each command.


The CLI Cheat Sheet at a Glance

sf CLI Command Categories
sf CLI CategoriesOrg Managementorg create scratchorg openorg listorg delete scratchorg displayauth web loginSource / Deployproject deploy startproject retrieve startsource pushsource pullsource statussource diffDatadata querydata import treedata export treedata upsert bulkdata delete bulkdata create recordApex / Testsapex runapex run testapex get logapex list logapex tail logschema generate field

Org Management (Commands 1-8)

1. Create a Scratch Org

sf org create scratch \
  --definition-file config/project-scratch-def.json \
  --alias myproject-dev \
  --duration-days 30 \
  --set-default

--set-default saves you from typing -o myproject-dev on every subsequent command. I always set this.

# Open default org home page
sf org open

# Open directly to a specific Lightning page
sf org open --path /lightning/n/Account_Dashboard__c

# Open a specific record
sf org open --path /lightning/r/Account/001XXXXXXXXXXXXXXX/view
💡 Pro Tip

This is genuinely one of the most underused commands. No more copy-pasting URLs from the browser. You can deep-link to any Setup page, Lightning app, or specific record directly from the terminal.

3. List All Authenticated Orgs

sf org list --verbose

Output shows alias, username, org type (scratch/sandbox/production), expiry date, and whether it’s the default. The --verbose flag adds the org ID and connected status.

4. Display Org Details (Including Auth Token)

sf org display --target-org myproject-dev --verbose

Use --verbose to get the access token — useful for debugging API calls with curl or Postman.

5. Delete a Scratch Org

sf org delete scratch --target-org myproject-dev --no-prompt

6. Authenticate to a New Org

Browser OAuth

sf org login web --alias prod-org --instance-url https://login.salesforce.com

JWT for CI

sf org login jwt \
  --client-id $CONSUMER_KEY \
  --jwt-key-file ./server.key \
  --username $SF_USERNAME \
  --alias ci-org

7. Set a Default Org

sf config set target-org myproject-dev
sf config set target-dev-hub my-devhub

8. List Config Values

sf config list

Source Tracking and Deployment (Commands 9-16)

The Problem

Scenario: You’ve been making changes in both your local project and directly in a scratch org through the UI. You’re not sure which version is the source of truth, and you’re worried a blind push or pull will overwrite work you want to keep.

The Solution

Run sf source status (or the canonical sf v2 commands sf project deploy preview / sf project retrieve preview) before any push or pull. The colour-coded output shows local-only changes in green, remote-only changes in blue, and conflicts in yellow. Resolve conflicts one file at a time to see the exact delta before committing to either direction.

9. Push Source to Scratch Org

# Push all tracked changes
sf project deploy start --source-dir force-app

# Push specific metadata
sf project deploy start --metadata ApexClass:AccountService,CustomObject:Order__c

10. Pull Changes from Scratch Org

sf project retrieve start --source-dir force-app

11. Check Source Status

sf source status
ℹ️ Info

Colour-coded output: green for local-only changes, blue for remote-only, yellow for conflicts. Run this before every push to avoid surprises.

Note: sf source status is a legacy sfdx-style alias. The canonical sf v2 command is sf project deploy preview (for deploy) and sf project retrieve preview (for retrieve).

12. Source Diff

sf source diff --source-dir force-app --target-org staging
ℹ️ Info

Note: sf source diff is a legacy sfdx-style alias. The canonical sf v2 equivalents are sf project deploy preview and sf project retrieve preview.

13. Deploy with Test Run

sf project deploy start \
  --source-dir force-app \
  --target-org production \
  --test-level RunLocalTests \
  --dry-run

--dry-run validates without committing. Use this in PR pipelines.

14. Quick Deploy (After Validated Deploy)

sf project deploy quick --job-id <validated-deploy-id> --target-org production

If validation passed in the last 10 days, this deploys without re-running tests — huge time saver for scheduled release windows.

15. Generate a Manifest (package.xml)

sf project generate manifest \
  --source-dir force-app \
  --output-dir manifest

16. Retrieve Using a Manifest

sf project retrieve start \
  --manifest manifest/package.xml \
  --target-org production

Data Operations (Commands 17-22)

17. Run a SOQL Query

sf data query \
  --query "SELECT Id, Name, AnnualRevenue FROM Account WHERE Type = 'Customer' LIMIT 10" \
  --result-format csv

--result-format supports human (default), csv, and json. I pipe the JSON output to jq for quick field extraction.

18. Bulk Upsert from CSV

sf data upsert bulk \
  --file data/accounts.csv \
  --sobject Account \
  --external-id External_ID__c \
  --wait 10

19. Bulk Delete

sf data delete bulk \
  --file data/ids-to-delete.csv \
  --sobject Lead \
  --wait 10

The CSV just needs an Id column.

20. Export Data as a Tree (for Import)

sf data export tree \
  --query "SELECT Id, Name, (SELECT Id, Subject FROM Cases) FROM Account LIMIT 5" \
  --output-dir data/seed

21. Import a Data Tree

sf data import tree \
  --plan data/seed/Account-Case-plan.json \
  --target-org myproject-dev

22. Create a Single Record

sf data create record \
  --sobject Account \
  --values "Name='Forcenaut Test' Type='Prospect' AnnualRevenue=500000"
💡 Pro Tip

Combine sf data export tree with a postCreateOrg script in your sfdx-project.json to automatically seed fresh scratch orgs with realistic test data. Every developer on your team gets a consistent starting state without manually running import commands.


Apex and Debugging (Commands 23-28)

23. Execute Anonymous Apex

sf apex run --file scripts/apex/seed-data.apex

# Quick one-liner via stdin
echo "System.debug('Hello from CLI');" | sf apex run

24. Run Apex Tests

All Local Tests (CI)

sf apex run test \
  --synchronous \
  --result-format human \
  --code-coverage \
  --output-dir test-results

Specific Test Class

sf apex run test \
  --tests AccountServiceTest \
  --synchronous
⚠️ Warning

--synchronous is essential in CI — it blocks the process until tests finish and exits non-zero on test failures. Without it, the pipeline may report success before tests have completed.

25. Tail Debug Logs in Real Time

sf apex tail log --color --debug-level FINEST

This is like tail -f for Apex logs. I keep this open in a side terminal during development sessions.

26. List and Fetch Debug Logs

# List recent logs
sf apex list log

# Fetch a specific log
sf apex get log --log-id <log-id> --output-dir logs/

27. Generate a Field via Schema Command

sf schema generate field --label "External ID" --object Account

28. Generate an Apex Class

sf apex generate class --name AccountService --output-dir force-app/main/default/classes

CI Problem

Scenario: A CI/CD pipeline is failing intermittently on Apex test runs. The pipeline exits before tests finish, reports a false success, and broken code makes it to the next environment. The issue is that tests are running asynchronously and the pipeline doesn’t wait for results.

CI Solution

Add the --synchronous flag to sf apex run test. This blocks the pipeline process until all tests complete and exits with a non-zero code on any test failure. Pair it with --code-coverage and --output-dir test-results to capture JUnit-compatible XML for your CI reporting dashboard.


Aliases and Productivity (Commands 29-30)

29. Set and List Aliases

# Set an alias for a long org username
sf alias set mydev=test-abc123@example.com

# List all aliases
sf alias list

30. Generate a Project Scaffold

sf project generate \
  --name my-new-project \
  --default-package-dir force-app \
  --manifest

My Terminal Setup

Shell aliases I use daily

I keep these aliases in my .zshrc to cut down on typing:

alias sfpush='sf project deploy start --source-dir force-app'
alias sfpull='sf project retrieve start --source-dir force-app'
alias sftest='sf apex run test --synchronous --code-coverage'
alias sfopen='sf org open'
alias sflog='sf apex tail log --color'

Combined with shell tab completion (sf --completion), the CLI becomes almost conversational.

💡 Pro Tip

Run sf --completion and follow the instructions to install tab completion for your shell. After setup, pressing Tab after sf shows all available command groups, and after sf apex shows all apex subcommands. This eliminates the need to memorize exact command names.


Which of these commands was new to you? And what commands or workflows are missing from this list that you use daily? Drop a comment — I’m always looking for CLI tricks I haven’t discovered yet.


What does the --synchronous flag do when running sf apex run test?
What is the purpose of sf project deploy start --dry-run?

How did this article make you feel?

Comments

Salesforce Tip

🎉

You finished this article!

What to read next

Contents