[BUG] Plugin update/reinstall never refreshes installed cache for private git marketplaces — panel shows new version, but old code still runs

Status Open
Maintainer reply None cached
Activity 0 comments · opened Aug 28, 2026

Description

Updating a plugin in a private/custom git-based marketplace (pushing a new commit + bumped version in .claude-plugin/plugin.json) is correctly picked up by the Plugins panel's displayed metadata (version number, description, "Last updated" timestamp), but the actual installed plugin cache is never refreshed — none of the normal update paths (toggle off/on, the panel's "reinstall" action from the ⋮ menu, or a full app restart) write any files to disk.

This means the panel can show a plugin as "up to date" at the new version while the code that actually runs is still the old version, with no visible indication of the mismatch.

Repro steps

  1. Have a plugin installed from a private git marketplace (extraKnownMarketplaces in settings.json, source type git).
  2. Locally, edit files in the marketplace's git checkout under ~/.claude/plugins/marketplaces/<marketplace>/plugins/<plugin>/, bump version in .claude-plugin/plugin.json, commit, and git push to the remote.
  3. Open the Plugins panel for that plugin.

Observed:

  • Panel immediately shows the new version, the new description text (I had changed both), and "Last updated: N minutes ago" matching the push time.
  • The "Update" button is greyed out / disabled, implying the plugin is already current.
  1. Check what's actually installed:

``
cat ~/.claude/plugins/installed_plugins.json # still shows old version + old gitCommitSha
ls ~/.claude/plugins/cache/<marketplace>/<plugin>/ # only the old version-numbered directory exists
``

  1. Try to force a refresh:
  • Toggle the plugin off, then on again in the panel.
  • Use the ⋮ menu → reinstall.
  • Fully quit and restart the app.

Result: After each of these, installed_plugins.json's installedAt/lastUpdated/gitCommitSha fields and the cache directory contents are byte-for-byte unchanged (confirmed via stat — same mtimes as the original install, from hours earlier and before any of the above actions). The skill content (SKILL.md) actually loaded and executed by Claude Code in a real task also still reflects the old version — verified by grepping the cache copy for a string I added in the new version, which is absent.

Expected behavior

One of:

  • The "Update" button should be enabled and clickable whenever the marketplace HEAD differs from the installed gitCommitSha, and clicking it (or toggling off/on, or reinstalling) should actually re-fetch and unpack the new version into the cache and update installed_plugins.json.
  • If the panel's displayed "Version"/"Last updated" reflect marketplace-HEAD metadata rather than the installed copy, that should be visually distinguished from the installed version, so users aren't misled into thinking they're running code they aren't.

Environment

  • macOS (Darwin), Claude Code desktop
  • Plugin source: private git marketplace (extraKnownMarketplaces, source: git)
  • Confirmed via direct filesystem inspection (installed_plugins.json, ~/.claude/plugins/cache/...) rather than relying on the panel

Possibly related

  • #83704 — "Desktop plugin stores desync: sessions load stale account-registry copies that shadow current CLI installs; settings Update checks the wrong store and Uninstall deletes from both" — matches my hypothesis that the panel is reading a different store than the actual install.
  • #86700 — "claude plugin install refreshes the marketplace, sees a newer version, and still reports 'already installed' without upgrading"
  • #45810 — "Marketplace update button is disabled/not pressable even when version is outdated"
  • #72162 — "/plugin marketplace update + /reload-plugins does not pick up pushed plugin changes"

Those cover overlapping symptoms; filing separately because this repro is a fully offline-verifiable filesystem check (manifest + cache mtimes unchanged across three distinct update attempts) against a private git marketplace specifically, which may be a distinct code path from the official marketplace.

View original on GitHub ↗