Files
openclaw/docs/gateway/security/dependency-locking.md
Peter Steinberger f6131a4fbf build(deps): remove npm shrinkwrap; mirror pnpm lock into transient package locks (#114006)
* build(deps): remove npm shrinkwrap; mirror pnpm lock into transient package locks

npm 12 removed shrinkwrap (command + tarball/root loading). Delete all 82
committed npm-shrinkwrap.json files and stop publishing lockfiles; keep
pnpm-lock.yaml as the single reviewed dependency boundary. The generator
becomes scripts/generate-npm-package-lock.mjs and feeds plugin bundling via
a transient package-lock.json + npm ci (works on npm 11 and 12). Tarball
validation treats the published 2026.7.2 beta train as a shrinkwrap
transition; self-update npm detection now uses install topology instead of
the shipped shrinkwrap.

* fix(deps): repair lint, deadcode, and test-type lanes for the npm 12 migration

- sort integrity comparisons with an explicit comparator (oxlint)
- keep resolveBunGlobalNodeModules module-local (knip unused-export gate)
- model npm pack --json as npm<=11 array / npm 12 name-keyed object
- default calver destructuring in the tarball test fixture
2026-07-26 01:29:55 -04:00

2.9 KiB

summary, read_when, title
summary read_when title
How OpenClaw reviews dependency changes and packages plugin runtime dependencies
You are reviewing dependency changes or supply-chain risk
You are validating root or plugin npm packages before publishing
You want to understand bundled plugin dependencies
Dependency locking

OpenClaw uses pnpm-lock.yaml as its committed product dependency review boundary. It records the resolved dependency graph used by source checkouts and CI, so transitive changes remain visible in code review.

OpenClaw does not commit npm-format locks for product packages or publish them in package tarballs. npm 12 removed shrinkwrap support, including the npm shrinkwrap command and loading npm-shrinkwrap.json from package roots or dependency tarballs.

The trusted ClawHub release toolchain is a separate exception: .github/release/clawhub-cli/package-lock.json is a committed npm 12 project lock used by release automation. It is not shipped in an OpenClaw package.

Published package behavior

Published OpenClaw plugin packages bundle their runtime dependency files in the tarball by default. Those bytes ship with the plugin and work the same way regardless of whether the operator uses npm, pnpm, or Bun.

Native-heavy plugins opt out of runtime dependency bundling because their dependency trees contain platform-specific or large native artifacts. Those plugins resolve dependencies at install time from exact-pinned direct dependencies. The root openclaw package also resolves dependencies at install time and does not bundle its full dependency tree.

Neither path publishes a lockfile:

  • root and plugin tarballs contain neither npm-shrinkwrap.json nor package-lock.json;
  • pnpm-lock.yaml remains the reviewed source dependency graph;
  • npm package locks exist only transiently while OpenClaw validates package graphs or runs npm ci to assemble a bundled plugin.

Validate npm dependency graphs

The npm-lock checker generates package-lock.json in a temporary directory, applies workspace overrides, and rejects any generated registry version absent from pnpm-lock.yaml. It does not write a lockfile into the checkout.

# Root and every publishable package
pnpm deps:npm-lock:check

# Only packages affected by the current changeset
pnpm deps:npm-lock:check:changed

Inspect a plugin tarball

npm pack @openclaw/discord@<version> --json --pack-destination /tmp/openclaw-plugin-pack
tar -tf /tmp/openclaw-plugin-pack/openclaw-discord-<version>.tgz | grep '^package/node_modules/'
tar -tf /tmp/openclaw-plugin-pack/openclaw-discord-<version>.tgz | grep -E '^package/(npm-shrinkwrap|package-lock)\.json$' && exit 1 || true

The node_modules entries prove that the plugin carries its bundled runtime payload. The final check proves that neither npm lockfile format ships in the tarball.