Comprehensive Salesforce DevOps automation using sf CLI v2. Handles deployments, CI/CD pipelines, scratch orgs, and metadata management with built-in validation and error handling.
Inherits all available tools
Additional assets for this skill
This skill inherits all available tools. When active, it can use any tool Claude has access to.
Expert Salesforce DevOps engineer specializing in deployment automation, CI/CD pipelines, and metadata management using Salesforce CLI (sf v2).
sf-metadata → sf-flow → sf-deploy → sf-data (you are here: sf-deploy)
See shared/docs/orchestration.md (project root) for details.
Deploy order WITHIN sf-deploy: Objects/Fields → Permission Sets → Flows → Apex → Activate Flows
Why: Flows need fields, users need FLS, triggers may need active flows.
# CORRECT: Validate before deploying
sf project deploy start --dry-run --source-dir force-app --target-org alias
sf project deploy start --source-dir force-app --target-org alias
# WRONG: Deploying without validation
sf project deploy start --source-dir force-app --target-org alias # Risky!
Common Error:
Error: In field: field - no CustomObject named ObjectName__c found
Solution: Deploy objects first, THEN permission sets referencing them.
Flows deploy as Draft by default. Activation steps:
<status>Draft</status>sf project deploy report --job-id [id]Draft → ActiveWhy? Draft lets you verify before activating; if activation fails, flow still exists.
Common Errors: "Flow is invalid" (deploy objects first) | "Insufficient permissions" (check Manage Flow) | "Version conflict" (deactivate old version)
⚠️ Deployed fields may be INVISIBLE without FLS!
After deploying custom objects/fields:
sf org assign permset --name PermSetName --target-org aliasThis skill uses sf CLI (v2.x), NOT legacy sfdx (v1.x)
| Legacy sfdx (v1) | Modern sf (v2) |
|---|---|
--checkonly / --check-only | --dry-run |
sfdx force:source:deploy | sf project deploy start |
Before deployment, verify:
sf --version # Requires v2.x
sf org list # Check authenticated orgs
test -f sfdx-project.json # Valid SFDX project
Gather via AskUserQuestion: Target org, deployment scope, validation requirements, rollback strategy.
Analyze:
sfdx-project.json for package directories**/force-app/**/*.{cls,trigger,xml,js,html,css}TodoWrite tasks: Validate auth, Pre-tests, Deploy, Monitor, Post-tests, Verify
sf org display --target-org <alias> # Check connection
sf apex test run --test-level RunLocalTests --target-org <alias> --wait 10 # Local tests
sf project deploy start --dry-run --test-level RunLocalTests --target-org <alias> --wait 30 # Validate
Commands by scope:
# Full metadata
sf project deploy start --target-org <alias> --wait 30
# Specific components
sf project deploy start --source-dir force-app/main/default/classes --target-org <alias>
# Manifest-based
sf project deploy start --manifest manifest/package.xml --target-org <alias> --test-level RunLocalTests --wait 30
# Quick deploy (after validation)
sf project deploy quick --job-id <validation-job-id> --target-org <alias>
Handle failures: Parse errors, identify failed components, suggest fixes.
sf project deploy report --job-id <job-id> --target-org <alias>
Verify components, run smoke tests, check coverage.
Provide summary with: deployed components, test results, coverage metrics, next steps.
See examples/deployment-report-template.md for output format.
Deployment Variants: Production (full + RunAllTests), Hotfix (targeted + RunLocalTests), CI/CD (scripted + gates), Scratch (push source).
Deploy: sf project deploy start [--dry-run] [--source-dir <path>] [--manifest <xml>] [--test-level <level>]
Quick: sf project deploy quick --job-id <id> | Status: sf project deploy report
Test: sf apex test run --test-level RunLocalTests | Coverage: sf apex get test --code-coverage
Org: sf org list | sf org display | sf org create scratch | sf org open
Metadata: sf project retrieve start | sf org list metadata --metadata-type <type>
| Error | Cause | Solution |
|---|---|---|
| FIELD_CUSTOM_VALIDATION_EXCEPTION | Validation rule blocking | Deactivate rules or use valid test data |
| INVALID_CROSS_REFERENCE_KEY | Missing dependency | Include dependencies in deploy |
| CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY | Trigger/validation error | Review trigger logic, check recursion |
| TEST_FAILURE | Test class failure | Fix test or code under test |
| INSUFFICIENT_ACCESS | Permission issue | Verify user permissions, FLS |
| Error | Cause | Solution |
|---|---|---|
| "Element X is duplicated" | Elements not alphabetically ordered | Reorder Flow XML elements |
| "Element bulkSupport invalid" | Deprecated element (API 60.0+) | Remove <bulkSupport> |
| "Error parsing file" | Malformed XML | Validate XML syntax |
--dry-run for productionpackage.xml for controlled deploymentsStandard pipeline workflow:
See examples/deployment-workflows.md for scripts.
Before deploying, verify these prerequisites from other skills:
| Dependency | Check Command | Required For |
|---|---|---|
| TAF Package | sf package installed list --target-org alias | TAF trigger pattern (sf-apex) |
| Custom Objects/Fields | sf sobject describe --sobject ObjectName --target-org alias | Apex/Flow field references |
| Trigger_Action__mdt | Check Setup → Custom Metadata Types | TAF trigger execution |
| Queues | sf data query --query "SELECT Id,Name FROM Group WHERE Type='Queue'" | Flow queue assignments |
| Permission Sets | sf org list metadata --metadata-type PermissionSet | FLS for custom fields |
Common Cross-Skill Issues:
| Error Message | Missing Dependency | Solution |
|---|---|---|
Invalid type: MetadataTriggerHandler | TAF Package | Install apex-trigger-actions package |
Field does not exist: Field__c | Custom Field or FLS | Deploy field or create Permission Set |
No such column 'Field__c' | Field-Level Security | Assign Permission Set to running user |
SObject type 'Object__c' not supported | Custom Object | Deploy object via sf-metadata first |
Queue 'QueueName' not found | Queue Metadata | Deploy queue via sf-metadata first |
Complete DevOps guide: See docs/agent-deployment-guide.md for comprehensive agent deployment documentation.
| Metadata Type | Description |
|---|---|
Bot | Top-level chatbot definition |
BotVersion | Version configuration |
GenAiPlannerBundle | Reasoning engine (LLM config) |
GenAiPlugin | Topic definition |
GenAiFunction | Action definition |
The Agent pseudo type syncs all agent components at once:
# Retrieve agent + all dependencies from org
sf project retrieve start --metadata Agent:[AgentName] --target-org [alias]
# Deploy agent metadata to org
sf project deploy start --metadata Agent:[AgentName] --target-org [alias]
# Activate agent (makes available to users)
sf agent activate --api-name [AgentName] --target-org [alias]
# Deactivate agent (REQUIRED before making changes)
sf agent deactivate --api-name [AgentName] --target-org [alias]
# Preview agent (simulated mode - safe testing)
sf agent preview --api-name [AgentName] --target-org [alias]
# Preview agent (live mode - real Apex/Flows)
sf agent preview --api-name [AgentName] --use-live-actions --client-app [App] --target-org [alias]
# Validate Agent Script syntax
sf afdx agent validate --api-name [AgentName] --target-org [alias]
# 1. Deploy Apex classes (if any)
sf project deploy start --metadata ApexClass --target-org [alias]
# 2. Deploy Flows
sf project deploy start --metadata Flow --target-org [alias]
# 3. Validate Agent Script
sf afdx agent validate --api-name [AgentName] --target-org [alias]
# 4. Publish agent
sf agent publish --api-name [AgentName] --target-org [alias]
# 5. Preview (simulated mode)
sf agent preview --api-name [AgentName] --target-org [alias]
# 6. Activate
sf agent activate --api-name [AgentName] --target-org [alias]
⚠️ Deactivation Required: You MUST deactivate an agent before modifying topics, actions, or system instructions.
# 1. Deactivate
sf agent deactivate --api-name [AgentName] --target-org [alias]
# 2. Make changes to Agent Script
# 3. Re-publish
sf agent publish --api-name [AgentName] --target-org [alias]
# 4. Re-activate
sf agent activate --api-name [AgentName] --target-org [alias]
# 1. Retrieve from source org
sf project retrieve start --metadata Agent:[AgentName] --target-org source-org
# 2. Deploy dependencies to target org first
sf project deploy start --metadata ApexClass,Flow --target-org target-org
# 3. Deploy agent metadata
sf project deploy start --metadata Agent:[AgentName] --target-org target-org
# 4. Publish agent in target org
sf agent publish --api-name [AgentName] --target-org target-org
# 5. Activate in target org
sf agent activate --api-name [AgentName] --target-org target-org
| Command | Description |
|---|---|
sf agent publish --api-name X | Publish authoring bundle |
sf agent activate --api-name X | Activate published agent |
sf agent deactivate --api-name X | Deactivate agent for changes |
sf agent preview --api-name X | Preview agent behavior |
sf afdx agent validate --api-name X | Validate Agent Script syntax |
sf org open agent --api-name X | Open in Agentforce Builder |
sf project retrieve start --metadata Agent:X | Retrieve agent + components |
sf project deploy start --metadata Agent:X | Deploy agent metadata |
Reusable multi-step deployment script: examples/deploy.sh
Deploys in order: Objects → Permission Sets → Apex (with tests) → Flows (Draft)
Auto-generate package.xml from source directory:
# Generate from source
sf project generate manifest --source-dir force-app --name manifest/package.xml
# Generate for specific metadata types
sf project generate manifest \
--metadata CustomObject:Account \
--metadata ApexClass \
--metadata Flow \
--name manifest/package.xml
# Deploy using manifest
sf project deploy start --manifest manifest/package.xml --target-org alias
When to use manifest vs source-dir:
| Scenario | Use | Command |
|---|---|---|
| Deploy everything | --source-dir | sf project deploy start --source-dir force-app |
| Deploy specific components | --manifest | sf project deploy start --manifest package.xml |
| CI/CD pipelines | --manifest | Controlled, reproducible deployments |
| Development iteration | --source-dir | Quick local changes |
sf (v2) with modern flag syntax--wait to monitor; most deploys are asyncMIT License. See LICENSE file. Copyright (c) 2024-2025 Jag Valaiyapathy