Managed runtimes
Select Node.js and Bun versions for project commands, workspace members, and development services.
A runtime pin selects the Node.js or Bun version that project commands use. LPM CLI stores managed installations outside the project and reuses them.
Use pins for consistent local development and CI. Use package.json > engines.node to require compatibility with the Node executable that actually runs.
Quickstart
lpm use node@22
lpm use bun@1.3.14
lpm run startlpm use installs the selected version and records the pin in lpm.json. From a subdirectory, it writes to the nearest directory that has a package.json or an lpm.json.
For configuration without an immediate download:
{
"runtime": {
"node": "22.12.0",
"bun": "1.3.14"
}
}A Bun pin makes bun available. It does not change package-script execution to bun run.
Node.js and Bun are the supported managed runtimes.
Detection order
| Runtime | Selection order |
|---|---|
| Node.js | lpm.json > runtime.node, then .nvmrc, then .node-version. |
| Bun | lpm.json > runtime.bun. |
The first available selector wins. Without a selector, the command uses the first matching executable on its constructed PATH.
Configuration read errors stop detection.
Node selectors support exact versions, prefixes, ranges, latest, lts, lts/*, and named channels such as lts/iron.
Named LTS selectors retain their codename. lts and lts/* select the latest matching LTS release.
Bun supports exact versions, prefixes, ranges, and latest, including version prefixes such as bun-v1.3.14.
lpm use pin node@lts/iron
lpm use pin 'node@>=22 <23'
lpm use pin bun@latestPin-only Node commands preserve channel selectors. An explicit installation resolves the selector and records the installed version. Invalid or contradictory selectors are rejected by lpm use.
Automatic installation and fallback
lpm dev, lpm run, lpm exec, lpm test, and lpm bench prepare managed runtimes. They prefer matching installed versions before they request a download.
For Node latest, installed-only selection chooses the newest installed version.
LTS selection uses the cached release index to classify installed versions. Ordinary runs can reuse stale classification data without a network request.
An explicit lpm use node@<selector> can refresh release discovery instead.
LPM_NO_AUTO_INSTALL=1 lpm run start
LPM_NO_AUTO_INSTALL=true lpm devThese values disable automatic downloads for both runtimes. They do not disable installed runtime selection. If selection or installation fails, automatic preparation warns and leaves the inherited runtime path available. A pin alone does not guarantee that a command stops when its requested runtime is unavailable. Node engine constraints still apply to the executable that the command resolves.
lpm bundle, lpm pack, and lpm check reuse installed runtimes. They do not automatically download Node. Prepare the required version with lpm use first. Their installed-only Node lookup also supports cached channels and preserves range operators. Root install scripts use the same installed Node selection without an automatic runtime download.
Workspaces and services
Workspace members inherit root pins for runtimes that they do not select locally.
A local Node selector replaces root Node without removing an inherited Bun selector, and vice versa.
Development services apply the same rule from each service's cwd.
{
"runtime": { "node": "20" }
}lpm run test --filter legacy
lpm test --allThe selected member uses its local Node version. Other selected members use their own selectors or inherited root pins. See workspaces and development services for execution rules.
Script PATH order
Package scripts normally receive:
- Project and ancestor
node_modules/.bindirectories, nearest first. - The selected managed Node directory.
- The selected managed Bun directory.
- The inherited
PATH.
Ancestor script lookup stops at the workspace boundary, or at the filesystem root outside a workspace.
Built-in tool lookup stays within its project or workspace boundary.
A local .bin/node can take precedence over managed Node. Engine checks use the executable on the actual execution path.
Existing nvm or fnm shell configuration can coexist with managed runtimes.
A managed pin takes precedence over inherited shell paths, after project executable directories.
If both .nvmrc and lpm.json > runtime.node exist, the lpm.json selector wins.
Node engine constraints
engines.node is a compatibility constraint. It never selects or downloads a managed runtime.
{
"engines": { "node": ">=22 <23" }
}The runner checks the Node executable on the constructed path against the applicable root and member constraints. Workspace members without a requested task do not need runtime preparation. For development services, runtime checks finish before the service set starts.
Engine checks stop incompatible runs by default. Set package.json > lpm > engineStrict: false or ~/.lpm/config.toml > engine-strict = false for warnings only.
Install-time checks also apply to dependency Node constraints. Required mismatches stop installation, while incompatible optional-only packages are skipped.
See lpm install for install-time controls.
engines.bun can produce a compatibility warning, but it is neither an enforced engine constraint nor a managed Bun pin.
Supported hosts
Managed downloads recognize macOS, Linux, and Windows on x64 or ARM64. The selected release must provide a matching platform asset. Bun selects musl assets on musl Linux and baseline x64 assets on processors without AVX2. Node downloads use the standard upstream distributions.
Storage and reuse
~/.lpm/runtimes/
node/<version>/bin/node # macOS and Linux
node/<version>/node.exe # Windows
bun/<version>/bin/bun
index-cache.json
bun-index-cache.jsonWindows Bun uses bun.exe in its bin directory.
LPM_HOME replaces ~/.lpm. Installations are shared by projects that use the same LPM CLI home.
Concurrent requests for one version share an installation lock. Only a complete directory becomes available for reuse.
Reuse checks the expected executable's shape and permissions. It does not recheck the downloaded content hash on every command. If an installed runtime is damaged, remove it and install it again:
lpm use remove node@22.12.0
lpm use node@22.12.0
lpm use listRemoval leaves project pins unchanged. It can affect other projects that use the same installation.
Download verification
Node release discovery uses https://nodejs.org/dist/index.json with a one-hour cache.
Downloads use SHA-256 from the exact archive entry in SHASUMS256.txt. Conflicting duplicate entries stop installation.
LPM_NODE_DIST_BASE_URL changes the archive and checksum location. It does not change release-index discovery.
Node verification trusts HTTPS and the selected distribution source. LPM CLI does not verify the detached GPG signature.
Bun discovery uses the oven-sh/bun GitHub release API with a one-hour cache.
Downloads use the GitHub asset digest, SHASUMS256.txt, or both. If both are present, both must agree with the downloaded bytes.
Conflicting checksum entries also stop Bun installation.
CI and recovery
lpm use node@22.12.0 --json
LPM_NO_AUTO_INSTALL=1 lpm run test --jsonCache the runtime directory between compatible CI jobs. Preinstall exact versions before offline runs. LTS reuse also needs cached release metadata. An exact version avoids that channel lookup.
| Problem | Action |
|---|---|
| The wrong Node version runs. | Check local .bin/node, project pins, workspace inheritance, and inherited PATH. |
| A pin cannot download. | Correct connectivity or install the required version before the command. |
| An LTS pin misses an installed version. | Refresh release discovery with lpm use node@<selector>, or pin the exact version. |
| Node fails an engine check. | Select a version that satisfies both project and workspace constraints. |
| A runtime directory is incomplete or damaged. | Remove that version and reinstall it. |