Skip to content

miro: the plugin ships package-lock.json beside a self-contained bundle, so every consumer's cache installs 188 MB of dev toolchain #4084

Description

@kyle-sexton

Context

An install-state audit on 2026-09-08 (repeated 2026-09-11 in a second container) found ~/.claude/plugins/cache/melodic-software/miro/0.3.15/node_modules at 188 MB / 6,150 files, 63% of the whole ~/.claude tree. The largest packages were biome (69 MB), typescript (28 MB), rolldown (19 MB), esbuild (11 MB), and lightningcss (10 MB). plugins/miro/package.json lists those under devDependencies; plugins/miro/.mcp.json runs node ${CLAUDE_PLUGIN_ROOT}/dist/index.min.js, a committed bundle that needs no node_modules at runtime.

The install is product behaviour, not a bug in Claude Code: plugins-reference.md (fetched 2026-09-11) states that when Claude Code copies a plugin into the cache it installs the plugin's Node dependencies there, runs npm ci --ignore-scripts when a package-lock.json is present, and "You can't turn the automatic install off; no setting or environment variable disables it." npm ci installs devDependencies by default (npm CLI v12 docs). The marketplace entry's source is ./plugins/miro, a path source, so there is no shipped-versus-development split and link mode (command sources only) does not apply.

The plugins/miro/build.mjs header comment says the install copies the plugin verbatim and runs no build step, which the upstream page contradicts; the comment is stale about the cache.

Cost: every fresh install, including every Claude Code on the web container, downloads and writes 188 MB the server never loads.

Proposed work

  • Decide the route; each documented option has a constraint the implementer must weigh:
    • Ship no lockfile Claude Code recognises. Removing package-lock.json outright breaks this repo's own miro CI lane (npm ci in .github/workflows/ci.yml and the Dependabot bundle workflow both require it). Switching the plugin to a lockfile Claude Code skips (upstream lists yarn.lock and pnpm-lock.yaml as skipped) keeps a lockfile but changes the package manager CI uses.
    • Move dependency installation to ${CLAUDE_PLUGIN_DATA} via a SessionStart hook (the pattern plugins-reference.md documents). Keeps package-lock.json and CI intact, but the automatic cache install still runs unless the lockfile is gone, so this alone does not remove the 188 MB.
    • Keep the lockfile and accept the cost, documenting it in the plugin README.
  • Whatever route lands: update the build.mjs header comment to describe the cache install accurately, and add a CI assertion or note that guards the chosen shape.

Acceptance criteria

  • A fresh install of the miro plugin from this marketplace no longer materialises the devDependency toolchain in the consumer's plugin cache, or the README documents the retained cost and why.
  • The miro CI lane (typecheck, lint, test, verify-bundle, stdio smoke test) still passes on the chosen route.
  • The build.mjs header comment matches the upstream-documented cache install behaviour.

References

  • Audit evidence: CSV breakdown by package under the miro 0.3.15 cache directory; du in a second container on 2026-09-11 (188M node_modules, 1.4M dist).
  • plugins-reference.md "plugin caching" section: install command table, npm ci --ignore-scripts, the cannot-turn-off line, the skipped-lockfile line, the ${CLAUDE_PLUGIN_DATA} SessionStart pattern (raw markdown, fetched 2026-09-11).
  • npm CLI v12 docs for npm ci (lockfile required; devDependencies installed unless --omit=dev).
  • plugins/miro/package.json, plugins/miro/.mcp.json, plugins/miro/build.mjs, .claude-plugin/marketplace.json miro entry, .github/workflows/ci.yml miro steps, .github/workflows/dependabot-miro-bundle.yml.
  • Related: claude-ops/audit-install-state size-attribution issue filed alongside this one; closed plugins: project-scope pins accumulate per worktree (15 paths x ~60 plugins, 3 paths gone, 412 cached versions) #3688 is the nearest prior miro packaging item and does not cover this.

Metadata

Field Value
Category unspecified
Area unspecified
Ecosystem unspecified

Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions