sfpm
CLI reference

Build

Build packages in dependency order, choose a validation level, and check async validation results.

sfpm build builds the packages you name, in dependency order. Dependencies are built too unless you pass --no-dependencies. A package is skipped when its source has not changed since its last build, unless you pass --force.

sfpm build <package> [<package>...] [flags]

Package names can be scoped (@myorg/my-package) or unscoped (my-package). An unscoped name that matches more than one package fails with --json and prompts in an interactive run.

Flags

FlagDefaultDescription
-l, --validation <level>localValidation level: local, org, or full. See validation levels.
-f, --forceoffBuilds even when the source hash shows no changes. Env: SFPM_FORCE_BUILD.
--no-dependenciesoffBuilds only the named packages, without their transitive dependencies.
--asyncoffReturns after validation requests are created, without waiting for results. Check progress with sfpm build status.
-v, --target-dev-hub <username>target-dev-hub from sf configDevHub username or alias. Required for org and full validation. Env: SF_DEV_HUB.
-o, --build-org <username>noneOrg used to validate source packages (deploy and test). Without it, org and full validation create a scratch org from the DevHub and delete it after the build, unless --async is set.
-k, --installation-key <key>noneInstallation key for unlocked packages. Repeatable. Pass <package>=<key> for one package, or a bare value as the default for all packages.
--source-onlyoffRoutes every package through source deployment. No DevHub and no package version IDs. Env: SFPM_SOURCE_ONLY.
-b, --build-number <number>noneNumeric build number, appended to the package version.
-w, --wait <minutes>120Timeout, in minutes, for package version creation. Minimum 1.
--turbooffSingle-package mode for external orchestrators such as Turborepo. Requires exactly one package. Implies --no-dependencies and --force.

The shared flags --json, --plain, and --log-level also apply. See the CLI reference.

The CLI default for --validation is local. The build GitHub Action has its own default, org, for its validation input. The two are separate defaults for separate tools. Check the action's inputs when you move a command into CI.

Validation levels

Validation runs checks before a package is considered built. The level controls which checks run.

LevelChecks run
localLocal checks only, with no org. A compile check for packages with Apex and a dependency check for undeclared dependencies. Both warn and do not fail the build.
orgOrg validation only. Source packages are deployed and tested in a build org. Unlocked packages are validated by Salesforce through a package version request.
fullLocal checks and org validation. Undeclared dependencies fail the build in this level.

The local checks use Nimbus, a local Apex runtime, so they need Nimbus installed. sfpm looks for the nimbus binary on your PATH and in the location the sf CLI plugin uses. Local checks only run at local and full; at org, no local checks run at all (see the table above).

When the binary is missing, the compile check reports itself as skipped and the build continues. The dependency check instead reports an error. At local, that check is warn-only, so the error is logged and the build continues. At full, it isn't warn-only, so a missing Nimbus binary fails the build.

Local checks are best-effort. The org check is the authoritative signal.

Scratch orgs for source packages

When validation is org or full, a source package needs an org to deploy and test against. Without --build-org, sfpm creates a scratch org from the DevHub using config/project-scratch-def.json. The scratch org lasts one day. sfpm deletes it when the build finishes, unless you pass --async.

Async validation

Org validation can take a long time for unlocked packages. With --async, sfpm starts a background watcher and returns once the validation requests exist. The watcher checks the results later.

sfpm build my-package --validation org --target-dev-hub my-devhub --async
sfpm build status
sfpm build status --poll

sfpm build status lists the active build watchers, with their ID, type, status, process ID, age, and any error. --poll asks Salesforce for the current status of each request instead of reading only local state. --json prints the same data as JSON.

Turbo mode

--turbo builds a single package for an external orchestrator. Each package that sfpm project init turbo creates has an sfpm:build script that runs sfpm build <package> --turbo. turbo run sfpm:build runs those scripts across the workspace, and Turborepo handles the ordering and caching.

With --turbo, the command also writes its JSON result to dist/build-result.json in the package directory.

Examples

# Build one package and its dependencies, with local checks
sfpm build my-package

# Build two packages without their dependencies, validated against the DevHub
sfpm build package-a package-b --no-dependencies --validation org --target-dev-hub my-devhub

# Rebuild even without source changes, and return without waiting for validation
sfpm build my-package --force --async --target-dev-hub my-devhub

# Check async validation by polling Salesforce
sfpm build status --poll

On this page