| name | salesforce-cli |
| description | Safety-first Salesforce CLI skill wrapping `sf` (v2). This skill should be used when performing Salesforce operations — SOQL/SOSL queries, metadata deploy/retrieve, data import/export, Apex execution, org management, auth, and platform events. Enforces risk classification w/ mandatory confirmation for all write/destructive operations. Integrates w/ Salesforce MCP servers and file-converter skill for format conversion.
|
| author | George Khananaev |
Salesforce CLI
Safety-first wrapper for Salesforce CLI (sf v2). Every command is classified by risk level before execution. NEVER modify Salesforce data or metadata without explicit user permission.
When to Use
- User asks to query Salesforce data (SOQL/SOSL)
- User asks to deploy or retrieve metadata
- User asks to export/import data (CSV, JSON, tree)
- User asks to execute Apex code
- User asks to manage orgs (scratch, sandbox, production)
- User asks to authenticate w/ Salesforce
- User asks to work w/ platform events or CDC
- User asks to manage packages or permissions
- User asks to interact w/ Salesforce APIs (REST, Bulk, Tooling)
Prerequisites
- Install:
npm install -g @salesforce/cli or brew install sf
- Auth:
sf org login web (interactive) or sf org login jwt (CI/CD)
- Verify:
sf --version (requires v2.x)
- Default org:
sf config set target-org <alias>
Safety Model
Every sf command falls into one of four risk tiers. Default mode is read-only.
| Tier | Action Required | Examples |
|---|
| Safe | Execute immediately | sf org list, sf data query, sf project retrieve preview |
| Write | AskUserQuestion BEFORE executing | sf data create record, sf project deploy start --dry-run |
| Destructive | AskUserQuestion w/ explicit consequences | sf project deploy start, sf data delete, sf org delete |
| Forbidden | Multi-step validation, NEVER auto-confirm | Bulk delete in production, mass data wipe, production org delete |
See references/safety-rules.md for full classification and confirmation templates.
Production Guardrails
Detect org type before ANY write operation:
sf org display --target-org <alias> --json
Check instanceUrl and isScratch/isSandbox fields:
login.salesforce.com or no sandbox/scratch flag → PRODUCTION → extra confirmation required
test.salesforce.com or isSandbox: true → Sandbox
isScratch: true → Scratch org
For production orgs: ALL write operations require AskUserQuestion w/ org alias typed confirmation.
Fail-Safe Principles
- If org type detection fails → BLOCK all operations (never assume non-production)
- If unsure about tier → classify HIGHER (Write → Destructive, Destructive → Forbidden)
- Bulk operations always require row count preview before confirmation
- Deploys with
destructiveChanges.xml are FORBIDDEN in production via scripts
--test-level NoTestRun is BLOCKED for production deployments
- Apex code must be shown to user BEFORE execution (never run sight-unseen)
- Permission set changes require warning about privilege escalation / lockout risks
- Field/object deletions in deploys require warning about cascade impacts (reports, flows, integrations)
- Sandbox refresh requires explicit acknowledgment that ALL data will be overwritten
- PII fields in queries trigger a warning (Email, Phone, Birthdate, SSN, etc.)
Decision Flow
Command received
→ Detect target org type (prod/sandbox/scratch)
→ Classify risk tier (see Quick Reference)
→ Safe? Execute immediately
→ Write? AskUserQuestion → wait for answer → execute or cancel
→ Destructive? AskUserQuestion w/ consequences → wait → execute or cancel
→ Forbidden? Warn → require typed confirmation → final confirm → execute or cancel
→ PRODUCTION? Add extra confirmation step regardless of tier
Quick Reference
Safe (read-only, execute immediately)
| Command | Description |
|---|
sf org list | List authorized orgs |
sf org list --all | Include expired scratch orgs |
sf org display | Display org info |
sf org open | Open org in browser |
sf config list | List config values |
sf config get target-org | Get default org |
sf alias list | List aliases |
sf data query --query "..." | SOQL query (w/ mandatory LIMIT) |
sf data search --query "..." | SOSL search |
sf data get record | Get single record |
sf project retrieve preview | Preview what would be retrieved |
sf project deploy preview | Preview what would be deployed |
sf apex list log | List debug logs |
sf apex get log | Get debug log content |
sf apex tail log | Tail logs in real-time |
sf api request rest (GET) | Read-only REST API calls |
sf limits api display | Display API limits |
sf sobject describe --sobject <name> | Describe object schema (fields, types) |
sf package list | List packages |
sf package version list | List package versions |
sf plugins list | List installed plugins |
sf doctor | Run diagnostics |
sf org list auth | List auth connections (sf auth list = legacy alias) |
Write (AskUserQuestion required)
| Command | Description |
|---|
sf data create record | Create a single record |
sf data update record | Update a single record |
sf data import tree | Import data from tree files |
sf project deploy start --dry-run | Validate deployment (no changes) |
sf project retrieve start | Retrieve metadata to local |
sf org create scratch | Create scratch org |
sf alias set | Set an alias |
sf config set | Set config value |
sf package create | Create a package |
sf package version create | Create package version |
Destructive (AskUserQuestion w/ consequences)
| Command | Description |
|---|
sf project deploy start (no dry-run) | Deploy metadata (modifies org) |
sf data delete record | Delete a single record |
sf data delete bulk | Bulk delete records |
sf data update bulk | Bulk update records — can corrupt data at scale |
sf data import bulk | Bulk import — can create thousands of duplicate records |
sf data upsert bulk | Bulk upsert — incorrect key can overwrite wrong records |
sf apex run | Execute anonymous Apex |
sf org delete scratch | Delete scratch org |
sf org delete sandbox | Delete sandbox |
sf org create sandbox | Create sandbox (long-running, uses resources) |
sf org assign permset | Assign permission set — can escalate privileges or lock users out |
sf package install | Install package — can modify schema, automation, and data |
sf package uninstall | Uninstall package |
sf org logout | Remove org auth |
sf api request rest -X POST/PUT/PATCH/DELETE | Write/delete REST API calls |
Forbidden (multi-step validation)
| Command | Description |
|---|
sf org delete targeting production | Delete production org connection |
| Bulk delete in production | Mass data deletion in production |
sf data delete bulk w/o WHERE in source query | Full-table data wipe risk |
sf project deploy start w/ destructiveChanges.xml in prod | Deploy destructive metadata changes to production |
sf project deploy start --test-level NoTestRun in prod | Skip tests in production (BLOCKED) |
sf org refresh sandbox | Refresh sandbox — overwrites ALL data and customizations |
sf org logout --all | Remove ALL org auth — can break CI/CD pipelines |
| Bulk loops w/o limits | Any loop running delete/update w/o LIMIT |
sf apex run in production w/o review | Execute unreviewed Apex in production |
| Dangerous deploy flags in prod | --ignore-conflicts, --ignore-warnings, --purge-on-delete |
SOQL/SOSL Query Safety
Mandatory rules for ALL queries:
- Always add LIMIT — Default to
LIMIT 200 if user omits
- Never use
SELECT * — Expand fields via sf sobject describe --sobject <name> or ask user
- Production queries — Require WHERE clause unless object is known to be small
- Tooling API queries — Use
--use-tooling-api flag for metadata queries
sf data query --target-org my-org \
--query "SELECT Id, Name, Industry FROM Account WHERE Industry = 'Technology' LIMIT 100"
sf data query --target-org my-org \
--query "SELECT Id, Name, (SELECT Id, FirstName FROM Contacts) FROM Account LIMIT 50"
sf data query --target-org my-org \
--query "SELECT Id, Name FROM Account LIMIT 100" \
--result-format csv --output-file accounts.csv
sf data query --target-org my-org --use-tooling-api \
--query "SELECT Id, Name FROM ApexClass WHERE Name LIKE '%Test%' LIMIT 50"
sf data search --target-org my-org \
--query "FIND {Acme} IN NAME FIELDS RETURNING Account(Id, Name LIMIT 50)"
See references/soql-sosl.md for query patterns, date literals, and aggregate examples.
Data Export/Import
Export (Safe tier — read-only)
sf data query --target-org my-org \
--query "SELECT Id, Name FROM Account LIMIT 200" \
--result-format csv --output-file accounts.csv
sf data query --target-org my-org \
--query "SELECT Id, Name FROM Account LIMIT 200" \
--json > accounts.json
sf data export tree --target-org my-org \
--query "SELECT Id, Name, (SELECT Id, FirstName FROM Contacts) FROM Account LIMIT 50" \
--output-dir ./data
sf data export bulk --target-org my-org \
--query "SELECT Id, Name FROM Account" \
--output-file accounts.csv
Import (Write/Destructive tier — confirmation required)
sf data import tree --target-org my-org --files Account.json,Contact.json
sf data import bulk --sobject Account --file accounts.csv --target-org my-org
sf data upsert bulk --sobject Account --file data.csv \
--external-id External_Id__c --target-org my-org
File-Converter Integration
Convert between formats using the file-converter skill:
python3 .claude/skills/file-converter/scripts/csv_json_yaml.py accounts.json accounts.csv
python3 .claude/skills/file-converter/scripts/csv_json_yaml.py data.csv data.json
python3 .claude/skills/file-converter/scripts/csv_json_yaml.py accounts.json accounts.yaml
sf data query --target-org my-org \
--query "SELECT Id, Name FROM Account LIMIT 200" --json > data.json
python3 .claude/skills/file-converter/scripts/csv_json_yaml.py data.json report.csv
See references/data-operations.md for bulk patterns and tree format details.
Metadata Deploy/Retrieve
Retrieve (Write tier — modifies local files)
sf project retrieve start --source-dir force-app --target-org my-org
sf project retrieve start --metadata ApexClass --target-org my-org
sf project retrieve start --manifest package.xml --target-org my-org
Deploy (Destructive tier — modifies org)
Always validate first:
sf project deploy preview --source-dir force-app --target-org my-org
sf project deploy start --source-dir force-app --target-org my-org --dry-run
sf project deploy start --source-dir force-app --target-org my-org
sf project deploy start --source-dir force-app --target-org prod-org \
--test-level RunLocalTests
Apex Execution
Always show code before running. Always confirm.
cat script.apex
sf apex run --target-org my-org --file script.apex
sf apex run test --target-org my-org --class-names MyClassTest --code-coverage
sf apex get log --target-org my-org --number 1
Org Management
Scratch Orgs
sf org create scratch --definition-file config/project-scratch-def.json \
--alias my-scratch --duration-days 7
sf org list --all
sf org delete scratch --target-org my-scratch
Sandboxes
sf org create sandbox --target-org prod-org --name dev-sandbox --alias dev-sb
sf org refresh sandbox --target-org dev-sb
sf org delete sandbox --target-org dev-sb
Authentication
sf org login web --alias my-org --set-default
sf org login web --alias my-sandbox --instance-url https://test.salesforce.com
sf org login jwt --client-id <consumer_key> --jwt-key-file server.key \
--username user@example.com --alias my-org
sf org login sfdx-url --sfdx-url-file auth.txt --alias my-org
sf org login device
sf org display --target-org my-org
sf auth list
See references/auth-flows.md for detailed setup instructions.
MCP Server Integration
Official Salesforce MCP Server (recommended)
{
"mcpServers": {
"salesforce-dx": {
"command": "npx",
"args": ["-y", "@salesforce/mcp", "--orgs", "DEFAULT_TARGET_ORG"]
}
}
}
Available toolsets: Core, Orgs, Data, Users, Metadata, Testing, Code-Analysis, LWC, Aura, Mobile, Scale Products.
Tool Detection Flow
1. Check: Are Salesforce MCP tools available? (ToolSearch "salesforce")
→ YES: Use MCP tools (structured, validated)
→ NO: Fall back to sf CLI commands
→ NO CLI: Guide user through installation
Community MCP Servers
| Server | Tools | Best For |
|---|
@salesforce/mcp (official) | 60+ | Full DX workflow, LWC, testing, metadata |
tsmztech/mcp-server-salesforce | 16 | CRUD, schema, Apex, SOSL |
advancedcommunities/salesforce-mcp-server | 36 | Apex, testing, code analysis, data export |
See references/mcp-integration.md for setup and toolset details.
Direct API Access
sf api request rest /services/data/v67.0/sobjects/Account/describe
sf api request rest /services/data/v67.0/query?q=SELECT+Id+FROM+Account+LIMIT+10
sf api request graphql --body query.graphql --target-org my-org
sf api request rest /services/data/v67.0/composite --body composite.json -X POST
Platform Events & CDC
sf data create record --sobject MyEvent__e --values "Field1__c='value'" --target-org my-org
sf apex run --target-org my-org --file subscribe_events.apex
sf data query --target-org my-org --use-tooling-api \
--query "SELECT QualifiedApiName FROM EntityDefinition WHERE IsEnabledForChangeDataCapture = true LIMIT 100"
AskUserQuestion Integration
For ALL write, destructive, and forbidden operations, use AskUserQuestion w/ tailored options.
Data Modification Example
question: "Create a new Account record in <org-alias> (<org-type>)?"
header: "SF Write"
options:
- label: "Create record"
description: "Insert the Account record with the specified field values"
- label: "Cancel"
description: "Do not create any records"
Deploy Example
question: "Deploy metadata to <org-alias> (<org-type>)? <N> components will be modified."
header: "SF Deploy"
options:
- label: "Validate only (dry-run)"
description: "Run validation without making changes"
- label: "Deploy now"
description: "Deploy and modify the target org"
- label: "Cancel"
description: "Do not deploy"
Apex Execution Example
question: "Execute the following Apex in <org-alias> (<org-type>)?\n\n<code preview>"
header: "SF Apex"
options:
- label: "Execute"
description: "Run the Apex code in the target org"
- label: "Cancel"
description: "Do not execute"
See references/safety-rules.md for all confirmation templates.
Error Handling
| Error | Cause | Fix |
|---|
sf: command not found | Not installed | npm install -g @salesforce/cli |
No default org set | No target org | sf config set target-org <alias> |
INVALID_SESSION_ID | Auth expired | sf org login web --alias <org> |
MALFORMED_QUERY | Bad SOQL syntax | Check query, verify field names |
INVALID_FIELD | Wrong field name | Use sf sobject describe --sobject <name> to check fields |
REQUEST_LIMIT_EXCEEDED | API limit hit | Check sf limits api display, wait or optimize |
DUPLICATE_VALUE | Unique constraint | Check external IDs, use upsert instead |
REQUIRED_FIELD_MISSING | Missing field | Check object requirements w/ describe |
DEPLOY_FAILED | Deploy validation error | Check error details, fix code, redeploy |
Shell Safety
- No interactive mode: Always provide explicit flags, never rely on interactive prompts
- No pagers: Pipe to
cat if output may trigger a pager: sf org list | cat
- Always specify org: Use
--target-org to prevent accidental operations on wrong org
- Quote arguments: Always quote query strings and multi-word values
- JSON output: Use
--json for programmatic parsing
- Never print tokens: Auth tokens, keys, and secrets must never appear in output
Self-Healing
sf v2 renames commands across releases. On any error: sf <topic> --help
(authoritative for the installed version) → if unclear, WebFetch
https://developer.salesforce.com/docs/atlas.en-us.sfdx_cli_reference.meta/sfdx_cli_reference/cli_reference_unified.htm
→ adjust → re-run. Never guess flags twice; surface renamed commands w/ the doc link.
Integration
Pairs with:
- file-converter — Convert Salesforce exports between CSV, JSON, YAML, XML formats
- github-cli — Commit and PR Salesforce metadata changes
- code-quality — Review Apex code before deployment
- token-optimizer — Compress large query results or metadata descriptions