@sfdt/cli
v0.27.0
Published
Salesforce DevTools — Production-grade CLI for Salesforce DX deployment, testing, quality analysis, and release management
Maintainers
Readme
SFDT — Salesforce DevTools
Org health and tech debt for Salesforce — see the org you actually have, then change it safely.
@sfdt/cli is the command-line core of the SFDT suite. It diagnoses org health and technical
debt (audit, monitoring, drift, dependencies, permissions, coverage), groups that evidence
under the AI-Readiness Index, and ships changes with preflight, testing and rollback. Pairs with
the SFDT Chrome extension and the VS Code extension.
📖 Read the docs at sfdt.dev → · npm · Usage guide
Features
- Org health & tech-debt diagnosis —
sfdt audit(17 checks: access sprawl, MFA, unused and unreferenced Apex, inactive automation, deprecated API versions, connected apps, missing field descriptions, setup audit-trail anomalies),sfdt monitor(limits, errors, Security Health Check, deploy history, legacy API use), plusdependencies,permissions,packages,fieldandcoverage - AI-Readiness Index evidence pack —
sfdt audit --indexgroups every check under the eight Index dimensions (automation sprawl, dependency risk, documentation, permissions, dead metadata, data quality, change safety, AI-groundability) and writes a Markdown pack for an assessment. The same grouping appears in the Chrome extension's Org Health panel. It is evidence for a person scoring the org, not a score. - Interactive deployment workflows with preflight validation, tagging, and PR creation
- Automated release manifest generation from git diffs
- Parallel Apex test execution with configurable coverage enforcement
- Code and test quality analysis with AI-powered fix plans
- Pre-release validation checklist (
sfdt preflight) - Deployment rollback with pre-rollback org state backup
- Post-deploy smoke testing
- Org metadata drift detection
- Multi-package project support — scope manifests and deploys to individual
packageDirectorieswith--packageand--name; deploy source folders directly with--source-dir - Smart package.xml generator from git diffs with AI dependency cleanup (
sfdt manifest) - AI deployment error log interpreter with heuristic fallback for offline use (
sfdt explain) - AI-generated PR descriptions and Slack messages from deployment changes (
sfdt pr-description) - AI-powered code review, test failure analysis, changelog generation, and release notes — optional, works with Claude, Gemini, or OpenAI
- Org metadata comparison — diff two orgs or local source vs org with optional package.xml export (
sfdt compare) - Local web dashboard for test results, preflight, drift monitoring, and org comparison (
sfdt ui) - Smart delta deployments — minimal git-delta package with overwrite protection, automatic test-level selection, optional AI / coding-agent auto-fix (
sfdt deploy --smart) - Scheduled org monitoring & backup —
sfdt monitor --backup, notification digests, and CI monitor templates - CI/CD pipeline templates for GitHub, GitLab, Azure, and Bitbucket (
sfdt ci init— monitor, PR validation, approval-gated release, scratch-org CI), plus a published GitHub Action (uses: scoobydrew83/sfdt@v0); PR decoration (sfdt pr comment) and cross-org retrofit (sfdt retrofit) - Multi-channel notifications — Slack, MS Teams, Google Chat, email, webhook, and Grafana Loki, with optional AI executive-summary digests (
sfdt notify) - Plugin architecture — extend sfdt with
sfdt-plugin-*npm packages or local.sfdt/plugins/scripts, plus a Salesforce CLI plugin exposing every command assf sfdt <command>(sf plugins install @sfdt/plugin) - Works with any Salesforce DX project — no project-specific values hardcoded
For in-depth command walkthroughs and workflow examples, see docs/USAGE.md.
Repository layout
@sfdt/cli is one of six workspaces in this monorepo:
| Workspace | What it is | Status |
|---|---|---|
| @sfdt/cli (/src, /bin, /scripts) | The npm CLI documented below. | Published to npm |
| @sfdt/extension (/extension) | Chrome extension for Salesforce Flow Builder + Setup productivity. Talks to the CLI via the local bridge for deploy / rollback / quality / AI features. See extension/README.md and extension/PRIVACY.md. | Published to the Chrome Web Store |
| sfdt-devtools (/vscode) | VS Code extension — a CLI-backed command center (Org Health sidebar, command palette, CodeLens, diagnostics, embedded dashboard); it drives the sfdt binary and reimplements no logic. See vscode/README.md. | Published to the VS Code Marketplace |
| @sfdt/host (/host) | Native messaging host used as the extension's fallback transport when sfdt ui isn't running. Installed with sfdt extension install-host. | Bundled with CLI |
| @sfdt/flow-core (/packages/flow-core) | Shared TypeScript library — Flow normalization, rules engine, scoring, and the versioned bridge contract. Consumed by both CLI and extension. | Published to npm (publishes alongside the CLI) |
| @sfdt/plugin (/packages/plugin) | Salesforce CLI plugin — a thin oclif wrapper exposing every command as sf sfdt <command>. Forwards argv to the bundled sfdt binary; reimplements no logic. | Published to npm (publishes alongside the CLI) |
The CLI's sfdt ui command starts a local web dashboard (/gui) that exposes the same bridge endpoints the extension uses.
Quick Start
npm install -g @sfdt/cli
cd your-salesforce-project
sfdt init
sfdt deployOther install methods
# Bootstrap script (checks prerequisites, then installs via npm)
curl -fsSL https://raw.githubusercontent.com/scoobydrew83/sfdt/main/install.sh | bash
# Homebrew (macOS/Linux) — tap once, then install by name
brew tap scoobydrew83/sfdt
brew install sfdt
# (Third-party tap: it won't show in brew's website search, which only lists homebrew-core.)
# Docker (official multi-arch image)
docker run --rm -v "$PWD:/project" ghcr.io/scoobydrew83/sfdt:latest --help
# Salesforce CLI plugin — run every command as `sf sfdt <command>`
sf plugins install @sfdt/plugin
sf sfdt deploy --dry-runThe
@sfdt/pluginpackage is a thin wrapper over@sfdt/cli(it shells out to the same binary), so every command, flag, and--jsonoutput is identical to runningsfdtdirectly.--jsoncommands emit a Salesforce-native{ status, result, warnings }envelope. As an unsigned third-party plugin,sfshows a one-time security prompt on install.
npm alternatives: pnpm add -g @sfdt/cli · yarn global add @sfdt/cli · one-off npx @sfdt/cli --help.
From source (contributors):
git clone https://github.com/scoobydrew83/sfdt.git && cd sfdt
npm install
npm link # makes `sfdt` available globally from your checkout
npm run build:gui # build the local web dashboardFull install reference — every method plus CI usage — at sfdt.dev/cli/installation.
Commands
The full command reference — every command, flag, and default, generated from the CLI's own
command registry so it can never drift — lives at
sfdt.dev/cli/commands. Locally, sfdt --help (and
sfdt <command> --help) is always current. The machine-readable inventory is
generated/commands.json.
By area:
- Deploy & release — smart git-delta deploys with overwrite protection and automatic test-level selection, preflight validation, rollback with pre-rollback backup, smoke tests, release manifests + AI release notes, CI pipeline generation for four providers, and PR decoration.
- Metadata & source — incremental pull with a SQLite delta cache, drift detection,
org-to-org compare, full inventory scans,
package.xmlfrom git diffs, dependency tracing (including source-parsed gaps the Tooling API misses), and cross-org retrofit. - Testing & quality — the enhanced Apex runner, unified Apex + Flow logic tests, local LWC (Jest) tests, Agentforce agent tests as CI gates, Code Analyzer v5 scans (SARIF output for code scanning), coverage gates, and changelog management.
- Environments & data — scratch-org creation, deletion, listing, and pooling (
sfdt scratch), plus org data set import/export oversf data tree(sfdt data). - AI — code review, deployment-error analysis, PR descriptions, fix plans, and ad-hoc prompts across Claude / Gemini / Codex CLI providers or any OpenAI-compatible endpoint.
- Org health —
auditandmonitorcheck suites with multi-channel notifications, metadata backup, run history trending, and generated org documentation with ER diagrams. - Platform — the local web dashboard (
sfdt ui), MCP server for agents, Chrome-extension bridge + native messaging host management, feature kill-switch, environment doctor, shell completion, and a plugin scaffold.
Configuration
Running sfdt init creates a .sfdt/ directory in your project root:
.sfdt/
config.json # Core settings: org aliases, feature flags, AI provider, coverage threshold
environments.json # Named environments and org aliases
test-config.json # Test classes, coverage threshold, test level
pull-config.json # Metadata types to pull from orgconfig.json
{
"projectName": "My Salesforce Project",
"defaultOrg": "my-dev-org",
"deployment": {
"coverageThreshold": 75,
"preflight": {
"enforceTests": false,
"enforceBranchNaming": false,
"enforceChangelog": false
}
},
"features": {
"ai": true,
"notifications": false,
"releaseManagement": true
},
"ai": {
"provider": "claude",
"model": "",
"baseURL": "",
"apiKeyEnv": "",
"headers": {},
"timeoutMs": 300000
},
"plugins": []
}
baseURL/apiKeyEnv/headers/timeoutMsapply only to thehttpprovider; CLI providers (claude/gemini/openai) ignore them. See AI Features.
AI Features
AI-powered commands (review, explain, manifest --ai-cleanup, quality --fix-plan, pr-description, changelog generate, release) work with Claude, Gemini, OpenAI/Codex CLI providers, or any OpenAI-compatible HTTP endpoint (Ollama, OpenRouter, MiniMax, …). The provider is configured during sfdt init or by editing .sfdt/config.json.
Claude (default)
Requires the Claude Code CLI:
npm install -g @anthropic-ai/claude-code{ "ai": { "provider": "claude" } }Claude's interactive mode lets AI commands read your repository files directly with tool use.
Gemini
Requires the Gemini CLI:
npm install -g @google/gemini-cli{ "ai": { "provider": "gemini", "model": "" } }Authentication and model selection are handled by the Gemini CLI.
OpenAI
Requires the Codex CLI:
npm install -g @openai/codex{ "ai": { "provider": "openai", "model": "" } }Authentication and model selection are handled by the Codex CLI.
HTTP (OpenAI-compatible)
A single http provider talks to any endpoint exposing POST /chat/completions — local (Ollama) or cloud (OpenRouter, MiniMax, or any gateway). No extra CLI is needed; it uses Node's built-in fetch.
// Ollama (local, no API key)
{ "ai": { "provider": "http", "baseURL": "http://localhost:11434/v1", "model": "llama3.1" } }
// OpenRouter / MiniMax (cloud — key comes from an env var, never stored in config)
{ "ai": {
"provider": "http",
"baseURL": "https://openrouter.ai/api/v1",
"model": "openrouter/auto",
"apiKeyEnv": "OPENROUTER_API_KEY"
} }apiKeyEnv names the environment variable holding your key (export OPENROUTER_API_KEY=…); the key itself is never written to .sfdt/config.json. Optional headers (object) and timeoutMs (default 300000) are also supported.
Because an HTTP model can't read files or run git/sf itself, sfdt pre-gathers the needed context (git history, test results) and injects it into the prompt for agentic commands. Note: with a cloud endpoint, prompt content (diffs, git logs) is transmitted to that service — sensitive values are redacted before sending.
Disabling AI
Set features.ai to false to disable all AI prompts. Heuristic fallbacks still run in sfdt explain.
{ "features": { "ai": false } }Web Dashboard (sfdt ui)
sfdt ui starts a local Express server and opens the SFDT dashboard in your browser:
sfdt ui # opens http://localhost:7654
sfdt ui --port 8080 # custom port
sfdt ui --no-open # start server without opening browserThe dashboard has 25 pages, grouped in the sidebar. The authoritative list is
generated/gui-pages.json:
- Observe — Dashboard, Drift, Org Audit, Org Monitor, Test Runs, Coverage, Logs
- Analyze — Compare, Scan, Preflight, Manifests, Quality, Agent Test, Pull, Review, Explain, Flow Intelligence, Dependency Graph, Scratch Orgs, Data Sets, Documentation
- Release — Release Hub, Retrofit
- Config — Notifications, Settings
Most pages both read the latest snapshot and can trigger the underlying command directly from the UI.
The dashboard reads log files from the project's configured logDir (defaults to <project>/logs). Data appears automatically after running sfdt test, sfdt preflight, or sfdt drift when those commands write JSON result files.
Build the GUI (required after cloning from source):
npm run build:guiThe pre-built gui/dist/ is included in the published npm package so end users don't need to build it.
Plugin Architecture
Extend sfdt with custom subcommands by creating a plugin.
npm package plugin
Create a package named sfdt-plugin-<name> and publish it to npm:
// sfdt-plugin-my-thing/index.js
export function register(program) {
program
.command('my-thing')
.description('My custom command')
.action(async () => {
console.log('Hello from my-thing!');
});
}Install it in your Salesforce project:
npm install --save-dev sfdt-plugin-my-thingsfdt auto-discovers all sfdt-plugin-* packages in your project's node_modules/ on startup — no config required.
Local plugin
Drop a .js file in .sfdt/plugins/:
// .sfdt/plugins/custom-deploy.js
export function register(program) {
program.command('custom-deploy').action(async () => { ... });
}Explicit plugin list
List plugin package names in config.plugins to load them in a specific order:
{ "plugins": ["sfdt-plugin-my-thing", "@myorg/sfdt-plugin-audit"] }GitHub Action
The repository doubles as a composite GitHub Action: run any sfdt command as a
single uses: step, with org authentication handled for you. Pinning the
action tag pins the CLI version (cli-version: auto installs the version
shipped at that ref — no unpinned @latest).
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Smart delta validation
uses: scoobydrew83/sfdt@v0
with:
args-json: '["deploy","--smart","--org","ci","--delta-base","origin/${{ github.event.pull_request.base.ref }}","--dry-run"]'
auth-method: sfdx-url
sfdx-auth-url: ${{ secrets.SFDX_AUTH_URL }}
org-alias: ciargs-json (a JSON array of arguments) is executed with no shell, so values can
never be interpreted as shell syntax. The legacy command string input still
works for shell-neutral strings but is deprecated; strings needing quoting or
expansion additionally require allow-shell-command: 'true' (trusted input only).
JWT bearer flow instead of an auth URL:
auth-method: jwt
consumer-key: ${{ secrets.SFDX_CONSUMER_KEY }}
jwt-secret-key: ${{ secrets.SFDX_JWT_SECRET_KEY }}
username: ${{ secrets.SFDX_USERNAME }}sfdt ci init --provider github --runner action generates complete workflows
built on the action (monitor, deploy, release). The floating v0 tag tracks
the newest stable release; pin an exact tag (e.g. @v0.16.2) or a commit SHA
if you prefer immutable references. Always pass secrets as ${{ secrets.X }}
expressions, and never feed untrusted input to command — it runs as a shell
command line.
Docker
An official Docker image is available for CI/CD pipelines. It ships Node 22, Salesforce CLI, git, bash, and jq.
Build from source:
docker build -t sfdt .Run against a mounted project:
docker run --rm \
-v "$(pwd):/project" \
-e SFDX_AUTH_URL="$SFDX_AUTH_URL" \
sfdt deployGitHub Actions example:
- name: Deploy
run: |
docker run --rm \
-v "${{ github.workspace }}:/project" \
-e SF_ORG_INSTANCE_URL="${{ secrets.SF_ORG_INSTANCE_URL }}" \
sfdt deploy --skip-preflightInstall the selected AI provider CLI in the container when using AI features:
docker run --rm -v "$(pwd):/project" \
sfdt explain --latestPull Groups
Pull groups let you define named sets of metadata types in .sfdt/pull-config.json:
{
"metadataTypes": [
"ApexClass",
"ApexTrigger",
"LightningComponentBundle",
"CustomObject",
"CustomField",
"Layout",
"FlexiPage",
"PermissionSet",
"Flow"
],
"targetDir": "force-app/main/default"
}Use sfdt pull to retrieve all configured metadata types from the default org.
Pull Cache
sfdt pull uses a SQLite cache (stored in .sfdt/cache/) to track retrieved components and their modification dates. On subsequent runs, only components that have changed in the org are re-fetched, significantly reducing retrieval time for large orgs.
Cache behavior is controlled via pullCache in .sfdt/config.json:
{
"pullCache": {
"enabled": true,
"parallelism": 5,
"batchSize": 100
}
}| Flag | Description |
|------|-------------|
| sfdt pull | Incremental pull — only retrieves changed components |
| sfdt pull --full | Force full retrieve and rebuild the cache |
| sfdt pull --status | Show cache status (last pull time, component counts) |
Requirements
- Node.js >= 22.15.0 (uses the built-in
node:sqlitemodule, unflagged in Node 22.15) - Salesforce CLI (
sf) installed and authenticated to target orgs - bash 4.0+ (macOS users:
brew install bash) - jq 1.6+ (required by several shell scripts)
- Optional: Claude Code CLI for AI features with the
claudeprovider - Optional: Gemini CLI or Codex CLI for AI features with the
geminioropenaiprovider - Optional: an OpenAI-compatible HTTP endpoint (Ollama, OpenRouter, MiniMax, …) for AI features with the
httpprovider — no extra CLI required - Optional: GitHub CLI (
gh) for PR creation during deployments
Development
git clone https://github.com/scoobydrew83/sfdt.git
cd sfdt
npm install
npm link # makes `sfdt` available globally from your checkout
# Build the web dashboard
npm run build:gui
# Run tests
npm test
# Lint
npm run lintAfter npm link, the sfdt command points to your local checkout.
Surface catalogs
generated/ holds machine-generated catalogs of every public surface — commands, MCP tools, GUI
pages, VS Code commands, Chrome features, CI capabilities, and the parity matrix. Code is
authoritative; the catalogs are derived and checked in. Never edit generated/* by hand.
If you add or change a public surface (a command, a flag, an MCP tool, a GUI page), regenerate and commit the diff:
npm run generate:catalogs # rewrite generated/* from the code
npm run check:all-contracts # what CI runs — fails on driftCI fails on catalog drift, so a surface change without a regenerated catalog will not merge.
Contributing
Contributions are welcome! Please follow these steps:
- Fork the repository
- Create a feature branch (
git checkout -b feature/your-feature) - Make your changes with tests
- Run the test suite (
npm test) and linter (npm run lint) - Commit with a descriptive message
- Push to your fork and open a Pull Request
Please ensure all tests pass and linting is clean before submitting.
Security
To report a vulnerability, use GitHub's private security advisory feature rather than opening a public issue. See SECURITY.md for the full policy.
Acknowledgements
Parts of SFDT's Flow tooling are derived from SF Flow Utility Toolkit by Mark Jones (MIT). The derived areas are the Flow Health rules, the flow metadata normalizer, the health scorer, the API name prefixes, the scheduled flow calculator, the metadata cleaner and the default AI prompts, in @sfdt/flow-core and the browser extension. The copyright and permission notice, with the full list of derived files, is in THIRD_PARTY_NOTICES.md.
The web dashboard bundles third-party npm packages. npm run build:gui writes their licenses to gui/dist/THIRD_PARTY_LICENSES.md, which ships in the npm package.
Related open-source projects
SFDT copies no code from the projects below. They cover overlapping ground, and several are worth running alongside it:
- Org Check (Salesforce Labs): an in-org technical-debt and org-health analyzer. It is the free benchmark for what
sfdt auditand the AI-Readiness Index evidence pack cover. - Lightning Flow Scanner: Flow best-practice rules.
@sfdt/flow-corechecks overlapping concepts (DML/SOQL in loops, missing fault paths, hardcoded IDs), but its rule set and scorer come from SF Flow Utility Toolkit, credited above. - sfdx-git-delta: git-diff →
package.xml/destructiveChanges.xml, the same job assfdt manifestandsfdt deploy --smart. SFDT's mapper is an independent implementation. - Salesforce Inspector Reloaded: the browser power tool the SFDT Chrome extension is designed to sit beside, not replace.
- Salesforce Lightning Design System: the SFDT extension's colour palette takes SLDS values (
extension/lib/tokens.ts). Values only, no SLDS code or assets.
