[BUG] Claude Code plugin update — stale `gitCommitSha`
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
After claude plugin update, the version, installPath, and lastUpdated fields in ~/.claude/plugins/installed_plugins.json correctly reflect the new release, but gitCommitSha retains its plugin install-time value. The field becomes a false witness — tools or humans inspecting it to determine "what commit is currently extracted in the cache" are misled.
This completes the third leg of an architectural cluster: writes to installed_plugins.json are inconsistent across the plugin system's distinct entry points. See Cluster context under Additional Information for the cross-references and unifying diagnosis.
What Should Happen?
After claude plugin update, all of version, installPath, and gitCommitSha should reflect the new release. Specifically, gitCommitSha should match the marketplaces clone's current HEAD — i.e., the result of git -C ~/.claude/plugins/marketplaces/<marketplace> rev-parse HEAD.
Error Messages/Logs
No errors are emitted; this is a silent metadata-staleness bug. Using this field to capture the observable post-state instead:
{
"scope": "project",
"projectPath": "/Users/josh/Desktop/workspace/Konjugieren",
"installPath": "/Users/josh/.claude/plugins/cache/ios-build-verify/ios-build-verify/0.2.1",
"version": "0.2.1",
"installedAt": "2026-05-05T23:44:07.571Z",
"lastUpdated": "2026-05-06T14:08:33.412Z",
"gitCommitSha": "f1f79ca56d64a3502fb2986f9dc44c3ffbe09fef"
}
The `gitCommitSha` shown is the v0.2.0 commit. The marketplaces clone has since advanced to `52e4d6f` (v0.2.1, which is what's actually extracted in the cache at `installPath`).
Steps to Reproduce
- Maintain a plugin in a git repo.
claude plugin install <plugin>@<marketplace> --scope projectfrom a consumer project. NoteversionandgitCommitShaininstalled_plugins.json. - Push commits to the plugin repo, bump
versionin.claude-plugin/plugin.json, push. - In the consumer project:
````
claude plugin marketplace update <marketplace>
claude plugin update <plugin>@<marketplace> --scope project
- Re-inspect the plugin's entry in
installed_plugins.json. Observe:version,installPath,lastUpdatedadvance correctly;gitCommitShais unchanged from step 1.
Claude Model
Opus
Is this a regression?
I don't know
Last Working Version
unknown
Claude Code Version
2.1.131
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
iTerm2
Additional Information
Cluster context
This report is the third reported instance of one architectural pattern: writes to ~/.claude/plugins/installed_plugins.json are inconsistent across the plugin system's distinct entry points. Three distinct triggers each produce a different incomplete write:
| Trigger | Failure mode | Issue |
|---|---|---|
| Project-local marketplace startup-sync | installed_plugins.json not written at all (cache advances; metadata stays at install-time version) | #43763 |
| Marketplace "autoUpdate": true runtime promotion | installed_plugins.json not written at all (UI/skills advance; bundled hooks pinned to old installPath) | #52218 |
| Explicit /plugin update (this report) | version, installPath, lastUpdated all advance correctly; gitCommitSha retains install-time value | (this issue) |
Unifying diagnosis: the registry-write logic is not centralized. Each entry point either skips the write entirely or implements its own partial version of it. #43763's reporter pinpointed function zyA as only checking scope and projectPath; this report adds that even the path which does write most fields (explicit /plugin update) misses one of them. A clean fix consolidates the write into a single function called from all three entry points — resolving the cluster atomically rather than incrementally.
Supporting evidence for fragmentation. In a sample of 8 installed plugins on the reporting machine:
- 5 entries record
gitCommitSha, 3 do not (code-simplifier@claude-plugins-official,query@contextify,swift-lsp@claude-plugins-official). - 1 entry (
playground@claude-plugins-official) recordsversion: "unknown"(literal string).
These divergences are consistent with separate install pipelines emitting different field subsets — the same root cause as the three triggers above, observed in steady-state rather than in transition.
Adjacent (cache-lifecycle) cluster, for triage context. #17361, #14061, #41922, and #51536 all describe cache content/version/cleanup not converging with marketplace state. Distinct from the metadata-write cluster but reinforces the broader picture: the plugin system has multiple under-coordinated state-management paths.
Likely root cause (mechanism specific to this trigger)
The cache directory created by plugin update contains no .git subdirectory — only plugin install-created caches do. Update appears to extract via a non-git path (probably copy-from-working-tree of the marketplaces clone) rather than a git clone, so there's no natural git operation in the update flow that would produce a fresh SHA. None of the three referenced issues mentions this — it's a novel data point that explains why the explicit-update path drops gitCommitSha specifically while #43763 / #52218 drop all fields.
Suggested fix
Architectural (resolves cluster #43763 + #52218 + this issue atomically). Centralize installed_plugins.json writes into a single function. Call it from each of the four entry points that should be updating the registry:
/plugin install/plugin update- Project-local marketplace startup sync (#43763's path)
autoUpdateruntime promotion (#52218's path)
The function reads git -C ~/.claude/plugins/marketplaces/<marketplace> rev-parse HEAD for gitCommitSha, derives version from the cache's extracted plugin.json, and updates lastUpdated from the wall clock.
Localized (resolves only this issue). At the end of /plugin update, append a single git rev-parse HEAD step that refreshes gitCommitSha. Doesn't address #43763 or #52218.
Impact
- Debugging "is my cache on the latest commit?" by reading
gitCommitShamisleads any reader (human or AI agent). - Telemetry / analytics that aggregate by
gitCommitShawill undercount post-update versions. - It's the only commit-level identifier in the install record; without correctness here, the only commit check requires independently comparing the cache against the marketplaces clone.
Environment
- Claude Code (CLI), macOS 15.x (Darwin 24.6.0)
- Plugin:
ios-build-verify@ios-build-verifyv0.2.0 → v0.2.1 - Date observed: 2026-05-06
- (If the form has separate widgets for Claude Code Version / Platform / Operating System / Terminal/Shell / Is-this-a-regression / Last-Working-Version, fill those at submission time — values not pre-known to this draft.)
This issue has 6 comments on GitHub. Read the full discussion on GitHub ↗