Claude Code performs git fetch origin + git reset --hard origin/main on the user's project repo every 10 minutes via programmatic git operations (no external git binary spawned). This silently destroys all uncommitted changes to tracked files. Untracked files survive. Git worktrees are immune.
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
...
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 timer tied to session start time with a 600-second interval. 95+ entries observed across 4 sessions over ~36 hours.
src/lib/api.ts (tracked file) and created .canary-test.txt (untracked file)api.ts silently reverted — modification gone.canary-test.txt (untracked) survivedAt the exact reset time, fswatch on .git/ captured:
23:59:10.349 .git/refs/remotes/origin/HEAD.lock Created IsFile Removed AttributeModified
23:59:10.352 .git/logs/HEAD IsFile Updated
23:59:10.354 .git/refs/heads/main.lock Created IsFile Removed AttributeModified
This is the classic pattern for git fetch origin + git reset --hard origin/main.
lsof confirms the Claude Code CLI process (PID 70111, claude --dangerously-skip-permissions) is the only process with CWD in the affected repo. Two other Claude CLI sessions are in different directories.
Process monitoring at 0.1-second intervals found zero git processes around reset times. The operations are programmatic (libgit2 or similar) within the Claude Code process, confirmed by .git/ lock file creation without any external process.
The worktree reflog shows zero reset: moving to origin entries. The reset targets the main working tree only.
A thorough investigation eliminated all external causes:
| Cause | Verdict | Detail |
|---|---|---|
| Git hooks | Cleared | All .sample (inactive). No husky/lint-staged. |
| Claude Code user hooks | Cleared | Only peon-ping (audio). None reference git. |
| Plugin marketplace updater | Disproven | Deleted ~/.claude/plugins/marketplaces/ — resets continued unchanged. |
| macOS cloud sync | Cleared | No sync tool covers this directory (checked iCloud, Dropbox, Syncthing, Synology, Google Drive). |
| Cron/LaunchAgents | Cleared | No crontab. No LaunchAgent does git operations on this path. |
| Vite/SvelteKit dev server | Cleared | All file writes go to output dirs. Zero git awareness in source. |
| IDE/editors | Cleared | nvim in different repo. No format-on-save. |
| Time Machine | Cleared | Local snapshots are read-only APFS. |
| File watchers | Cleared | No fswatch/entr/watchman/guard running. |
From the compiled binary at /opt/homebrew/Caskroom/claude-code/2.1.87/claude:
hg1() function does ["fetch","origin"] via t_(C8(), _) without explicit CWD, defaulting to process.cwd()io1() function is a git pull wrapper logging git pull: cwd=${H} ref=${_??"default"}fileHistory state tracks {snapshots: [], trackedFiles: new Set, snapshotSequence: 0}Any uncommitted changes to tracked files in the main working tree are silently destroyed every 10 minutes. During a 2-hour session, changes had to be re-applied 3+ times before the cause was identified. The bug is invisible when all changes are committed (the reset is a no-op), making it appear intermittent.
What internal mechanism runs git fetch origin + git reset --hard against process.cwd() every 600 seconds? This could not be determined from the outside due to the compiled binary and lack of sudo for process tracing.
claude install corrupts project git remote URL to anthropics/claude-plugins-official on macOS #32793 — "claude install corrupts project git remote URL" (marketplace git in wrong directory — related but not this specific bug)