LPM CLI

Managed runtimes

How LPM CLI detects, installs, and exposes managed Node.js and Bun runtimes.

LPM CLI manages project runtimes itself. It detects the versions your project asks for, downloads missing installs on demand, stores them under ~/.lpm/runtimes/, and prepends the right bin/ directories to PATH for every script you run.

Node and Bun are supported managed runtimes. Deno is still unsupported.

Detection Order

When lpm run, lpm dev, lpm <file> / lpm exec, lpm test, or lpm bench starts, LPM CLI resolves managed runtime pins in deterministic order: Node first, then Bun.

Node

PrioritySourceFormat
1lpm.json > runtime.nodeSemver: ">=22.0.0", "22.5.0", "22"
2package.json > engines.nodeSemver
3.nvmrcPlain version: 22.5.0, lts/iron, v22
4.node-versionPlain version
(fallback)None of the aboveUse the system node from PATH — no managed runtime

.nvmrc lives in this list intentionally — projects migrating from nvm get Node pinning for free without writing lpm.json. New projects should prefer lpm.json > runtime.node because it sits next to the rest of the LPM CLI config.

Bun

PrioritySourceFormat
1lpm.json > runtime.bunExact, latest, v1.3.14, bun-v1.3.14, prefix, or range
(fallback)No runtime.bun declaredDo not prepend managed Bun

package.json > engines.bun is recognized as a compatibility warning, but LPM CLI does not enforce it and does not use it as a managed-runtime pin. Use lpm.json > runtime.bun when scripts need Bun available.

Auto-Install

If a detected version is not already installed, LPM CLI downloads it before running the script unless auto-install is disabled:

LPM_NO_AUTO_INSTALL=true lpm dev

LPM_NO_AUTO_INSTALL=true applies to both Node and Bun. When auto-install is off and a managed runtime is missing, LPM CLI warns and leaves the system PATH in place for that runtime.

Node releases come from https://nodejs.org/dist/index.json, cached for 1 hour at ~/.lpm/runtimes/index-cache.json. Downloads are SHA-256 verified against the matching SHASUMS256.txt entry.

Bun releases come from the GitHub releases API for oven-sh/bun, cached for 1 hour at ~/.lpm/runtimes/bun-index-cache.json. Downloads use Bun's platform asset names such as darwin-aarch64, linux-x64-musl, linux-x64-baseline, and windows-x64. Downloads are SHA-256 verified against GitHub asset digests and/or SHASUMS256.txt; when both are present, both must verify.

Storage Layout

~/.lpm/runtimes/
├── node/
│   └── 22.12.0/
│       └── bin/
│           ├── node
│           ├── npm
│           └── npx
├── bun/
│   └── 1.3.14/
│       └── bin/
│           └── bun
├── index-cache.json
└── bun-index-cache.json

Each version is installed once and reused by every project on the machine. LPM_HOME=<path> moves the entire LPM CLI root, including runtimes/, which is useful for hermetic CI.

Script PATH Order

When a script runs, LPM CLI builds PATH from:

  1. Project-local node_modules/.bin/
  2. Managed Node bin/, if a Node pin resolves to an installed version
  3. Managed Bun bin/, if runtime.bun resolves to an installed version
  4. The inherited PATH

This means locally-installed CLIs win over managed runtime tools, and managed Node wins over managed Bun when both provide a command with the same name.

runtime.bun only exposes bun to scripts. It does not switch LPM CLI script execution to bun run.

Node Engine Enforcement

The workspace root's engines.node plays two roles. As a detection source it tells LPM CLI which managed Node runtime to install for lpm dev / lpm run when runtime.node is absent. As an enforcement constraint it gates lpm install / lpm rebuild / lpm add. Selected dependencies' engines.node ranges are install-time enforcement only: required mismatches abort, optional-only incompatible packages are skipped, and the ranges are persisted for lockfile replay.

$ lpm install
Error: lpm::engine_mismatch
  × node version 18.20.4 does not satisfy required >=22.0.0 (from package.json
  │ > engines.node (compared against system PATH))

Resolution: install the matching managed runtime first (lpm use node@22), or relax the constraint.

engines.bun is not enforced in this first Bun runtime pass. Put the desired Bun version in lpm.json > runtime.bun to manage Bun availability.

lpm use

lpm use node@22                 # install the latest 22.x, pin in lpm.json
lpm use node@lts                # install latest Node LTS
lpm use bun@1.3.14              # install + pin Bun
lpm use bun@latest              # install + pin latest Bun
lpm use --list bun              # list installed Bun versions
lpm use remove bun@1.3          # remove all installed 1.3.x Bun runtimes

lpm use <runtime>@<spec> writes the resolved version into lpm.json > runtime.<runtime>. During a fresh install, the human output shows the resolved version, downloaded size, SHA-256 verification, extraction/linking, final runtime, and PATH hint.

lpm use <runtime>@<spec> --pin skips the download step. If the spec already matches an installed runtime, LPM CLI writes that exact installed version; otherwise it records the requested spec unchanged so a later lpm dev / lpm run can resolve or auto-install it.

lpm use remove <runtime>@<spec> deletes installed managed runtimes matching the spec without changing lpm.json. If the project still pins a matching runtime, LPM CLI warns because later commands can auto-install it again.

Compatibility With nvm / fnm

LPM CLI's Node management is independent. If you have nvm or fnm installed:

  • They modify PATH in your shell, affecting node lookup outside LPM CLI.
  • LPM CLI's Node detection respects .nvmrc, so a project pinned via nvm works under LPM CLI without converting.
  • When LPM CLI runs a script with a managed Node pin, LPM CLI's runtime takes precedence over whatever nvm set in the shell.

You do not have to remove nvm to adopt LPM CLI. If a project has both .nvmrc and lpm.json > runtime.node, the lpm.json value wins.

See Also