Skip to Content
CLISmart Deploy

Smart Deploy

sfdt deploy --smart deploys only the metadata that changed between two git refs, picks the minimal safe Apex test level, honors overwrite protection, and runs a self-contained, non-interactive sf project deploy (no archive/commit side effects).

sfdt deploy --smart --dry-run # validate the delta (recommended in CI) sfdt deploy --smart --delta-base main # delta vs main sfdt deploy --smart --delta-base origin/main --delta-head HEAD --org uat sfdt deploy --smart --prod # treat target as production sfdt deploy --smart --ai-fix # AI analysis on failure sfdt deploy --smart --pr-comment # decorate the PR with the result

How it works

  1. Delta — computes changed metadata between --delta-base (default main, or deployment.smart.deltaBase) and --delta-head (default HEAD) using the same engine as sfdt manifest. Additive and destructive changes are separated automatically.
  2. Overwrite protection — members listed in package-no-overwrite.xml (configurable; * wildcard supported) are removed from the deploy so they’re never overwritten.
  3. Smart test selection:
    • Production (or --prod/assumeProd) → RunLocalTests, never downgraded.
    • No impacting metadata changed (Apex/triggers/flows) → NoTestRun.
    • Only Apex test classes changed → RunSpecifiedTests (those tests).
    • Any other impacting change → RunLocalTests.
    • When RunSpecifiedTests is chosen, the selection is widened by Spring ‘26 @IsTest annotations: test classes whose @IsTest(testFor='Type:Name') targets a changed component, plus every @IsTest(critical=true) class, are included automatically (sources are comment/string-sanitized first, so commented-out annotations don’t count).
    • On a non-production org with sourceApiVersion ≥ 66, deployment.smart.useRelevantTests (default false) opts into Salesforce’s beta RunRelevantTests instead of the RunLocalTests fallback. Production deploys are never auto-downgraded.
  4. Executesf project deploy validate (with --dry-run) or sf project deploy start, including --post-destructive-changes when needed.

Agentforce metadata is delta-aware. The manifest engine recognises Agentforce / Einstein agent types — Bot, BotVersion (member Bot.Version), GenAiPlanner, GenAiPlannerBundle, GenAiPlugin, GenAiFunction, GenAiPromptTemplate, AiEvaluationDefinition, and AiAuthoringBundle (the Agent Script authoring bundle). Previously these changes mapped to UNKNOWN and were silently dropped from deploy --smart deltas and sfdt manifest output.

Options

FlagNotes
--smartEnable smart delta deploy
--delta-base <ref> / --delta-head <ref>Git refs to diff (defaults: config/mainHEAD)
--overwrite-manifest <path>Path to package-no-overwrite.xml (overrides config)
--prodTreat the target as production (never downgrade tests)
--dry-runValidate only (no changes applied)
--ai-depsRun AI dependency cleanup on the computed delta first
--ai-fixOn failure, run AI deploy-error analysis (or the auto-fix loop, below)
--max-turns <n>Auto-fix iteration cap (overrides ai.agent.maxTurns)
--pr-commentPost the delta + outcome to the current PR (via gh)
--notifyDispatch deploy-success / deploy-failure through configured notification channels after the run (see below)
--agentNon-interactive mode (AI prompts never block on input)

Configuration

{ "deployment": { "smart": { "enabled": false, "deltaBase": "main", "noOverwriteManifest": "manifest/package-no-overwrite.xml", "impactingTypes": ["ApexClass", "ApexTrigger", "Flow"], "downgradeTestsOnNonProd": true, "useRelevantTests": false, "assumeProd": false } } }

useRelevantTests opts non-production orgs on API ≥ 66 into Salesforce’s beta RunRelevantTests (the org analyzes the payload and runs only the relevant tests) in place of the RunLocalTests fallback. It’s beta — a known sf CLI issue  can cause deploy validate to run zero tests with this level, so verify with --json output.

Notifications

sfdt deploy --smart --notify dispatches deploy-success / deploy-failure through the configured notification channels after the run (previously --notify was ignored with a warning in smart mode — it only worked on the standard manifest deploy). The notification includes the delta refs, additive/destructive counts, and test level; validate-only runs say “Validation (check-only)”. When no channels are configured it warns instead of failing.

AI deploy-error resolution & auto-fix loop

--ai-fix captures the failure output and runs the editable deploy-error prompt to explain the failure and suggest fixes (read-only).

When ai.agent.enabled and ai.agent.allowWrite are set (CLI providers only — the http provider can’t run tools), --ai-fix instead runs a bounded coding-agent auto-fix loop: the agent edits the repo, re-validates via a dry-run each turn, and stops on success or after maxTurns. It never deploys, the failure text is redacted before prompting, and everything defaults off.

{ "ai": { "agent": { "enabled": false, "maxTurns": 3, "allowWrite": false } } }

Delta deployments are git-diff based and don’t automatically pull in parent metadata (e.g. a changed field without its object). Use --ai-deps for an AI dependency pass, or maintain package-no-overwrite.xml and review the computed delta in --dry-run first.

See Retrofit & PR Comments for promoting org changes through smart-deploy, and CI/CD Integration for the generated PR validation pipeline.

Last updated on