Alexandre Gaubert Alexandre Gaubert
April 1, 2026 · 4 min read

The Day My AI Agent Deleted 29 Git Worktrees

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.

Stay ahead in CI/CD

Blog posts, release news, and automation tips straight in your inbox.

Recommended posts

When GitHub Webhooks Lie: How an Empty Array Broke Our Merge Queue
March 25, 2026 · 8 min read

When GitHub Webhooks Lie: How an Empty Array Broke Our Merge Queue

GitHub webhooks can deliver structurally valid payloads with stale data. We traced a customer incident to out-of-order delivery and built action-aware upserts to protect against it.

Mehdi Abaakouk Mehdi Abaakouk
The Comfortable Room
March 6, 2026 · 5 min read

The Comfortable Room

Software engineering was a walled garden. AI just copied the key. The data is messy: 19% slower in trials, 30% more warnings, 322% more vulnerabilities. But the baseline wasn't pristine either. What's left isn't coding: it's judgment, taste, and knowing which room to build.

Rémy Duthu Rémy Duthu
How We Turned Claude Into a Cross-System Support Investigator
February 20, 2026 · 9 min read

How We Turned Claude Into a Cross-System Support Investigator

Support triage at Mergify meant juggling Datadog, Sentry, PostgreSQL, Linear, and source code. We built a repo with MCP servers and Claude Code that investigates tickets in parallel — cutting triage from 15 minutes to under 5, with 75% first-pass accuracy.

Julian Maurin Julian Maurin