[BUG] autoUpdate: true on extraKnownMarketplaces does not re-install plugins

Resolved 💬 2 comments Opened May 23, 2026 by tyroneross Closed May 27, 2026

Plain-language summary

What I noticed. I set autoUpdate: true on my marketplace expecting plugins to stay current automatically. Sessions start, the marketplace catalog refreshes (I can see the git log inside ~/.claude/plugins/marketplaces/<name>/ advancing), but my installed plugins never move forward. No notification, no error — just silent staleness.

What the system can't do. Update plugins automatically. The flag is documented but its effect ends at the catalog metadata refresh. There is no runtime path that propagates a catalog version bump into the registry's installPath. Manual /plugin update <name> works correctly; the automatic counterpart does not.

What that means for me as a user. I cannot trust autoUpdate: true to keep me current — so I either remember to manually update every plugin every session, or I stay on stale code without realizing it. For plugins I actively develop, that means I'm validating my work against yesterday's bug fixes by accident. I ended up writing a ~600-line Python shim that runs on SessionStart to do what autoUpdate: true claims to do. A typical user who hasn't built that compensation has no signal that they're falling behind.

---

What's Wrong?

settings.json lets users register external marketplaces under extraKnownMarketplaces and opt them into "autoUpdate": true. The session-start machinery does refresh each marketplace's local git checkout at ~/.claude/plugins/marketplaces/<name>/ (the catalog updates), but no runtime path then re-installs the per-plugin files into the registry's installPath. As a result, plugins stay pinned at the version they were first installed at, even when the marketplace catalog advertises a newer version and autoUpdate: true is set.

The flag is effectively a no-op for plugin code. Only the catalog metadata refreshes.

What Should Happen?

When autoUpdate: true is set on a marketplace entry, on session start (or on some defined cadence) Claude Code should:

  1. Refresh the marketplace catalog (this already works), AND
  2. For each installed plugin from that marketplace, compare the version field in ~/.claude/plugins/installed_plugins.json against the catalog's declared version.
  3. If they differ, fetch the new version into a fresh cache/<marketplace>/<plugin>/<version>/ directory and atomically swap the registry's installPath to point at it.

/plugin update <name> already performs roughly this for a single plugin on demand. The autoUpdate: true flag should drive the same path automatically.

Steps to Reproduce

  1. Add a github-source marketplace to ~/.claude/settings.json with autoUpdate: true:

``json
"extraKnownMarketplaces": {
"rosslabs-ai-toolkit": {
"source": {
"source": "github",
"repo": "tyroneross/RossLabs-AI-Toolkit"
},
"autoUpdate": true
}
}
``

  1. Install a plugin from it: /plugin install build-loop@rosslabs-ai-toolkit.
  2. Confirm the registry entry in ~/.claude/plugins/installed_plugins.json shows version: "X.Y.Z" and installPath: .../cache/rosslabs-ai-toolkit/build-loop/X.Y.Z/.
  3. Bump the plugin's version in the marketplace's .claude-plugin/marketplace.json (publish a new tag on the upstream repo).
  4. Start a new Claude Code session. Observe:
  • The marketplace's local clone at ~/.claude/plugins/marketplaces/rosslabs-ai-toolkit/ fetches the new commit (catalog metadata updates — verifiable via git log inside that dir).
  • But ~/.claude/plugins/installed_plugins.json is unchanged. installPath still points at the old cache/.../X.Y.Z/ dir.
  • No new cache/<marketplace>/<plugin>/<new-version>/ directory is created.

Expected: a new versioned cache dir is fetched and the registry's installPath + version for that plugin are updated.

Error Messages/Logs

No errors are surfaced — the failure is silent. The plugin continues to function at the old version. There is no log entry indicating that the catalog drift was detected.

To make the gap concrete, here is a third-party shim I wrote on 2026-05-03 to compensate. Its module docstring states the diagnosis verbatim:

marketplace-autoupdate.py

Compensates for Claude Code's broken `autoUpdate: true` flag on extra
known marketplaces. Reads the registry at
~/.claude/plugins/installed_plugins.json, detects drift between each
installed entry and the marketplace catalog's declared version, fetches
the new version into a fresh `cache/<marketplace>/<plugin>/<version>/`
directory, then atomically updates the registry to point at it.

Diagnosis date: 2026-05-03. Underlying gap: settings.json declares
`autoUpdate: true` for a marketplace. The marketplace's local git
checkout under ~/.claude/plugins/marketplaces/<name>/ does refresh, but
no runtime path actually re-installs the per-plugin files into the
registry's `installPath`. This script fills that gap.

The shim is ~600 lines and runs as a SessionStart hook. The fact that an end-user had to write it at all is the bug.

Reproduction confidence

High. I have reproduced it across multiple plugin versions on my own marketplace (tyroneross/RossLabs-AI-Toolkit) over a ~3 week window. Each catalog bump required either /plugin update <name> manually or my shim — autoUpdate: true never moved the registry on its own.

Claude Model

Not relevant (this is a plugin-manager bug, model-independent).

Is this a regression?

I don't know. I have only used extraKnownMarketplaces since April 2026 and have not observed autoUpdate: true work at any point in that window.

Last Working Version

Unknown.

Claude Code Version

2.1.149 (Claude Code)

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

Terminal.app (macOS)

Additional Information

  • Registry file path: ~/.claude/plugins/installed_plugins.json
  • Marketplace checkout path: ~/.claude/plugins/marketplaces/<name>/
  • Versioned cache path: ~/.claude/plugins/cache/<marketplace>/<plugin>/<version>/
  • /plugin update <name>@<marketplace> works correctly when invoked manually — so the install/swap machinery exists; only the auto-driven path is missing.
  • Possibly related: there is also no cleanup of superseded versioned cache dirs (filed as a separate issue).

I'm happy to provide my shim's source as a reference for the expected behavior shape if useful.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗