Plugin marketplace updater runs git reset --hard against user's project repo every 10 minutes
Summary
Claude Code's plugin marketplace refresh mechanism runs git fetch origin + git reset --hard origin/main every 10 minutes. When the marketplace clone at ~/.claude/plugins/marketplaces/claude-plugins-official/ is broken (missing .git directory), these git commands execute against the user's project repo instead, silently destroying all uncommitted changes to tracked files.
Environment
- Claude Code version: 2.1.87
- OS: macOS 15.4 (Darwin 25.3.0)
- Shell: zsh
Root Cause
The marketplace clone directory exists but has no .git:
$ ls -la ~/.claude/plugins/marketplaces/claude-plugins-official/.git
No such file or directory
$ ls ~/.claude/plugins/marketplaces/claude-plugins-official/
external_plugins/ plugins/ README.md
The marketplace config confirms periodic refresh is active:
{
"claude-plugins-official": {
"source": { "source": "github", "repo": "anthropics/claude-plugins-official" },
"installLocation": "/Users/john/.claude/plugins/marketplaces/claude-plugins-official",
"lastUpdated": "2026-03-29T21:25:55.704Z"
}
}
Debug logs confirm the mechanism does git pull:
[DEBUG] git pull: cwd=/Users/john/.claude/plugins/marketplaces/claude-plugins-official ref=default
[DEBUG] Successfully refreshed marketplace: claude-plugins-official
When the marketplace clone's .git is missing, the fallback code path runs git operations without an explicit cwd parameter, so they execute against the user's current working directory (their project repo). Analysis of the compiled binary shows the marketplace pull function does git fetch origin + git reset --hard origin/main, and the fetch function (hg1()) calls git without specifying a cwd.
Evidence
Git reflog: 95+ entries at exact 10-minute intervals
e8ea2c9 HEAD@{2026-03-29 22:19:09 +0200}: reset: moving to origin/main
e8ea2c9 HEAD@{2026-03-29 22:09:09 +0200}: reset: moving to origin/main
e8ea2c9 HEAD@{2026-03-29 21:59:09 +0200}: reset: moving to origin/main
e8ea2c9 HEAD@{2026-03-29 21:49:09 +0200}: reset: moving to origin/main
e8ea2c9 HEAD@{2026-03-29 21:39:09 +0200}: reset: moving to origin/main
...
8792b6c HEAD@{2026-03-29 16:55:41 +0200}: reset: moving to origin/main
8792b6c HEAD@{2026-03-29 16:45:41 +0200}: reset: moving to origin/main
...
32aa7c7 HEAD@{2026-03-28 15:47:36 +0100}: reset: moving to origin/main
32aa7c7 HEAD@{2026-03-28 15:37:36 +0100}: reset: moving to origin/main
The second offset is consistent within each session but varies between sessions (:08, :36, :41, :09), confirming a setInterval(fn, 600000) tied to session start time. 95+ entries observed across 4 sessions over ~36 hours.
Live reproduction
- Modified
src/lib/api.ts(tracked file) and created.canary-test.txt(untracked file) - Monitored every 15 seconds
- At the next 10-minute mark,
api.tssilently reverted — the modification was gone .canary-test.txt(untracked) survived- Reproduced consistently across 4 consecutive 10-minute cycles
No external git binary spawned
Process monitoring at 0.1-second intervals found zero git processes around reset times. fswatch on .git/ detected lock file operations (.git/refs/remotes/origin/HEAD.lock, .git/refs/heads/main.lock) at exact reset times, consistent with programmatic git operations (libgit2 or similar) within the Claude Code Node.js process.
Worktrees are immune
The worktree reflog shows zero reset: moving to origin entries. The marketplace updater's git commands execute against the main working tree only.
What was ruled out
A thorough investigation eliminated all other causes:
- Git hooks — all inactive (
.sampleonly), no husky/lint-staged - Claude Code user hooks — only peon-ping audio notifications, none reference git
- macOS mechanisms — no cloud sync, cron, LaunchAgents, or file watchers covering the project
- Vite/SvelteKit dev server — traced all file-writing code paths; writes only to output directories
- IDE/editors — no format-on-save, no auto-restore configured
- File history/checkpoint system — uses
writeFilefor restores, not git operations; not the cause
Impact
Any uncommitted changes to tracked files are silently destroyed every 10 minutes. This caused significant rework during a 2-hour session where changes had to be re-applied 3+ times. The bug is invisible when all changes are committed (the reset is a no-op), making it appear intermittent.
Suggested fix
The marketplace refresh function should:
- Verify the target directory is a valid git repo (has
.git) before running git commands - Always pass an explicit
cwdorgit -C <path>to git operations - Never fall back to the session's working directory for marketplace git operations
- If the clone is broken, re-clone it rather than running git commands against an unknown repo
Workarounds
- Use git worktrees — confirmed immune
- Commit frequently — committed changes survive the reset
- Possibly: delete the broken marketplace clone (
rm -rf ~/.claude/plugins/marketplaces/claude-plugins-official/) to force a fresh clone with a proper.git(untested)
Related issues
- #32793 — "
claude installcorrupts project git remote URL to anthropics/claude-plugins-official on macOS" (same root cause: marketplace git commands in wrong directory) - #8072 — "Critical Bug: Code Revisions Being Repeatedly Reverted"
- #7232 — "CRITICAL: Claude executed git reset --hard without authorization causing data destruction"
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗