LPM CLI

Resolver

Understand version selection, peer dependencies, overrides, and resolution failures.

The resolver selects exact package versions and connects each dependency to the package instance that satisfies it. Use this page to understand unexpected versions, peer conflicts, and failed installs.

LPM CLI resolves packages from npm, LPM.dev Registry, and private registries. Registry configuration controls routing and authentication. Only @lpm.dev/* packages always use LPM.dev Registry.

Quickstart

# Resolve and install the project's declared dependencies
lpm install

# Inspect candidate packages without changing the project
lpm resolve 'react@^19' 'react-dom@^19' --json

# Explain a package in the existing project graph
lpm graph --why react

# Require the committed graph in CI
lpm ci

lpm resolve uses the supplied package specs and default resolution policies. It does not apply the project's dependency declarations, catalogs, overrides, or peer rules. lpm install applies those project settings, so its result can differ.

Configuration

lpm.json has no dedicated resolver settings. Project resolution settings belong in package.json > lpm:

package.json
{
  "lpm": {
    "autoInstallPeers": true,
    "strictPeerDependencies": true,
    "overrides": {
      "example-parent>example-child": "^2.0.0"
    }
  }
}

For a repeatable candidate check, use an uncached task:

lpm.json
{
  "tasks": {
    "check-candidates": {
      "command": "lpm resolve \"react@^19\" \"react-dom@^19\"",
      "cache": false
    }
  }
}
lpm run check-candidates -- --json

Task caching stays off, but registry metadata caches still apply. See Task runner for task configuration.

Locked installs and new selections

An eligible lockfile replays exact package instances instead of selecting new versions. A newer registry release alone does not replace a locked version. Use lpm upgrade to update selected dependencies.

For a new resolution, the default resolver prefers a compatible latest version or the requested dist-tag. It then considers other matching versions in descending version order, subject to install policy. The numerically highest release is not always the selected release.

For ordinary transitive dependencies, a compatible version already selected by a manifest dependency can take precedence. Otherwise, reuse requires the selected version to match. Overrides can require a separate selection.

Several versions of the same package can coexist. For example, dependencies that require helper@^1 and helper@^2 need separate versions. Different peer contexts can also require separate instances of the same name and version. See Dependency graph for the distinction between a package version and an installed instance.

Resolver modes

ModeSelection
Greedy-fusionDefault. Selects versions as metadata becomes available and supports multiple versions and automatic peer installation.
PubGrub with split retriesOptional alternative. Retries conflicts with separate package selections, but does not automatically install missing peers.
LPM_RESOLVER=pubgrub lpm install

The environment variable applies to this command. Remove it to restore the default. A locked install can reuse its graph without running either resolver.

PubGrub stops when a conflict report provides no new package to split. It does not guarantee a solution for every satisfiable graph. Its wildcard requests can select prereleases. The default resolver excludes prereleases from bare wildcard requests. If you need a prerelease, use an explicit prerelease range or tag.

Peer and optional dependencies

The default resolver automatically installs missing required peers when autoInstallPeers is enabled. These packages can appear at the project root without an entry in package.json. Optional peers are not automatically installed. They can bind to a compatible version already present in the graph.

SettingPrecedence and default
Automatic peerslpm.autoInstallPeers, then user auto-install-peers, then true.
Strict peersCLI flag, then lpm.strictPeerDependencies, then user strict-peer-dependencies, then false.
# Fail on missing required peers, mismatches, and conflicting requirements
lpm install --strict-peer-dependencies

# Use warnings for this invocation
lpm install --no-strict-peer-dependencies

PubGrub does not add missing peers, even when automatic peers are enabled. Strict peer checks still apply to the resulting graph. A required peer with no available candidate can fail resolution before these checks. peerDependencyRules changes post-resolution warnings. It does not change automatic peer selection or conflict detection.

With the default linker selection, peer conflicts can switch an install to the isolated layout. An explicit --linker flag or persistent linker setting prevents this automatic switch. Isolation does not make incompatible peer ranges compatible.

Optional dependencies can be skipped when resolution, download, platform, or engine checks reject them. If a required dependency also reaches the package, required-dependency rules apply. See lpm install for peer configuration and diagnostics.

Overrides and aliases

Override sources have this precedence:

SourcePriority
package.json > lpm > overridesHighest
package.json > overridesMiddle
package.json > resolutionsLowest
package.json
{
  "lpm": {
    "overrides": {
      "example-child": "^2.0.0",
      "example-parent>other-child": "3.1.0"
    }
  }
}

A plain package selector applies throughout the graph. Plain selectors and unqualified parent selectors can replace a range that has no available version. parent>child targets a direct parent-child edge. A version selector, such as child@<2, matches the naturally selected version. A range-qualified selector cannot match without a natural candidate. Multi-level paths such as a>b>c are rejected. Override targets must be strings. Nested npm override objects produce a warning and are not applied.

Release-age, trust, engine, and platform checks still apply to overridden versions. If an override target is unavailable or rejected during selection, LPM CLI warns and keeps the natural selection. If neither selection is available, required dependencies fail and optional dependencies can be skipped.

Override summaries omit unchanged selections. A rescued selection shows unresolved as its original version. JSON output and saved override records use from_version: null for this case. See Override selectors for the supported forms.

An npm alias gives a dependency a local name:

package.json
{
  "dependencies": {
    "react-previous": "npm:react@^18"
  }
}

The alias follows the target package's registry route. The lockfile preserves the alias and its exact target for later installs.

Policies that affect the result

PolicyEffect
Minimum release ageOff by default. When enabled, checks direct dependencies; strict policy also checks transitive dependencies and lockfile replay.
Trust policyCan reject candidates that reduce trusted-publisher evidence. Fetch-time checks can also require previously verified provenance.
EnginesRequired incompatible packages fail by default. Optional-only incompatible packages can be skipped.
PlatformPreserves os, cpu, and libc metadata in the lockfile, then checks compatibility for the current host.

During resolution, ranges can select an older version that passes release-age or publisher-trust checks. Fetch-time provenance failures do not trigger version reselection. A blocked exact pin fails instead of silently changing its version. See Install policies, Trust, and Security and audit.

Diagnose a failed or unexpected selection

lpm graph --why example-child
lpm install --strict-peer-dependencies --json
lpm resolve 'example-child@^2' --json

Resolution errors identify the requested package, range, and parent when that information is available. Structured resolution failures use error_code: "resolution_failed". The nested error.kind describes the cause. Strict peer-check failures use error_code: "peer_dependency".

CauseRecovery
No matching version or no solutionCheck the range, tag, registry route, and override selectors.
Policy rejectionRead the named policy and choose an allowed version.
Registry request failureCheck registry availability and credentials before retrying.
Peer conflictAlign the consumer ranges or explicitly declare a compatible peer.
Platform or engine mismatchUse a supported environment or a compatible package release.

To change a locked selection, use lpm upgrade or update the applicable override, then review lpm.lock. Deleting the lockfile changes the scope of resolution to the whole project. Current lockfile version 13 uses authoritative TOML and does not produce a binary companion.

Advanced diagnostics

These environment variables help compare resolver behavior during troubleshooting:

VariableEffect
LPM_RESOLVER=pubgrubSelect the alternative resolver.
LPM_GREEDY_FUSION=0Keep greedy selection but disable fused metadata scheduling.
LPM_NPM_FANOUT=<N>Set the metadata concurrency limit. Defaults vary with install scheduling.
LPM_WALKER=streamSelect streaming metadata traversal when the non-fused path runs.

Higher metadata concurrency does not guarantee a faster install and can increase registry load. See Environment variables for diagnostic controls.

See also

  • lpm install — apply project resolution settings and install the graph.
  • lpm resolve — inspect candidate packages without installing them.
  • lpm graph — inspect an existing project's dependencies.
  • Lockfile — retain exact selections across installs.
  • Save policy — choose the ranges written to the manifest.