Plugin installer: wrong extraction path + infinite recursive nesting for marketplace plugins using plugins/ subdirectory

Status Fixed / completed
Maintainer reply None cached
Activity 4 comments · opened Mar 17, 2026 · closed Apr 9, 2026

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

  1. Add a third-party marketplace pointing to a GitHub repo that uses plugins/<name>/ directory structure (same as claude-plugins-official)
  2. Install a plugin from that marketplace: /plugin install <name>@<marketplace>
  3. Run /reload-plugins
  4. Observe: skill not available, load error reported
  5. Check cache: entire repo root is at install path instead of plugin subdirectory contents
  6. With autoUpdate: true, run /reload-plugins multiple 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.

View original on GitHub ↗

4 Comments

shafqatevo · 6 months ago

Additional Reproduction Path: plugin update with 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

  • Claude Code: latest
  • OS: macOS (Darwin)
  • Install format: owner@repo (no third-party marketplace)

Steps to Reproduce

  1. The plugin repository has its name match the plugin's own identifier — e.g., a GitHub repo named multai containing a plugin also called multai:

``
claude plugin install multai@multai
``

  1. Run an update:

``
claude plugin update multai@multai
``

  1. Inspect the cache (~/.claude/plugins/cache/):

Actual Behavior

The cache path becomes infinitely nested:

cache/multai/multai/0.2.260318/multai/0.2.260318/multai/0.2.260318/...

Nesting continues until the OS path-length limit is exhausted. The cache becomes unrecoverable with standard tools.

Root Cause (Same as this issue)

git clone of the repo named multai creates a multai/ 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

claude plugin uninstall multai@multai
# manually clear ~/.claude/plugins/cache/multai if needed
claude plugin install multai@multai

This avoids the plugin update code 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 update command on a direct owner@repo install rather than a marketplace autoUpdate cycle, but the fix should address both paths.

FrankLedo · 6 months ago

Thanks for closing this as completed! Could you let us know which version includes the fix so we can verify?

rob2universe · 6 months ago

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!

github-actions[bot] · 6 months 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.