Plugin installer: wrong extraction path + infinite recursive nesting for marketplace plugins using plugins/ subdirectory
Summary
The plugin installer has two related bugs when installing plugins from a marketplace that uses the standard plugins/<name>/ subdirectory structure (matching the claude-plugins-official layout).
Environment
- Claude Code version: latest
- OS: macOS Darwin 25.3.0
Bug 1: Wrong extraction path
When the official claude-plugins-official marketplace installs a plugin, it correctly extracts the contents of plugins/<plugin-name>/ into the cache root:
# Correct (claude-plugins-official):
cache/claude-plugins-official/claude-md-management/1.0.0/
├── .claude-plugin/plugin.json ← contents of plugins/claude-md-management/
├── commands/
└── skills/
For a third-party marketplace using the identical plugins/<name>/ structure, the installer instead copies the entire repo root to the cache:
# Broken (third-party marketplace with same structure):
cache/fxl/slack-monitor/0.1.2/
├── CHANGELOG.md ← entire repo root copied
├── LICENSE
├── plugins/ ← plugin content buried here
│ └── slack-monitor/
│ ├── .claude-plugin/plugin.json
│ └── SKILL.md
Because .claude-plugin/plugin.json is not at the cache root, the plugin loader cannot find it and the skill is never registered.
Bug 2: Infinite recursive nesting on auto-update
With autoUpdate: true set in the marketplace config, each update cycle nests the repo root inside itself, producing a deeply recursive directory tree:
cache/fxl/slack-monitor/0.1.2/
└── slack-monitor/
└── 0.1.2/
└── slack-monitor/
└── 0.1.2/
└── ... (repeats dozens of levels deep)
This also produces a "1 error during load" on /reload-plugins and likely causes filesystem performance issues as the tree grows unboundedly.
Steps to Reproduce
- Add a third-party marketplace pointing to a GitHub repo that uses
plugins/<name>/directory structure (same asclaude-plugins-official) - Install a plugin from that marketplace:
/plugin install <name>@<marketplace> - Run
/reload-plugins - Observe: skill not available, load error reported
- Check cache: entire repo root is at install path instead of plugin subdirectory contents
- With
autoUpdate: true, run/reload-pluginsmultiple times and observe recursive nesting growing
Expected Behavior
The installer should extract plugins/<plugin-name>/ contents to the cache root, identical to how it handles claude-plugins-official plugins.
Actual Behavior
- Entire repo root is copied to cache instead of the plugin subdirectory
- Auto-updates recursively nest the repo root inside itself infinitely
- Plugin skill is never registered ("Unknown skill: <name>")
Workaround
Manually delete the corrupted cache (~/.claude/plugins/cache/<marketplace>/) and avoid autoUpdate: true until fixed.
4 Comments
Additional Reproduction Path:
plugin updatewith matching plugin/repo name (no marketplace)This bug also reproduces without a marketplace, using a direct GitHub install where the plugin name equals the repository name.
Environment
owner@repo(no third-party marketplace)Steps to Reproduce
multaicontaining a plugin also calledmultai:``
``claude plugin install multai@multai
``
``claude plugin update multai@multai
~/.claude/plugins/cache/):Actual Behavior
The cache path becomes infinitely nested:
Nesting continues until the OS path-length limit is exhausted. The cache becomes unrecoverable with standard tools.
Root Cause (Same as this issue)
git cloneof the repo namedmultaicreates amultai/subdirectory inside the version folder. The path resolver re-interprets that subdirectory as a new<marketplace>/<plugin>/<version>level, and each subsequent update call clones again one level deeper — producing unbounded recursion.Workaround
This avoids the
plugin updatecode path entirely.Note
This is the same root cause as described in this issue (git clone implicitly creates a directory named after the repo, which the path resolver misinterprets as an additional cache level). The trigger here is the
plugin updatecommand on a directowner@repoinstall rather than a marketplace autoUpdate cycle, but the fix should address both paths.Thanks for closing this as completed! Could you let us know which version includes the fix so we can verify?
Same infinite nesting on claude plugin update where plugin name equals repo name. Exact error:
ENAMETOOLONG: name too long, copyfile
…/cache/<plugin>/<plugin>/0.7.2/<plugin>/0.7.2/<plugin>/0.7.2/…
Workaround confirmed: uninstall + reinstall bypasses the update code path.
Seconding @FrankLedo's question. Thank you!
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.