Docs: plugin installation silently runs `bun install`/`npm ci` — automatic dependency installation is undocumented

Status Fixed / completed
Maintainer reply None cached
Activity 3 comments · opened Aug 7, 2026 · closed Aug 11, 2026
Update 2026-08-07: re-verified on v2.1.224 — behavior unchanged (identical installer table in the binary, and a live test with a minimal three-plugin marketplace reproduced all three cases: bun.lock → auto-install, no lockfile → nothing, yarn.lock → silently skipped). Details in this comment. Also newly observed: claude plugin uninstall does not remove the cached version directory, so auto-installed node_modules persists on disk after uninstall.

Summary

When Claude Code installs a plugin from a marketplace, it automatically installs the plugin's Node.js dependencies into the cached copy — but this behavior is not mentioned anywhere in the plugin docs (plugins, plugins-reference, discover-plugins) or the CHANGELOG. Developers installing plugins have no way to know that a plugin can pull hundreds of MB of node_modules onto disk, and plugin authors have no documented guidance on which lockfiles are supported.

Observed behavior (Claude Code v2.1.220, re-verified on v2.1.224, macOS)

Installing the qmd plugin (marketplace repo ~11 MB, 179 items) produced a cache directory of ~230 MB / 9,000+ items at ~/.claude/plugins/cache/qmd/qmd/0.1.0/ — 212 MB of which is a node_modules created by an automatic bun install within a minute of install. No user or session ran the install.

Note: this is not specific to qmd — it's just the plugin that surfaced the behavior. Any plugin shipping a package.json plus a supported lockfile triggers the automatic install. This was confirmed with a synthetic minimal marketplace containing three one-dependency test plugins (see the v2.1.224 verification comment): the bun.lock plugin got its dependencies auto-installed, while otherwise-identical plugins with no lockfile or a yarn.lock did not.

From observed behavior and strings in the bundled CLI, the logic appears to be:

  1. After copying the plugin into the cache, if the plugin directory contains a package.json, check for a lockfile:
  • bun.lock / bun.lockb → bun install --frozen-lockfile --ignore-scripts
  • npm-shrinkwrap.json / package-lock.json → npm ci --ignore-scripts
  1. yarn.lock / pnpm-lock.yaml are explicitly skipped with: "Skipped: yarn/pnpm lockfiles are not supported (resolution-time hooks bypass --ignore-scripts). Use bun or npm."
  2. The install runs with a 60-second timeout; --ignore-scripts means no lifecycle/postinstall scripts execute.
  3. No package.json (or no supported lockfile) → nothing runs.

Corroborating datapoint: claude-mem 13.12.4 ships bun.lock and has a 473 MB node_modules in cache; 13.4.0 (same plugin, package.json but no lockfile) has none.

Why this should be documented

  • Disk usage: each cached plugin version gets its own full dependency install and old versions are not cleaned up — three qmd versions × 212 MB each on this machine. Uninstalling a plugin also leaves its cached version directory (including node_modules) on disk. Users deserve to know where the space goes and that it's expected.
  • Plugin author guidance: authors need to know that shipping a bun.lock/package-lock.json opts them into automatic installs, that yarn/pnpm lockfiles are rejected, and that postinstall scripts will never run (so native builds relying on them will not work).
  • Security posture (worth advertising!): --ignore-scripts + frozen/ci installs is a deliberate, good design — no plugin-supplied code executes at install time. Documenting it would answer an obvious supply-chain question.
  • Update semantics: claude plugin update and marketplace auto-update re-run this install for each new version directory, which affects update duration and disk growth.

Suggested doc changes

  • A "Plugin dependencies" section in the plugins reference covering: trigger conditions, supported lockfiles, exact commands/flags, the 60 s timeout, yarn/pnpm rejection, and failure behavior.
  • A note in the marketplace/install docs about per-version cache layout and disk implications.
  • Optionally: document whether a setting exists (or add one) to disable automatic dependency installation.

Environment

  • Claude Code v2.1.220 (original report) and v2.1.224 (re-verified 2026-08-07), macOS (darwin arm64)

View original on GitHub ↗

3 Comments

rymalia · 2 months ago

Re-verified on v2.1.224 (2026-08-07) — behavior unchanged.

Two layers of confirmation:

  1. Binary: the v2.1.224 bundle contains the identical lockfile→installer table (bun.lock/bun.lockb → bun install --frozen-lockfile --ignore-scripts; npm-shrinkwrap.json/package-lock.json → npm ci --ignore-scripts) and the same yarn/pnpm rejection string.
  1. Live end-to-end test: built a minimal local marketplace with three plugins, each declaring left-pad@1.3.0 as a dependency, and installed them through the v2.1.224 CLI:

| Test plugin | Ships | Result in cache |
|---|---|---|
| dep-test | package.json + bun.lock | node_modules/left-pad@1.3.0 auto-installed |
| no-lock-test | package.json only | no node_modules |
| yarn-test | package.json + yarn.lock | no node_modules — silently skipped; plugin install still reports success with no warning shown to the user |

New observation while testing: claude plugin uninstall does not remove the cached version directories — ~/.claude/plugins/cache/<marketplace>/<plugin>/<version>/ (including its auto-installed node_modules) remains on disk after uninstall until deleted manually. This compounds the disk-usage concern in the issue body: uninstalled plugins keep their full dependency trees indefinitely.

rymalia · 2 months ago

Thanks @sarahdeaton for closing this out — I checked plugins-reference on the documentation site and see the new Node.js package dependencies section covers everything from the report: the lockfile → installer table, the yarn/pnpm rejection rationale, the 60-second timeout, and the "can't be disabled" note.

Also glad to see claude plugin uninstall --prune / orphaned-dependency cleanup landed — that addresses the follow-up I found in testing (uninstall leaving node_modules behind indefinitely). 👌

github-actions[bot] · 16 days ago

This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.