Compared to npm, pnpm, bun
Side-by-side defaults across the four JavaScript package managers — security, resolution, developer orchestration, publishing, and platform.
A factual comparison of default behavior across npm, pnpm, bun, and lpm.
Install benchmarks use the tracked VitePress docs fixture, a real-world workspace graph with 535 packages.
| Benchmark | npm | pnpm | bun | lpm | lpm + LPM Firewall monitor |
|---|
| Cold install, equal footing ¹ | 17,354ms | 6,125ms | 2,455ms | 2,945ms | 3,043ms |
| Warm install ¹ | 3,819ms | 3,301ms | 451ms | 387ms | 324ms |
| Up-to-date install ¹ | 282ms | 522ms | 77ms | 14ms | 14ms |
Dev command benchmarks measure already-installed local scripts, local bins, and built-in tools.
| Benchmark | npm / npx / tsx | pnpm | bun / bunx | lpm |
|---|
| Trivial echo script ² | 74ms | 161ms | 15ms | 10ms |
| Node startup + tiny script ² | 101ms | 185ms | 33ms | 27ms |
Local bin: esbuild --version ² | 144ms | 174ms | 27ms | 21ms |
| Run TSX app, warm cache ³ | 112ms | — | 19ms | 41ms |
lpm lint vs npx oxlint ⁴ | 273ms | — | — | 3ms |
lpm fmt vs npx biome ⁴ | 340ms | — | — | 3ms |
| Axis | npm | pnpm | bun | lpm |
|---|
| Dependency lifecycle-script sandbox | — | — | — | Dependency lifecycle-script sandbox: approved or triage-selected dependency scripts run under macOS Seatbelt, Linux Landlock, or Windows AppContainer. Default mode contains filesystem access while allowing network. Strict mode denies outbound network on macOS and AppContainer; Linux 6.7+ uses Landlock V4 plus seccomp, with AF_UNIX retained for IPC. Older Linux kernels and Windows installs missing the AppContainer helper refuse strict mode unless allow-degraded = true. Root-project lifecycle scripts are not sandboxed. |
Dependency lifecycle scripts (preinstall / install / postinstall) | All scripts run | Blocked until approved (approve-builds flow) | Blocked unless in trustedDependencies; bun ships a built-in 367-package default trusted list that also runs scripts without approval | Dependencies are blocked by default. Under the opt-in triage policy, green verdicts are eligible to auto-run in the sandbox; an optional advisor can approve amber verdicts for the current run; red verdicts remain blocked. The root project's lifecycle runs on bare lpm install without the dependency sandbox. |
| Registry package signatures | Manual via npm audit signatures | Manual via pnpm audit signatures | — | lpm audit signatures; optional install-time fail-closed verification with lpm config signatures --set true |
| Sigstore provenance verification | Publish-time provenance support | Publish-time provenance support | — | DSSE + Rekor body + Rekor SET + SCT + X.509 chain verified end-to-end on install for provenance bundles served by npmjs |
| Minimum release age (cooldown) | min-release-age flag, off by default | 1-day cooldown by default | Off by default | 1-day direct/root cooldown by default; strict transitive policy opt-in |
engines.node enforcement | Warn only | Warn only | — | When an effective Node version is available, hard-fails incompatible required root/dependency constraints, skips optional-only incompatible packages, persists dependency constraints for warm/frozen/offline replay, and supports warning-only opt-out |
| Built-in vulnerability audit | npm security database | Registry-side data | Proxies to npm audit endpoint | OSV + behavioral analysis + verdict cache |
| Approval-gated weakening of security posture | — | — | — | Weaker CLI flags can require native approval; pulled repo or config-file weakenings are treated as proposals until a short-lived unlock or persistent signed machine approval exists |
| Provenance drift detection on republish | — | Resolve-time trust-rank downgrade refusal (trustedPublisher → provenance → none) | — | Detects publisher-identity drift for stored rich trust bindings; optional trust-policy = "no-downgrade" refuses weaker npm publish trust during resolution and requires continued artifact verification after verified lockfile history |
| Pluggable third-party security scanner protocol (register an npm package as a scanner, run it against the lockfile) | — | — | bunfig.toml > [install.security] scanner = "<pkg>", invoked by bun pm scan | — (built-in triage + audit cover a different surface; not pluggable) |
| Axis | npm | pnpm | bun | lpm |
|---|
| Resolver | Arborist backtracking | Highest-version + workspace-rooted peer resolution | Tree resolution + backtracking | Greedy-fusion (PubGrub legacy arm available) |
| Package store | Content-addressable cache | Content-addressable, versioned virtual store | Content-addressable, hardlinked | Content-addressable; prefers APFS clonefile on macOS, with hardlink/copy fallback |
node_modules layout | Hoisted | Isolated (symlinked virtual store) | Auto: hoisted for single-package, isolated when workspaces detected | Auto: v2 hoisted virtual-store for single packages, isolated for workspaces or default peer-conflict installs |
| Phantom-dependency prevention | Hoisted layout leaks unlisted deps | Isolated by default | In isolated mode | In isolated mode (default for workspaces and peer-conflict installs) |
| Lockfile | package-lock.json v3 | pnpm-lock.yaml v9 | bun.lock (JSONC) | lpm.lock (TOML, authoritative) plus lpm.lockb binary companion when the graph fits the binary format |
| Patched dependencies | — | pnpm patch workflow | bun patch workflow | Native patchedDependencies; reads pnpm's shape for migration |
| Dependency overrides | Yes (overrides field, npm 8+) | Yes | Yes | Honors top-level npm overrides, Yarn resolutions, and lpm.overrides; lpm migrate translates pnpm.overrides |
| Native dependency build-artifact cache | — | Side-effects cache, enabled by default | — | Automatic for eligible strict-sandbox builds on macOS and Linux; content-addressed artifacts are reused only when package graph, platform, Node runtime/ABI, environment, sandbox, and toolchain inputs match |
This is the most lopsided table — three of the four columns are blank for several rows.
| Axis | npm | pnpm | bun | lpm |
|---|
| Secrets vault (E2E-encrypted, secure-store preferred, cloud sync) | — | — | Auto-loads .env, no vault | Per-project and per-environment; prefers the OS secure store with encrypted-file fallback; org sharing, OIDC CI escrow, and client-direct Vercel, Coolify, Fly.io, Railway, and GitHub Actions integrations |
| Zero-config dev server orchestrator | — | — | — | Auto-installs stale deps, loads env, starts services, opens the browser when ready, and starts LPM CLI's browser webhook inspector when tunneling |
| Remote task cache | Use Turborepo / Nx | Use Turborepo / Nx | Use Turborepo / Nx | Local task cache + hosted remote cache; content hashes always, optional HMAC signing via remoteCache.signature, read-only mode, quota / usage status, and env-policy upload guards |
| Local HTTPS with dev-only certificate authority | Use mkcert | Use mkcert | Use mkcert | Built-in CA: status / trust / uninstall / generate. Picked up automatically by the dev server. |
| Local tunneling (public URL to localhost) | Use ngrok | Use ngrok | Use ngrok | Stable claimable domains, webhook capture, replay, and audit log |
| Managed runtime availability | — | Node version pinning | Bun is its own runtime | Auto-installed Node and Bun via lpm.json > runtime; Node also falls back through engines.node, .nvmrc, .node-version |
| Managed linter / formatter | — | — | Formatter exists in the runtime, not the install surface | oxlint + biome as lazy-downloaded plugins, pinned via lpm.json > tools |
| One-off package execution (npx-equivalent) | npx, permanent cache | pnpm dlx, 1-day cache | bunx | lpm dlx / lpx, 1-day cache |
| Built-in bundler | — | — | Yes | No native bundler; lpm bundle uses managed Rolldown, while lpm pack wraps project-local tsdown |
| Built-in test runner | — | — | Yes | No native test engine; lpm test orchestrates Vitest / Jest / Mocha |
| Axis | npm | pnpm | bun | lpm |
|---|
| Source-code delivery (copy package files into the project, shadcn-style) | — | — | — | lpm add — works for any tarball-shipped package on any reachable registry (lpm.dev, npm, private via .npmrc) |
| Dependency selector queries (CSS-like syntax over behavioral tags) | — | — | — | lpm query — :eval, :scripts:not(:built), :root > :network, #express, --assert-none CI gate |
| Dependency-graph visualization | npm ls (text) | pnpm list (text) | bun pm ls (text) | lpm graph / lpm ls — HTML / JSON / dot output, depth filter, lpm why <pkg> reverse-lookup |
| Interactive upgrade picker | — | pnpm update -i | bun update --interactive | lpm upgrade [pkg...] (interactive by default on TTY) — targeted upgrades, peer-impact analysis |
| License inventory and policy gate | third-party tooling | third-party tooling | third-party tooling | lpm licenses — local inventory, --fail-on copyleft,missing, exact --deny <LICENSE> gates |
Programmable resolution hooks (intercept readPackage / afterAllResolved at resolve time) | — | .pnpmfile.cjs | — | — |
| Install-time policy extensions | — | — | — | Local package.candidate extensions evaluate resolved packages before fetch/link and return allow, warn, or block; they do not mutate resolution |
| Workspaces (monorepo) | --workspace selector | Rich --filter pattern syntax | --workspace, --all-workspaces | pnpm-style filter grammar |
| Catalog version pins for monorepos (one declaration, every member references it) | — | pnpm-workspace.yaml > catalog | Catalogs in lockfile | package.json > catalogs, plus pnpm-style pnpm-workspace.yaml catalogs and cleanup |
| Workspace-package deploy (extract one member + transitive deps to a deployable dir) | — | pnpm deploy | — | lpm deploy |
| Migration from other package managers | — | — | Reads npm + yarn lockfiles | One-command lockfile migration from npm / pnpm / Yarn / Bun; pnpm migration also translates overrides, patches, and peer rules |
| Swift Package Manager (SE-0292) | — | — | — | SE-0292-compatible after LPM CLI configures the scope; certificate/trust setup occurs on the first Swift install; CMS signing is available on a best-effort basis |
| Axis | npm | pnpm | bun | lpm |
|---|
| First-party hosted registry | npmjs.org (public and private packages) | — | — | lpm.dev: publish-time security analysis, with optional AI analysis and API-doc extraction; private publishers can opt out of AI processing. Packages are private by default, with pool and marketplace as explicit opt-ins. |
| Sigstore provenance signing on publish | --provenance flag | Auto in CI when OIDC available | — | --provenance flag + auto-OIDC token exchange |
| OIDC trusted-publisher token exchange | GitHub Actions | GitHub Actions + GitLab CI | — | GitHub Actions + GitLab CI |
| 2FA on publish | OTP | OTP | --otp flag | OTP |
.npmrc scope-to-registry routing | Yes | Yes | Yes | Yes — mappings are honored for npm-compatible private registries and JSR mirrors; per-origin authentication is supported |
| Auth-token storage | .npmrc plain text | .npmrc plain text | .npmrc / bunfig.toml plain text | OS keychain preferred; AES-256-GCM encrypted-file fallback; .npmrc honored for compatibility |
| Default registry routing | npmjs.org | npmjs.org | npmjs.org | npm packages go directly to npmjs.org; native jsr: dependencies go to npm.jsr.io; only @lpm.dev/* always routes through lpm.dev |
| Axis | npm | pnpm | bun | lpm |
|---|
| macOS (Intel + Apple Silicon) | Yes | Yes | Yes | Yes |
| Linux (glibc) | Yes | Yes | Yes | Yes |
| Linux (musl / Alpine) | Yes | Yes | Yes | Upcoming official x64 binary through npm, the standalone installer, and GitHub Releases (not included in v0.67.0); ARM64 requires a source build |
| Windows x64 | Yes | Yes | Yes | Yes |
| FreeBSD | Yes | Yes | — | — |
| Self-update | npm install -g npm | pnpm self-update | bun upgrade | lpm self-update — install-method-aware (npm / Homebrew / Cargo / standalone GitHub Releases); 24-hour banner check |
| Implementation language | JavaScript (Node.js) | TypeScript (Rust port underway) | Zig (Rust port underway) | Rust |