claude-code - 💡(How to fix) Fix Plugin caching: `fallback to full copy` drops `entry.skills` + `Removing old cached version` wipes sibling plugins (url-source, name collision) [1 comments, 2 participants]

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…
GitHub stats
anthropics/claude-code#55493Fetched 2026-05-03 04:51:55
View on GitHub
Comments
1
Participants
2
Timeline
5
Reactions
0
Timeline (top)
labeled ×4commented ×1

Two related bugs in plugin caching that surface together when a marketplace plugin uses url-based source and the plugin name equals the marketplace name (which is the natural pattern for "single-plugin marketplaces" where the repo itself is the plugin):

  1. fallback to full copy branch drops entry.skills — plugin loads with zero skills, slash commands disappear.
  2. Removing old cached version deletes a shared parent directory, wiping other plugins of the same marketplace whose caches happen to live as siblings.

Root Cause

Two related bugs in plugin caching that surface together when a marketplace plugin uses url-based source and the plugin name equals the marketplace name (which is the natural pattern for "single-plugin marketplaces" where the repo itself is the plugin):

  1. fallback to full copy branch drops entry.skills — plugin loads with zero skills, slash commands disappear.
  2. Removing old cached version deletes a shared parent directory, wiping other plugins of the same marketplace whose caches happen to live as siblings.

Fix Action

Workaround

Use path-based "./plugins/<name>" for the url-based plugin's source. This avoids both bugs at once: the normal-branch path is taken (no fallback), and no Removing old cached version step runs against the marketplace cache root.

Code Example

{
  "name": "kb-catchtable",
  "plugins": [
    { "name": "kb-catchtable",
      "source": { "source": "url", "url": "https://github.com/CatchTable/kb-catchtable.git" } },
    { "name": "wip",
      "source": "./plugins/wip" }
  ]
}

---

[DEBUG] Caching plugin from source: {"source":"url","url":".../kb-catchtable.git"} to temporary path .../temp_git_<X>
[DEBUG] Copying source directory ./plugins/wip for plugin wip@kb-catchtable
[DEBUG] Successfully cached plugin wip@kb-catchtable at .../cache/kb-catchtable/wip/0.1.0     ← wip OK
[DEBUG] Copied plugin wip to versioned cache: .../cache/kb-catchtable/wip/0.1.0

[DEBUG] Cloned repository from .../kb-catchtable.git to .../temp_git_<X>
[DEBUG] Removing old cached version at .../cache/kb-catchtable                                  ← BUG #2
[DEBUG] Successfully cached plugin kb-catchtable to .../cache/kb-catchtable
[DEBUG] Using git SHA for kb-catchtable@kb-catchtable: <sha>
[DEBUG] Copying plugin kb-catchtable@kb-catchtable to versioned cache (fallback to full copy)BUG #1
[DEBUG] Successfully cached plugin kb-catchtable@kb-catchtable at .../cache/kb-catchtable/kb-catchtable/<sha>
[DEBUG] Plugin kb-catchtable has no entry.skills defined                                          ← BUG #1
[DEBUG] Total plugin skills loaded: 0 (for kb-catchtable)
RAW_BUFFERClick to expand / collapse

Summary

Two related bugs in plugin caching that surface together when a marketplace plugin uses url-based source and the plugin name equals the marketplace name (which is the natural pattern for "single-plugin marketplaces" where the repo itself is the plugin):

  1. fallback to full copy branch drops entry.skills — plugin loads with zero skills, slash commands disappear.
  2. Removing old cached version deletes a shared parent directory, wiping other plugins of the same marketplace whose caches happen to live as siblings.

Environment

  • Claude Code: 2.1.123 (native installer, macOS Darwin 25.5.0)

Reproduction (100% deterministic, single instance, clean state)

Marketplace kb-catchtable declares two plugins (one url-based, one path-based) — multi-plugin marketplace, but the url-based plugin's name equals the marketplace name:

{
  "name": "kb-catchtable",
  "plugins": [
    { "name": "kb-catchtable",
      "source": { "source": "url", "url": "https://github.com/CatchTable/kb-catchtable.git" } },
    { "name": "wip",
      "source": "./plugins/wip" }
  ]
}

Steps:

  1. claude /plugin marketplace add CatchTable/kb-catchtable
  2. claude /plugin install kb-catchtable@kb-catchtable (path-based wip is auto-installed too)
  3. Observe debug log

Debug log (relevant lines, single Claude Code instance, freshly cleared cache and installed_plugins.json):

[DEBUG] Caching plugin from source: {"source":"url","url":".../kb-catchtable.git"} to temporary path .../temp_git_<X>
[DEBUG] Copying source directory ./plugins/wip for plugin wip@kb-catchtable
[DEBUG] Successfully cached plugin wip@kb-catchtable at .../cache/kb-catchtable/wip/0.1.0     ← wip OK
[DEBUG] Copied plugin wip to versioned cache: .../cache/kb-catchtable/wip/0.1.0

[DEBUG] Cloned repository from .../kb-catchtable.git to .../temp_git_<X>
[DEBUG] Removing old cached version at .../cache/kb-catchtable                                  ← BUG #2
[DEBUG] Successfully cached plugin kb-catchtable to .../cache/kb-catchtable
[DEBUG] Using git SHA for kb-catchtable@kb-catchtable: <sha>
[DEBUG] Copying plugin kb-catchtable@kb-catchtable to versioned cache (fallback to full copy)   ← BUG #1
[DEBUG] Successfully cached plugin kb-catchtable@kb-catchtable at .../cache/kb-catchtable/kb-catchtable/<sha>
[DEBUG] Plugin kb-catchtable has no entry.skills defined                                          ← BUG #1
[DEBUG] Total plugin skills loaded: 0 (for kb-catchtable)

After this sequence, cache/kb-catchtable/wip/0.1.0/ is gone as a side effect of the Removing old cached version step (BUG #2), even though wip was cleanly cached via path-based source moments earlier.

Bug 1 — fallback to full copy branch drops entry.skills

The cache path of the initial git clone is cache/<marketplace_name>/. The versioned cache target is cache/<marketplace_name>/<plugin_name>/<version>/. When marketplace_name == plugin_name, the versioned target's parent is the initial-clone target itself, which is already populated. Atomic rename fails, the code takes the Copying plugin ... to versioned cache (fallback to full copy) branch, and along that branch the entry.skills defaulting / skillsPath inference performed on the normal branch is missing:

  • Normal branch (e.g. adlc@claude-plugins-official where marketplace name ≠ plugin name): Using versioned cached plugin ... → Loaded N skills.
  • Fallback branch (this case): produces a directory on disk but registers the plugin with skillsPath=none, skillsPaths=0 paths even when plugin.json declares "skills": ["./skills/"] explicitly.

Bug 2 — Removing old cached version wipes sibling plugins

When the url-based plugin is cached, Removing old cached version at .../cache/<marketplace_name> deletes the entire cache/<marketplace_name>/ directory before recreating it. In a multi-plugin marketplace, sibling plugins of that same marketplace are stored as cache/<marketplace_name>/<sibling>/<version>/ and get wiped collaterally — even when they were cached via a completely different source (path-based) and are not being refreshed.

Reproduction shows wip's cache/kb-catchtable/wip/0.1.0/ is destroyed, then never re-created in the same session, leaving wip in a broken state until the next refresh.

Workaround

Use path-based "./plugins/<name>" for the url-based plugin's source. This avoids both bugs at once: the normal-branch path is taken (no fallback), and no Removing old cached version step runs against the marketplace cache root.

Why these haven't surfaced widely

  • "Plugin name == marketplace name" is the natural shape of single-plugin marketplaces (where the repo is the plugin). It is less common than multi-plugin marketplaces with cache/<marketplace>/<plugin>/... paths that don't collide.
  • Multi-plugin marketplaces that also use url-based source for one of their plugins with this exact name collision are even rarer. So 100%-deterministic is masked by pattern rarity.

Suggested fix direction

  1. Bug 1: In the fallback-copy branch, run the same entry.skills defaulting / skillsPath inference as the normal branch, so the two are observationally equivalent.
  2. Bug 2: Scope Removing old cached version to the plugin's own versioned subdirectory (cache/<marketplace>/<plugin>/<version>/) instead of cache/<marketplace>/, so unrelated sibling plugins are not affected.
  3. (Defensive) Use a marketplace-independent versioned cache root (e.g. cache/_versioned/<plugin>/<version>/) so neither cache path collisions nor sibling-plugin collateral damage are possible.

Issue authored with assistance from Claude. Reproduction was captured against a single Claude Code instance with cleared cache and no installed_plugins.json entry, ruling out multi-instance race conditions. Logs available on request. Maintainer verification welcome.

extent analysis

TL;DR

To fix the plugin caching issues, modify the caching logic to handle cases where the plugin name equals the marketplace name, ensuring that entry.skills are not dropped and sibling plugins are not deleted.

Guidance

  • Identify and separate the caching logic for plugins with the same name as their marketplace to prevent cache path collisions.
  • In the fallback-copy branch, implement the same entry.skills defaulting and skillsPath inference as the normal branch to prevent skills from being dropped.
  • Update the Removing old cached version step to scope deletion to the plugin's own versioned subdirectory, rather than the entire marketplace cache directory, to prevent sibling plugins from being deleted.
  • Consider using a marketplace-independent versioned cache root to prevent cache path collisions and sibling-plugin collateral damage.

Example

No code snippet is provided as the issue description does not include specific code that needs to be modified. However, the suggested fix direction provides a clear outline of the necessary changes.

Notes

The provided workaround of using path-based sources for url-based plugins can temporarily avoid the issues, but a proper fix is necessary to handle all cases. The rarity of the "plugin name == marketplace name" pattern and multi-plugin marketplaces with url-based sources may have contributed to these issues not being widely reported.

Recommendation

Apply the suggested fix direction to modify the caching logic and prevent the issues from occurring. This approach addresses both bugs and provides a more robust caching system.

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…

Still need to ship something?

×6

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

Back to top recommendations

TRENDING