The Day My AI Agent Deleted 29 Git Worktrees

What happens when you rubber-stamp an AI agentâs suggestion to âclean upâ your git worktrees, and the agent uses --force on all of them.
I asked Claude Code to remove one stale git worktree. Thirty seconds later, all 29 of my active worktrees were gone, along with every uncommitted change in them.
What happened
I use Claude Code daily to work on Mergifyâs dashboard. Claude Code can create isolated git worktrees for each task, so your main branch stays clean. Over a few weeks, Iâd accumulated around 30 of these, each on its own branch, several with uncommitted work-in-progress.
One of them, gifted-babbage, was stale. The directory had been deleted from disk, but git still referenced it. Every time I tried to git checkout main, git complained that main was already checked out there. So I asked Claude to remove it:
âCan you remove the worktree .claude/worktrees/gifted-babbage please?â
Claude found it, removed it with git worktree remove --force. Done. Then it added, unprompted:
âBy the way, you have ~30 accumulated worktrees. Want me to clean up and remove the ones you donât need anymore?â
I said: âYeah go ahead.â
What I meant was: look through them, figure out which ones are stale, maybe show me a list. What Claude did:
for wt in .claude/worktrees/*/; do
name=$(basename "$wt")
echo "Removing $name..."
git worktree remove --force ".claude/worktrees/$name"
done
A for loop with --force, no filter, no confirmation. Every single worktree, wiped in one pass. Without --force, git worktree remove refuses to delete worktrees that have uncommitted changes. With it, git doesnât even warn you. The agent had used --force for the first removal (where it was needed, the directory was already gone) and carried the flag into the loop without reconsidering.
Partial implementations, half-finished features. Gone. No reflog, no stash.
Claudeâs response was to reassure me:
âThe branches still exist. Only the working directories were deleted.â
Technically correct, completely beside the point. The branches had my last commits. The worktrees had my current work.
Why this is more interesting than âAI did something dumbâ
I said âyeah go aheadâ without thinking about what âclean up all worktreesâ actually meant. I didnât ask âwhich ones?â I read the offer, mentally translated it to âtidy up the obvious junk,â and hit enter. The agent interpreted my words literally. Iâm the one who didnât mean what I said.
But a rogue script doesnât create the feeling of being understood. When Claude offered to clean up, it used casual language, it referenced the context of what weâd just done together, it scoped the proposal to âthe ones you donât need anymore.â Every signal said âI get what you want.â Conversational interfaces donât just execute commands. They act like they understand you. And that act is convincing enough that you stop double-checking.
The moment that crystallized this for me was Claudeâs reassurance after the damage. It had just force-deleted my uncommitted work, and its response was a git tutorial about how branches survive. That gap between the tone (helpful, reassuring) and the reality (your files are gone forever) is disorienting in a way that a terminal printing an error never is. A terminal doesnât pretend to understand your situation.
A human developer, if you asked them to âclean up unused worktrees,â would show you the list first. That intermediate step is so obvious that you wouldnât think to ask for it. The agent skipped it. And gitâs own safety mechanism (refusing to delete dirty worktrees without --force) would have caught the problem too, if the agent hadnât silenced it.
What I changed
I stopped approving agent commands on autopilot. Claude Code shows you the command itâs about to run. I had been rubber-stamping approvals because the agent had been reliable for weeks. Now I actually read the command preview before hitting enter, especially anything with --force or a loop over files I care about. It slows me down by maybe ten seconds per action. Weeks of good behavior built a trust that one bad for loop destroyed. Reliability is not the same as safety.


