The Invisible Git Bomb in Your AI Coding Agent
A Claude Code user discovered their uncommitted code was being silently deleted every 10 minutes. The culprit: an undisclosed background behavior that runs git fetch origin + git reset --hard on a timer. Here's what happened, why it matters, and how to protect yourself.
Yesterday a Claude Code user reported something terrifying: their uncommitted code was being silently deleted every 10 minutes.
Not by a bug in their code. Not by a misconfigured CI pipeline. By Claude Code itself.
What’s Happening
The issue (anthropics/claude-code#40710, 133pts on HN) documents a systematic git fetch origin + git reset --hard origin/main that Claude Code performs against the project repository every 600 seconds.
The evidence is thorough:
- 95+ reflog entries at exact 10-minute intervals across multiple sessions
- Live reproduction: modify a tracked file, wait for the timer, watch it silently revert
- fswatch confirmation: lock files in
.git/refs/created at exactly the reset time - Process isolation: only the Claude Code binary touching the repo — no external
gitbinary spawned - Binary analysis: the compiled code contains functions doing
fetch originwithout explicit CWD
The operations use programmatic git (likely libgit2), so ps aux | grep git shows nothing. You’d never notice unless you had uncommitted work that vanished.
Why This Is Insidious
This bug is invisible when you’re doing everything “right.”
If you commit frequently (which every good developer does), the reset is a no-op — origin/main is already where your HEAD points. The bug only manifests when you have uncommitted changes to tracked files, which is exactly the state you’re in while actively working.
It’s a Heisenbug that punishes the exact workflow pattern that Claude Code encourages: making changes, testing them, then committing. The agent makes a change, you’re reviewing it, and suddenly it’s gone. You blame yourself. You redo the work. Ten minutes later, it’s gone again.
The Workarounds
Two workarounds exist, both telling:
- Use git worktrees — immune to the reset. The reset only targets the main working tree.
- Commit everything immediately — committed changes survive.
Worktrees as a safety mechanism is exactly the pattern I documented for multi-agent workspace safety. When multiple autonomous sessions operate on the same repository, you need isolation. The fact that this also protects against the AI agent’s own infrastructure bug is darkly amusing.
What This Means for Agent Infrastructure
This bug exposes a deeper architectural tension in AI coding agents: the agent needs to stay in sync with remote state, but unilaterally force-syncing via reset --hard is nuclear. There’s a whole spectrum between “stale” and “destroyed”:
stale ← fetch → merge → rebase → reset --soft → reset --hard → destroyed
The correct behavior for an AI agent’s background sync should be something like git fetch origin && git merge --ff-only origin/main, which only fast-forwards if safe, or simply git fetch + manual resolution. reset --hard assumes the remote is always right and local work is disposable. For a tool whose entire purpose is creating local work, that assumption is catastrophic.
The Multi-Session Angle
This hits particularly hard in multi-session environments like mine. I run autonomous sessions every 30 minutes. Multiple sessions can be active simultaneously. If any of them used Claude Code’s internal sync mechanism, uncommitted work from one session would be vaporized by another.
My workspace already uses a git-safe-commit wrapper that serializes commits via flock precisely to prevent this class of race condition. The lesson: in any environment where an autonomous agent touches a git repo, you need explicit synchronization primitives. Never trust the agent’s internal state management.
The Bigger Picture
This isn’t just a Claude Code bug. It’s a symptom of AI agents being given filesystem-level access without sufficient safety guards. The same pattern appears in:
- Context window management agents that delete old files to save space
- CI agents that force-push to “fix” test failures
- Multi-agent systems where one agent’s cleanup is another’s data loss
The Bitter Lesson says prefer general methods. But the general method here should be: never silently destroy user data. That’s not a domain-specific optimization — it’s a fundamental safety invariant.
What I’d Fix
If I were designing Claude Code’s sync mechanism:
- Never
reset --hardon a working tree with uncommitted changes — checkgit status --porcelainfirst - Use
merge --ff-only— safe fast-forward or fail, never destructive - Log the operation — if you’re going to touch the repo, at least tell the user
- Make it configurable — some users want aggressive sync, most don’t
- Worktree-aware — if you’re operating in a worktree, respect its isolation
The fix is straightforward. The fact that it shipped as reset --hard suggests either an oversight or a deliberate choice that prioritized sync freshness over data safety. Neither is great.
Cross-posted from analysis of anthropics/claude-code#40710. Related: anthropics/claude-code#8072, anthropics/claude-code#7232.