Plugin update is never idempotent for version-less plugins: 10 first-party marketplace plugins report "updated"/"refreshed from source" on every check
Environment
- Claude Code 2.1.202, macOS (darwin arm64)
- Marketplace: claude-plugins-official
Bug
Ten first-party plugins in claude-plugins-official ship without a version field in their plugin.json: pr-review-toolkit, code-review, serena, plugin-dev, hookify, playwright, mcp-server-dev, frontend-design, mcp-tunnels, feature-dev. They register in ~/.claude/plugins/installed_plugins.json as "version": "unknown".
For a version-less plugin, claude plugin update never concludes it is current — it unconditionally re-copies from source and reports success, so every update pass (including the automatic session-start check) reports these ten as updated. Users with the official marketplace installed see a persistent "10 plugins updated" style notice on every launch even when nothing changed.
Reproduction (deterministic)
$ claude plugin update pr-review-toolkit@claude-plugins-official
✔ Plugin "pr-review-toolkit" refreshed from source for scope user. Restart to apply changes.
$ claude plugin update pr-review-toolkit@claude-plugins-official # immediately again, zero changes
✔ Plugin "pr-review-toolkit" refreshed from source for scope user. Restart to apply changes.
Versioned control behaves correctly:
$ claude plugin update superpowers@claude-plugins-official
✔ superpowers is already at the latest version (6.1.1).
Corroborating: all ten version-less plugins carry an identical lastUpdated timestamp (to the millisecond) in installed_plugins.json — one pass re-stamps the whole set every time.
Enumerate affected plugins:
jq -r '.plugins | to_entries[] | [.key, (.value[0].version // "NO-VER")] | @tsv' ~/.claude/plugins/installed_plugins.json | grep unknown
Expected
A no-op update check reports up-to-date and leaves lastUpdated untouched.
Impact
- Misleading "N plugins updated / restart to apply" noise on every session start for anyone using the official marketplace.
- Unnecessary re-copy I/O per check for ten plugins.
- Update reporting becomes an unreliable signal (real updates are indistinguishable from no-ops).
Suggested fixes (either resolves it)
- CLI: for version-less plugins, compare the marketplace source's
gitCommitSha(already stored per install entry) and report up-to-date when unchanged, instead of unconditionally refreshing. - Marketplace: add
versionfields to the ten first-party plugin.json manifests.
🤖 Generated with Claude Code