Expert guidance for Salesforce CLI (sf) development deployments. Use this skill when deploying code during development, testing changes in sandboxes/scratch orgs, or when the user mentions sf CLI, deployments, or org operations. Focused on iterative development workflow.
Resources
1Install
npx skillscat add david-sfdev/claude-sf-skills/sf-cli-deployment Install via the SkillsCat registry.
This skill provides guidance on using the modern Salesforce CLI (`sf`) for development deployments to sandboxes and scratch orgs. It addresses common mistakes like using `deploy start` to check status and explains the correct commands for starting, monitoring, resuming, and canceling deployments. Developers should use it when iterating on Salesforce code changes that need to be deployed to non-production environments.
Salesforce CLI Development Deployment Guide
Core Principles
CRITICAL: Use the modern sf CLI (not legacy sfdx) for all Salesforce operations. This skill focuses on development deployments for iterative coding workflows, not production migrations or CI/CD pipelines.
Understanding Deployment Commands
❌ CRITICAL MISTAKE TO AVOID
NEVER use deploy start to check deployment status!
# ❌ WRONG - Starting new deployment when you meant to check status
sf project deploy start --source-dir force-app
# This starts a NEW deployment, doesn't check existing one!
# ✅ CORRECT - Check status of existing deployment
sf project deploy report --job-id <deployment-id>
# ✅ CORRECT - Resume waiting for existing deployment
sf project deploy resume --job-id <deployment-id> --wait 30Deployment Command Breakdown
Starting a deployment:
# Deploy and get deployment ID
sf project deploy start --source-dir force-app
# Returns:
# Deploying... ID: 0Af1234567890ABCD
# Status: InProgressChecking deployment status:
# Use the deployment ID to check status
sf project deploy report --job-id 0Af1234567890ABCD
# Shows current status: InProgress, Succeeded, FailedWaiting for completion:
# Resume waiting for deployment to complete
sf project deploy resume --job-id 0Af1234567890ABCD --wait 30
# Waits up to 30 minutes for completionCanceling a deployment:
# Cancel long-running deployment if needed
sf project deploy cancel --job-id 0Af1234567890ABCD
# Use when deployment is taking too long or was started by mistakeModern sf CLI Commands
Always use sf (not legacy sfdx):
# ✅ CORRECT - Modern sf CLI
sf project deploy start --source-dir force-app
sf org login web --alias mydev
sf data query --query "SELECT Id, Name FROM Account"
sf org open
# ❌ WRONG - Legacy sfdx (deprecated)
sfdx force:source:deploy -p force-app
sfdx force:auth:web:login -a mydevDevelopment Deployment Workflows
Quick Iteration Loop (LWC, Visualforce, Aura)
For front-end components that need testing in the org:
# 1. Deploy changes
sf project deploy start --source-dir force-app/main/default/lwc/myComponent
# 2. Open org to test
sf org open --target-org mydev
# 3. Test your changes in browser
# 4. Make adjustments and repeatNo tests needed - Front-end components don't require Apex tests.
Apex Deployment with Test Options
When deploying Apex classes or triggers, ASK the user about testing:
Prompt: "Would you like to run tests with this Apex deployment?"
Option 1: No tests (fastest - 1-2 minutes)
sf project deploy start \
--source-dir force-app \
--test-level NoTestRun
# Best for: rapid iteration, syntax fixes, development sandboxesOption 2: Specific test classes (moderate - 2-10 minutes)
sf project deploy start \
--source-dir force-app \
--test-level RunSpecifiedTests \
--tests AccountServiceTest \
--tests ContactTriggerHandlerTest
# Best for: testing specific functionality you changedOption 3: All local tests (slow - 15-60+ minutes)
⚠️ WARN USER FIRST:
Running all local tests can take a long time (15-60+ minutes depending on org size).
Continue with RunLocalTests? (yes/no)If user confirms:
# Start deployment with all tests
DEPLOY_ID=$(sf project deploy start \
--source-dir force-app \
--test-level RunLocalTests \
--json | jq -r '.result.id')
echo "Deployment ID: $DEPLOY_ID"
echo "⏳ Running all tests... this may take 15-60+ minutes"
echo "💡 To cancel: sf project deploy cancel --job-id $DEPLOY_ID"
# Monitor progress
sf project deploy resume --job-id $DEPLOY_ID --wait 60Monitoring Long-Running Deployments
For deployments that take time:
# Check status without waiting
sf project deploy report --job-id <deployment-id>
# Resume waiting (if interrupted)
sf project deploy resume --job-id <deployment-id> --wait 30
# Cancel if taking too long
sf project deploy cancel --job-id <deployment-id>Status indicators:
InProgress- Still runningSucceeded- Completed successfullyFailed- Deployment failedCanceled- User canceled deployment
Deployment Scenarios
Deploy Specific Components
# Single LWC component
sf project deploy start \
--source-dir force-app/main/default/lwc/accountList
# Single Apex class and its test
sf project deploy start \
--metadata ApexClass:AccountService \
--metadata ApexClass:AccountServiceTest
# Custom object with fields
sf project deploy start \
--source-dir force-app/main/default/objects/CustomObject__c
# Multiple metadata types
sf project deploy start \
--metadata ApexClass:AccountService \
--metadata ApexTrigger:AccountTrigger \
--test-level NoTestRunDeploy Entire Project
# Deploy all source
sf project deploy start --source-dir force-app
# Deploy with test validation
sf project deploy start \
--source-dir force-app \
--test-level RunLocalTestsPreview What Will Deploy
# See what would be deployed (dry run)
sf project deploy start --source-dir force-app --dry-run
# Preview changes
sf project deploy preview --source-dir force-appOrg Management
Authentication
# Login to sandbox (interactive)
sf org login web --alias mydev --instance-url https://test.salesforce.com
# Login to production
sf org login web --alias prod --instance-url https://login.salesforce.com
# Login to custom domain
sf org login web --alias myorg --instance-url https://mycompany.my.salesforce.com
# List authenticated orgs
sf org list
# Open org in browser
sf org open --target-org mydev
# Set default org
sf config set target-org=mydevScratch Orgs
# Create scratch org
sf org create scratch \
--definition-file config/project-scratch-def.json \
--alias scratch-dev \
--duration-days 7 \
--set-default
# Push source to scratch org (source tracking)
sf project deploy start --source-dir force-app
# Open scratch org
sf org open
# Delete scratch org
sf org delete scratch --target-org scratch-dev --no-promptRunning Tests Separately
After deploying without tests, run tests independently:
# Run specific test class
sf apex run test \
--tests AccountServiceTest \
--result-format human \
--code-coverage
# Run multiple test classes
sf apex run test \
--tests AccountServiceTest,ContactHandlerTest \
--result-format human
# Run all tests in org
sf apex run test \
--test-level RunLocalTests \
--result-format human \
--code-coverage \
--wait 60
# Get test results with coverage
sf apex get test \
--test-run-id <test-run-id> \
--code-coverage \
--result-format humanPost-Deployment Workflow
After Successful Deployment
When deployment succeeds, guide user:
✅ Deployment successful!
Next steps:
1. Test your changes: sf org open --target-org mydev
2. [If git detected] Commit your changes? (yes/no)If user wants to commit (and git is available):
# Check git status
git status
# Stage changes
git add force-app/
# Commit
git commit -m "Description of changes"
# Push (optional)
git push origin feature-branchRetrieving Metadata from Org
Pull changes from org to local project:
# Retrieve specific metadata
sf project retrieve start --metadata ApexClass:AccountService
# Retrieve by source directory
sf project retrieve start --source-dir force-app
# Retrieve using manifest
sf project retrieve start --manifest package.xml
# Preview what would be retrieved
sf project retrieve previewData Operations
Query Data
# Simple query
sf data query --query "SELECT Id, Name FROM Account LIMIT 10"
# Query to file
sf data query \
--query "SELECT Id, Name, Industry FROM Account" \
--result-format csv > accounts.csv
# Use SOQL file
sf data query --file query.soqlImport/Export Data
# Export with related records
sf data export tree \
--query "SELECT Id, Name, (SELECT Id, FirstName FROM Contacts) FROM Account" \
--output-dir data \
--plan
# Import data
sf data import tree --plan data/plan.json
# Import CSV
sf data import csv --file accounts.csv --sobject AccountCommon Development Patterns
LWC Development Loop
# 1. Make changes to LWC component
# (edit HTML, JS, CSS files)
# 2. Deploy component
sf project deploy start \
--source-dir force-app/main/default/lwc/myComponent
# 3. Open org and test
sf org open
# 4. Check browser console for errors
# 5. Make fixes and repeatApex Development Loop
# 1. Write/modify Apex class and test
# 2. Deploy without tests (fast iteration)
sf project deploy start \
--metadata ApexClass:MyClass \
--metadata ApexClass:MyClassTest \
--test-level NoTestRun
# 3. Run tests separately
sf apex run test \
--tests MyClassTest \
--result-format human \
--code-coverage
# 4. Review results and iterateCustom Object Changes
# 1. Modify object fields, validation rules, etc.
# 2. Deploy object
sf project deploy start \
--source-dir force-app/main/default/objects/MyObject__c
# 3. Test in org
sf org open
# 4. Verify fields, page layouts, etc.Troubleshooting Development Deployments
Deployment Failed
# Get detailed error report
sf project deploy report --job-id <deployment-id> --verbose
# Check for common issues:
# - Missing dependencies (deploy parent objects first)
# - Field references that don't exist
# - Validation rule conflicts
# - Test failures (if running tests)Test Failures
# View test failure details
sf project deploy report --job-id <deployment-id>
# Run failed test individually
sf apex run test \
--tests FailedTestClass \
--result-format human
# Check test coverage
sf apex get test --code-coverage --result-format humanDependency Issues
# Deploy in order:
# 1. Objects
sf project deploy start --metadata CustomObject
# 2. Fields
sf project deploy start --metadata CustomField
# 3. Apex
sf project deploy start --metadata ApexClass
# 4. Triggers
sf project deploy start --metadata ApexTriggerLong-Running Deployment
# Check progress
sf project deploy report --job-id <deployment-id>
# If stuck or taking too long, cancel
sf project deploy cancel --job-id <deployment-id>
# Then deploy without tests or with fewer tests
sf project deploy start \
--source-dir force-app \
--test-level NoTestRunKey Development Reminders
- Use
deploy reportto check status - Never usedeploy startfor status checks - Cancel long deployments - Use
deploy cancelif needed - NoTestRun for iteration - Skip tests during rapid development
- Test separately - Run tests after deployment for faster feedback
- Open org to test - Use
sf org openafter deployment - Deploy specific components - Faster than deploying entire project
- Preview before deploy - Use
--dry-runto check what will deploy - No git requirements - Commit only when ready, not before deployment
- Warn for long tests - Alert user before running all local tests
- Monitor progress - Check status periodically for long deployments
Time Estimates
- LWC/Visualforce deployment: 30 seconds - 2 minutes
- Apex without tests: 1-2 minutes
- Apex with specific tests: 2-10 minutes
- Apex with all local tests: 15-60+ minutes (warn user!)
- Large metadata deployments: 5-15 minutes
Quick Command Reference
Deploy
sf project deploy start --source-dir <dir>- Deploy sourcesf project deploy start --metadata <type>:<name>- Deploy specific metadatasf project deploy start --dry-run- Preview deploymentsf project deploy report --job-id <id>- Check statussf project deploy resume --job-id <id>- Resume waitingsf project deploy cancel --job-id <id>- Cancel deployment
Org
sf org login web --alias <name>- Login to orgsf org open- Open org in browsersf org list- List orgssf org display- Show org info
Test
sf apex run test --tests <class>- Run testssf apex get test --code-coverage- Get coverage
Data
sf data query --query <soql>- Query datasf org open- Open org to test UI changes
Focus: Development iteration and testing
NOT included: Production deployments, CI/CD, environment migrations
Created for: Claude Code
Last Updated: November 2025