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
| Flag | Default | Description |
|---|---|---|
-l, --validation <level> | local | Validation level: local, org, or full. See validation levels. |
-f, --force | off | Builds even when the source hash shows no changes. Env: SFPM_FORCE_BUILD. |
--no-dependencies | off | Builds only the named packages, without their transitive dependencies. |
--async | off | Returns 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 config | DevHub username or alias. Required for org and full validation. Env: SF_DEV_HUB. |
-o, --build-org <username> | none | Org 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> | none | Installation key for unlocked packages. Repeatable. Pass <package>=<key> for one package, or a bare value as the default for all packages. |
--source-only | off | Routes every package through source deployment. No DevHub and no package version IDs. Env: SFPM_SOURCE_ONLY. |
-b, --build-number <number> | none | Numeric build number, appended to the package version. |
-w, --wait <minutes> | 120 | Timeout, in minutes, for package version creation. Minimum 1. |
--turbo | off | Single-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.
| Level | Checks run |
|---|---|
local | Local 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. |
org | Org validation only. Source packages are deployed and tested in a build org. Unlocked packages are validated by Salesforce through a package version request. |
full | Local 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 --pollsfpm 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 --pollRelated
- Deploy and install covers deploying the built packages.
- Wire your build tools explains how to run your own compiler before
sfpm build.