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
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.
2. Open an Org (with Deep Link)
# 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/viewThis 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 --verboseOutput 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 --verboseUse --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-prompt6. Authenticate to a New Org
Browser OAuth
sf org login web --alias prod-org --instance-url https://login.salesforce.comJWT for CI
sf org login jwt \
--client-id $CONSUMER_KEY \
--jwt-key-file ./server.key \
--username $SF_USERNAME \
--alias ci-org7. Set a Default Org
sf config set target-org myproject-dev
sf config set target-dev-hub my-devhub8. List Config Values
sf config listSource 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__c10. Pull Changes from Scratch Org
sf project retrieve start --source-dir force-app11. Check Source Status
sf source statusColour-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 stagingNote: 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 productionIf 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 manifest16. Retrieve Using a Manifest
sf project retrieve start \
--manifest manifest/package.xml \
--target-org productionData 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 1019. Bulk Delete
sf data delete bulk \
--file data/ids-to-delete.csv \
--sobject Lead \
--wait 10The 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/seed21. Import a Data Tree
sf data import tree \
--plan data/seed/Account-Case-plan.json \
--target-org myproject-dev22. Create a Single Record
sf data create record \
--sobject Account \
--values "Name='Forcenaut Test' Type='Prospect' AnnualRevenue=500000"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 run24. Run Apex Tests
All Local Tests (CI)
sf apex run test \
--synchronous \
--result-format human \
--code-coverage \
--output-dir test-resultsSpecific Test Class
sf apex run test \
--tests AccountServiceTest \
--synchronous--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 FINESTThis 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 Account28. Generate an Apex Class
sf apex generate class --name AccountService --output-dir force-app/main/default/classesCI 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 list30. Generate a Project Scaffold
sf project generate \
--name my-new-project \
--default-package-dir force-app \
--manifestMy 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.
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.
How did this article make you feel?
Comments
Salesforce Tip