lpm release
Plan, apply, and publish workspace releases in dependency order.
lpm release plan --affected --base main --bump patchCoordinates releases across a workspace. lpm release plan computes the package/version/dependency update plan, lpm release apply writes it to manifests, and lpm release publish publishes selected members in dependency order.
lpm release is intentionally separate from lpm version: single-package version bumps stay simple, while workspace releases get explicit planning and publish orchestration.
Examples
lpm release plan --all --bump patch
lpm release plan --affected --base origin/main --bump minor --json
lpm release apply --filter core --bump major
lpm release apply --affected --base main --dry-run --json
lpm release publish --all --dry-run --json
lpm release publish --affected --base origin/main --npm -y
lpm release publish --all --lpm --otp 123456 --jsonPlanning
A release plan reads every selected workspace member's package.json, computes the new versions, and then checks workspace-internal dependents.
Dependency ranges are updated only when the new version no longer satisfies the existing range and the range is safely rewriteable:
| Existing spec | Example update |
|---|---|
| exact old version | 1.2.3 -> 2.0.0 |
| caret old version | ^1.2.3 -> ^2.0.0 |
| tilde old version | ~1.2.3 -> ~2.0.0 |
| explicit workspace range | workspace:^1.2.3 -> workspace:^2.0.0 |
Dynamic workspace specs such as workspace:*, workspace:^, and workspace:~ are left unchanged. catalog: specs are also left unchanged because the catalog owns the concrete version.
If any dependent has a range that would stop accepting a bumped internal package and LPM CLI cannot rewrite it safely, planning fails before anything is written.
Bump sources
Pass --bump <level> to use one bump for every selected package:
lpm release plan --affected --bump patchOr add lightweight change files under .lpm/changes/. Each non-empty, non-comment line is:
<package-name> <bump>Example:
core minor
app patchChange-file bumps override the command's --bump fallback for matching packages. If a selected package has no change-file entry and no --bump, the command fails instead of guessing. Use --bump patch when you want the conservative patch fallback.
Selection
Every lpm release subcommand requires an explicit workspace selection:
Selection modes are mutually exclusive: --all cannot be combined with --affected, --filter, or --filter-prod.
| Flag | Description |
|---|---|
--all | Select every workspace member. |
--affected | Select packages changed since --base plus their transitive dependents. |
--base <REF> | Git base ref for --affected. Defaults to main. |
--filter <EXPR> | Select workspace members with the same filter grammar as lpm run --filter. |
--filter-prod <EXPR> | Like --filter, but dependency closures follow production edges only. |
--changed-files-ignore-pattern <GLOB> | Ignore matching changed files when evaluating affected packages. |
--test-pattern <GLOB> | Treat matching changed files as tests so affected fanout does not include dependents from them. |
--fail-if-no-match | Exit non-zero when the selection resolves to no members. |
Subcommands
lpm release plan
Prints the release plan and never writes files.
lpm release plan --all --bump patch
lpm release plan --affected --base origin/main --bump minor --jsonlpm release apply
Writes the plan to the selected package manifests and any workspace dependents that need range updates.
lpm release apply --filter core --bump major
lpm release apply --affected --bump patch --dry-run --jsonLPM CLI records the original manifests before it replaces any file. It also coordinates these writes with installs, version changes, and publishing.
If the process stops during the write, run a mutating release apply, release publish, or version command. The command restores an incomplete update before it continues. If the original operation completed, an identical retry reports the completed operation without another version bump.
Read-only commands do not change recovery state. release plan, release apply --dry-run, and release publish --dry-run stop when an incomplete update exists. A concurrent install also stops instead of using a partially updated workspace.
lpm release publish
Publishes selected members in topological order, dependencies before dependents. Before the first upload it validates current workspace-internal ranges so a stale manifest fails before a partial publish.
release publish reuses the single-package lpm publish implementation for each member. It supports the same target flags that make sense for a workspace publish:
| Flag | Description |
|---|---|
--dry-run | Print publish order and skip decisions without uploading. |
-y, --yes | Skip per-package confirmation prompts. |
--otp <CODE> | Send a six-digit authenticator code for MFA-protected LPM.dev publishes. |
--min-score <N> | Require a minimum quality score. |
--allow-secrets | Skip the pre-publish secret scan. |
--npm | Publish to npm. |
--lpm | Publish to LPM.dev Registry. |
--github | Publish to GitHub Packages. |
--gitlab | Publish to GitLab Packages. |
--publish-registry <URL> | Publish to a custom npm-compatible registry. |
--provenance | Require generated Sigstore provenance. |
--no-provenance | Disable provenance for this run. |
--provenance-file <PATH> | Attach a pre-generated Sigstore bundle for npm-compatible targets. |
For an LPM.dev workspace release, --otp supplies the same code to each selected package. Use a fresh code before it expires.
For LPM.dev Registry and npm targets, LPM CLI checks metadata before upload. If every checked target already has the selected version, the package is skipped. If only some checked targets already have it, the command fails before uploading so it does not partially publish.
Custom, GitHub, and GitLab targets are still validated for local target-name/config correctness, but remote version existence is left to the target publish response.
Workspace publishing is not transactional across packages. If a later package fails, LPM CLI does not remove earlier successful uploads.
Human output names the failed package and shows its preparation or upload error. JSON output reports each selected package with one of these states:
| Status | Meaning |
|---|---|
published | Every selected target for the package succeeded. |
failed | Preparation or at least one selected target failed. |
not_attempted | An earlier package failed, so this package did not start. |
skipped | The checked targets already contain this version. |
planned | A dry run prepared this package without an upload. |
If a publish fails, keep the successful uploads. Then retry only the failed and not_attempted packages with a narrower selection.
JSON
--json is available on every subcommand. plan and apply emit the same envelope shape:
{
"success": true,
"dry_run": true,
"packages": [],
"dependency_updates": [],
"files": []
}publish --json emits:
{
"success": true,
"dry_run": true,
"packages": 2,
"results": []
}On failure, success is false. The results array keeps completed, failed, and unattempted packages, and warning explains the retry boundary.
See also
lpm version— single-package version bumpslpm publish— single-package publish behavior and provenancelpm workspaces— workspace declarations, protocols, catalogs, and filters