openclaw - ✅(Solved) Fix [Bug]: openclaw plugins install nests a full copy of openclaw via peer-dep auto-install — 800+ MB bloat and ~15s startup tax per command [1 pull requests]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

openclaw plugins install runs npm install in the plugin directory, and npm 7+'s auto-install-peers behavior installs openclaw itself as a nested dependency of the plugin, dragging in openclaw's entire transitive tree (lancedb, slack, lark, baileys, jimp, pdfjs, koffi, napi-rs, etc.) and adding a ~15-second module-resolution tax to every CLI subcommand.

Root Cause

Devastating-sized native deps (lancedb, koffi, jimp, napi-rs, pdfjs) should never end up in a plugin install just because the plugin peer-depends on openclaw.

Fix Action

Fixed

PR fix notes

PR #69514: fix(cli): omit peer deps during plugin install to prevent nested openclaw bloat

Description (problem / solution / changelog)

Problem

openclaw plugins install runs npm install without --omit=peer. On npm 7+, this causes auto-installation of peer dependencies — including openclaw itself when a plugin declares "peerDependencies": { "openclaw": "*" }.

This nests a full second copy of openclaw (~97 MB) plus its entire transitive tree (lancedb, koffi, jimp, napi-rs, pdfjs, etc.) into the plugin's node_modules/. Observed totals:

  • ~817 MB per affected plugin in node_modules/
  • ~15 s additional startup tax on every CLI invocation (module resolution + native binding loads for the duplicate tree)

Root Cause

The npm install command in installPackageDir() was:

npm install --omit=dev --silent --ignore-scripts

Peer deps were intentionally not omitted because the comment warned that doing so "can strip runtime requirements." While true for some edge cases, the common case (plugin peer-depending on the host openclaw) produces catastrophic bloat with no runtime benefit — the host process already satisfies that peer dep.

Fix

Add --omit=peer to the npm install args:

npm install --omit=dev --omit=peer --silent --ignore-scripts

The host openclaw already satisfies peer dependencies at runtime via its own module resolution path. Plugins that genuinely need specific peers available locally should declare them as regular dependencies instead of peerDependencies.

Changes

  • src/infra/install-package-dir.ts — add --omit=peer flag; update comment to explain rationale
  • src/infra/install-package-dir.test.ts — update test assertion to match new args

Fixes #69498

Changed files

  • src/infra/install-package-dir.ts (modified, +26/-2)

Code Example

$ cat ~/.openclaw/extensions/lossless-claw/package.json | jq '.dependencies, .peerDependencies, .scripts.build'
{
  "@mariozechner/pi-agent-core": "0.66.1",
  "@mariozechner/pi-ai": "0.66.1",
  "@mariozechner/pi-coding-agent": "0.66.1",
  "@sinclair/typebox": "0.34.48"
}
{ "openclaw": "*" }
"esbuild index.ts --bundle --platform=node --target=node22 --format=esm --outfile=dist/index.js --external:openclaw --external:\"@mariozechner/*\" --minify-whitespace"

# Direct deps total ~16 MB. Actual node_modules:
$ du -sh ~/.openclaw/extensions/lossless-claw/node_modules/
817M

# The nested openclaw is a full copy of the host install:
$ du -sh ~/.openclaw/extensions/lossless-claw/node_modules/openclaw/
 97M

# Timing comparison:
$ time openclaw config get meta > /dev/null
openclaw config get meta > /dev/null  31.11s user 2.15s system 143% cpu 23.240 total

$ mv ~/.openclaw/extensions/lossless-claw/node_modules/openclaw /tmp/quarantine/
$ time openclaw config get meta > /dev/null
openclaw config get meta > /dev/null  11.03s user 0.57s system 152% cpu  7.592 total

# (Same 7.6s as when the entire extension dir is hidden — so the nested openclaw is the *entire* tax.)
RAW_BUFFERClick to expand / collapse

Bug type

Regression (worked before, now fails)

Beta release blocker

No

Summary

openclaw plugins install runs npm install in the plugin directory, and npm 7+'s auto-install-peers behavior installs openclaw itself as a nested dependency of the plugin, dragging in openclaw's entire transitive tree (lancedb, slack, lark, baileys, jimp, pdfjs, koffi, napi-rs, etc.) and adding a ~15-second module-resolution tax to every CLI subcommand.

Steps to reproduce

  1. Install OpenClaw 2026.4.15 globally (pnpm/npm — both reproduce).
  2. Run openclaw plugins install @martian-engineering/lossless-claw (any plugin whose package.json declares peerDependencies: { "openclaw": "*" } reproduces this).
  3. du -sh ~/.openclaw/extensions/lossless-claw/node_modules/817 MB.
  4. du -sh ~/.openclaw/extensions/lossless-claw/node_modules/openclaw/97 MB (a nested second copy of openclaw itself).
  5. time openclaw config get meta → ~23s wall, ~32s user CPU. Trivial command, ~15s of which is module-resolution / dlopen overhead from the nested openclaw and its native deps.
  6. Quarantine just the nested copy: mv ~/.openclaw/extensions/lossless-claw/node_modules/openclaw /tmp/.
  7. Re-run time openclaw config get meta7.6s (matches the time when the entire extension is hidden — proving the nested openclaw was the entire 15s tax).

Expected behavior

peerDependencies on openclaw should not cause a second copy of openclaw to be installed inside the plugin's node_modules/. The host CLI is already openclaw and should satisfy the peer at load time. Either:

  • Install plugins with --omit=peer (or --legacy-peer-deps) so npm 7+ doesn't auto-install missing peers, or
  • Symlink/inject the running openclaw into the plugin's node_modules/openclaw so npm sees it as already satisfied, or
  • Configure Node's module resolution so import 'openclaw' from the plugin resolves to the host install path.

Devastating-sized native deps (lancedb, koffi, jimp, napi-rs, pdfjs) should never end up in a plugin install just because the plugin peer-depends on openclaw.

Actual behavior

~/.openclaw/extensions/<plugin>/node_modules/ ends up at hundreds of MBs with a self-referential nested openclaw and its full chat/vector/native-binding dep tree. Every subcommand pays ~15s of import + dlopen overhead. Plugin authors and end-users have no signal anything is wrong — the plugin loads and works, it's just slow on every invocation.

Top offenders observed in ~/.openclaw/extensions/lossless-claw/node_modules/ (lossless-claw itself only declares 4 runtime deps totaling ~16 MB):

ModuleSizeReachable from?
openclaw/97 MB(the nested copy itself)
@lancedb/92 MBnested openclaw only
@jimp/88 MBnested openclaw only
pdfjs-dist/40 MBnested openclaw only
koffi/28 MBnested openclaw only
@napi-rs/25 MBnested openclaw only
@larksuiteoapi/24 MBnested openclaw only
typescript/23 MBdev-dep leak
@img/16 MBnested openclaw only

openclaw plugins inspect lossless-claw reports the install as Source: npm, Spec: @martian-engineering/[email protected], confirming this came from openclaw plugins install, not a manual drop.

OpenClaw version

2026.4.15 (041266a)

Operating system

macOS 26.3.1 (arm64), Node 25.8.0

Install method

npm global (package manager: pnpm per openclaw status)

Model

openai-codex/gpt-5.4

Provider / routing chain

openclaw -> openai-codex

Additional provider/model setup details

Not relevant — the bug is in openclaw plugins install, independent of model/provider routing.

Logs, screenshots, and evidence

$ cat ~/.openclaw/extensions/lossless-claw/package.json | jq '.dependencies, .peerDependencies, .scripts.build'
{
  "@mariozechner/pi-agent-core": "0.66.1",
  "@mariozechner/pi-ai": "0.66.1",
  "@mariozechner/pi-coding-agent": "0.66.1",
  "@sinclair/typebox": "0.34.48"
}
{ "openclaw": "*" }
"esbuild index.ts --bundle --platform=node --target=node22 --format=esm --outfile=dist/index.js --external:openclaw --external:\"@mariozechner/*\" --minify-whitespace"

# Direct deps total ~16 MB. Actual node_modules:
$ du -sh ~/.openclaw/extensions/lossless-claw/node_modules/
817M

# The nested openclaw is a full copy of the host install:
$ du -sh ~/.openclaw/extensions/lossless-claw/node_modules/openclaw/
 97M

# Timing comparison:
$ time openclaw config get meta > /dev/null
openclaw config get meta > /dev/null  31.11s user 2.15s system 143% cpu 23.240 total

$ mv ~/.openclaw/extensions/lossless-claw/node_modules/openclaw /tmp/quarantine/
$ time openclaw config get meta > /dev/null
openclaw config get meta > /dev/null  11.03s user 0.57s system 152% cpu  7.592 total

# (Same 7.6s as when the entire extension dir is hidden — so the nested openclaw is the *entire* tax.)

Impact and severity

  • Affected: every plugin that declares peerDependencies: { "openclaw": "*" } (or any version range) installed via openclaw plugins install on a machine with npm 7+.
  • Severity: Medium. Plugins still load and work; UX is significantly degraded. ~15s added latency on every CLI invocation, plus ~700 MB of unneeded disk per such plugin.
  • Frequency: Always reproduces on the configurations above. 3/3 timed openclaw status runs were ~19s wall (vs. ~4s expected); 3/3 trivial commands like config get meta were ~23s.
  • Consequence: CLI feels broken, users assume openclaw itself is slow, plugin authors get blamed for slow startup that's not their fault. Plus large unnecessary disk consumption per plugin.

Additional information

This is the unintended consequence of the fix for #53517 ("openclaw plugins install does not install peer dependency"). That fix made openclaw plugins install properly run npm install, which under npm 7+ auto-installs peer deps. For plugins whose peer is openclaw itself, that means installing a fresh second copy of the host CLI as a child of the plugin — recursive in spirit, since openclaw is what's installing the plugin.

Suggested fix: openclaw plugins install should pass --omit=peer to npm (and resolve the host's openclaw via symlink, hoist, or NODE_PATH for plugins that genuinely need to import 'openclaw' at runtime). Probably also --omit=dev — TypeScript leaked in here as a 23 MB devDep.

extent analysis

TL;DR

To fix the issue, openclaw plugins install should be modified to pass --omit=peer to npm to prevent auto-installation of peer dependencies, including the host OpenClaw itself.

Guidance

  • Identify the openclaw plugins install command and modify it to include the --omit=peer flag to prevent npm from auto-installing peer dependencies.
  • Consider using --omit=dev as well to prevent devDependencies like TypeScript from being installed.
  • Verify the fix by checking the size of the node_modules directory after installing a plugin and measuring the execution time of a trivial command like openclaw config get meta.
  • If the issue persists, try symlinking or hoisting the host OpenClaw to make it visible to plugins that need to import it at runtime.

Example

No code snippet is provided as the issue is related to the openclaw plugins install command and its interaction with npm.

Notes

The suggested fix assumes that the openclaw plugins install command is using npm 7+ and that the --omit=peer flag is supported. Additionally, the fix may require further modifications to ensure that plugins that genuinely need to import OpenClaw at runtime can still do so.

Recommendation

Apply the workaround by modifying the openclaw plugins install command to include the --omit=peer flag, as this is a more straightforward and less invasive solution compared to upgrading or making significant changes to the OpenClaw codebase.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

peerDependencies on openclaw should not cause a second copy of openclaw to be installed inside the plugin's node_modules/. The host CLI is already openclaw and should satisfy the peer at load time. Either:

  • Install plugins with --omit=peer (or --legacy-peer-deps) so npm 7+ doesn't auto-install missing peers, or
  • Symlink/inject the running openclaw into the plugin's node_modules/openclaw so npm sees it as already satisfied, or
  • Configure Node's module resolution so import 'openclaw' from the plugin resolves to the host install path.

Devastating-sized native deps (lancedb, koffi, jimp, napi-rs, pdfjs) should never end up in a plugin install just because the plugin peer-depends on openclaw.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING