LPM CLI

Lockfile

Use lpm.lock to preserve exact dependency graphs across local installs, workspaces, and CI.

lpm.lock records the exact dependency graph for a project. LPM CLI uses this TOML file to reuse package selections across installs.

# Create or update the lockfile locally
lpm install

# Review and commit the dependency graph
git diff -- lpm.lock
git add package.json lpm.lock
git commit -m "Update dependencies"

# Install the committed graph in CI
lpm ci

A lockfile pins the graph. The content-addressable store holds package files, and node_modules exposes those files to your project.

Which files to commit

FilePurposeCommit it?
lpm.lockAuthoritative dependency graph and manifest snapshotYes. In a workspace, commit the root lockfile.
lpm.lockbGenerated binary companion for older, representable lockfilesCommit it when LPM CLI writes it. Commit its removal when LPM CLI removes it.

Current installs write lockfile version 13. This version requires TOML-only data, so LPM CLI writes lpm.lock and removes an obsolete lpm.lockb.

Install and inspection commands read the authoritative TOML. An old binary companion does not override it. Do not create a binary companion manually.

For the other files that LPM CLI creates and whether to commit them, see Files LPM CLI creates.

What the lockfile records

The graph records exact package instances, dependency edges, peer bindings, and root selections. Two instances can share a name and version but have different peer bindings or sources.

The lockfile also records:

  • Exact versions and package sources, including registries, Git revisions, and local paths.
  • Integrity hashes and tarball URL hints when available.
  • Alias names, platform restrictions, and optional dependency reachability.
  • Dependency declarations and resolver settings used to detect manifest changes.
  • Catalog selections, patch records, and automatic linker state when applicable.
  • Registry signatures and verified provenance evidence when recorded.

The manifest snapshot includes dependency sections, overrides, resolutions, catalogs, patch fingerprints, and peer settings. Workspace snapshots also track applicable root peer providers.

Because the lockfile records the overrides and patches its resolution used, a fresh clone installs from it without local state from an earlier install. This includes --offline. An offline install fails if the overrides in package.json differ from the recorded ones.

A lockfile does not approve dependency scripts or make package sources trustworthy. Script approval, registry policy, and integrity checks remain separate controls.

For field definitions and examples, see the lpm.lock format.

Frozen and offline installs

Frozen installs preserve the selected graph. Offline installs use local package data. These controls serve different purposes.

CommandBehavior
lpm installReuses a compatible graph. Resolves again when the manifest or relevant settings change.
lpm ciRequires a compatible lockfile and rejects changes that need new package selections. Can download missing packages.
lpm install --frozen-lockfileExplicitly requires a compatible lockfile.
lpm install --offlineReplays the locked graph using available local package data. Fails if required data is missing.
lpm ci --offlineCombines frozen validation with offline installation.
lpm install --no-frozen-lockfileExplicitly permits lockfile updates, including in CI.

With an existing lockfile, plain lpm install automatically uses frozen mode when LPM CLI detects CI. Without a lockfile, plain install can create one. Use lpm ci when CI must reject a missing lockfile.

Frozen mode rejects manifest drift, incompatible lockfile schemas, package-add requests, and --force. LPM CLI leaves lpm.lock and any lpm.lockb unchanged in frozen mode. Frozen mode does not disable downloads or lifecycle scripts.

To prepare the store for offline CI:

# Run with network access
lpm fetch

# Use the populated store and committed lockfile
lpm ci --offline

lpm fetch downloads supported remote artifacts from the lockfile. Local paths and Git sources can require additional preparation. Fetch does not run dependency scripts or create node_modules.

--strict-integrity rejects registry packages without integrity hashes. During resolution, it also requires inline SRI for direct tarball URLs. Replay uses the integrity already recorded in the lockfile:

lpm ci --offline --strict-integrity

Locked source types must match the manifest. A registry dependency cannot reuse a locked Git, tarball, or local-path package. Local paths must remain declared or reachable through the dependency graph.

Offline package replay is not a network sandbox for lifecycle scripts or policy extensions.

A compatible lockfile does not imply that every warm install hashes all cached package bytes. Store reuse, artifact verification, and script policy have separate rules.

Workspace ownership

A recursive workspace install writes one root lpm.lock. Each member has its own recorded dependency view within that file.

# Run from the workspace root
lpm install --recursive
git diff -- lpm.lock
git add lpm.lock

After a successful migration, LPM CLI removes obsolete member lpm.lock and lpm.lockb files. Cleanup failures produce warnings. Commit successful removals with the root lockfile.

Member commands use the nearest ancestor lockfile that records that member. A legacy local lockfile does not override its owning workspace lockfile.

If an owning workspace lockfile is malformed, inspection fails. It does not silently select a different local graph, including when the member also declares a nested workspace.

A standalone project can use its local lockfile despite an unrelated malformed ancestor lockfile. A directory containing only an exported lpm.lock can also support inspection:

cd exported-graph
lpm graph --format json

An ancestor lockfile that records the exported directory as a member still owns that view. See workspaces for installation and selection rules.

Reuse and updates

If the lockfile matches the manifest, LPM CLI can rebuild node_modules from the recorded graph and available store entries. Missing artifacts or online checks can still require network access.

The local .lpm/install-hash records reusable install state. It is disposable state, not a substitute for a committed lockfile. The .lpm/ directory keeps itself out of Git.

For dependency changes, use lpm install, lpm upgrade, or the relevant mutation command. Review the resulting manifest and lockfile changes together.

Sorted entries make lockfile changes reproducible and reviewable. A version change can also change transitive packages, peer instances, and workspace records.

Recovery

Manifest drift

If a frozen install reports a mismatch, update the lockfile in a development environment:

lpm install --no-frozen-lockfile
git diff -- package.json lpm.lock

Review and commit the result before you retry CI. For a workspace, add --recursive from the root to update all members.

Older lockfile schemas

Lockfile versions 1–12 lack the exact package-instance graph required for frozen and offline replay. Run an online mutable install to write version 13:

lpm install --no-frozen-lockfile

lpm migrate --no-install intentionally creates a version 12 staging lockfile. It also requires an online install before frozen or offline use.

An older LPM CLI can reject a newer schema. Use a CLI release that supports the committed lockfile.

Missing cached packages

If offline installation reports missing data, populate the store with network access:

lpm fetch
lpm ci --offline

For source types that fetch does not prepare, restore the required source or run an online install first.

Unavailable pinned artifacts

An online replay preserves the pinned version, source, and integrity. If a cached tarball URL returns 404, LPM CLI can refresh registry metadata once. It retries a moved URL only when the pinned package contract remains unchanged.

If the artifact remains unavailable, installation fails and preserves the existing lockfile bytes. It does not select a newer version automatically.

For a direct dependency, use its manifest key:

lpm upgrade <manifest-key>

For "local": "npm:canonical@1.0.0", the key is local. For an unavailable transitive package, restore the artifact or update its owning direct dependency or override. Review and commit the new graph.

Authentication, rate limits, transport errors, and registry server errors remain separate failures.

Invalid files or failed cleanup

If an owning lockfile is malformed, restore a valid committed copy before you retry inspection or a frozen install.

Current lockfile writes remove obsolete binary companions. If permissions or a directory at lpm.lockb prevent cleanup, LPM CLI reports an error. Inspect the reported path and preserve unrelated contents before you correct it.

Each lockfile replacement is atomic, but the TOML write and companion cleanup are separate operations. A cleanup error can occur after the new TOML file exists. This is not a multi-file transaction or a guarantee against power loss.

See also