Your Agent Fleet's Worktrees Are a Minefield. Here's How to See It.
The standard way to run coding agents in parallel is one git worktree each: every agent gets its own directory and branch, they don't trip over each other, and you fan out five, ten, twenty of them. It works great — right up until cleanup. A worktree is also a place work goes to die quietly: an agent edits files but never commits, or commits to a branch nobody ever pushed, and then a git worktree remove (or an auto-cleanup) takes the directory and the work with it. anthropics/claude-code#46444 is the worst version we've seen documented: worktree auto-cleanup silently deleted ~10 days of uncommitted work, ~300 files, because they were never committed.
The fix isn't a better undo — it's seeing the risk before you pull the trigger. So we wrote a 90-line tool that answers one question across every worktree in a repo: would I lose work if this got removed right now?
What "at risk" actually means
There are exactly two states where removing a worktree destroys work:
- Uncommitted changes. Files an agent edited but never
git add-ed are ordinary files. Delete the directory and they're gone —fsck, reflog, none of it helps, because nothing was ever written to the object store. - Commits that are on no remote. A commit is durable, but only as far as it has been pushed. A branch that lives only in a worktree — committed but never pushed — loses those commits if the branch and worktree are deleted together. (You can sometimes still
fsckthem back for two weeks; you'd rather not bet a launch on it.)
Everything else — committed and pushed — is safe. The whole tool is just: for each worktree, check those two things.
The tool
worktree-doctor parses git worktree list --porcelain, then for each worktree checks git status --porcelain (dirty?) and git rev-list --count HEAD --not --remotes (commits on no remote?). Run it from anywhere in the repo:
$ worktree-doctor
worktree-doctor — 5 worktrees, 4 at risk
● /repo [main] uncommitted changes · 8 commit(s) on no remote
● /repo-wt-blog [blog/xyz] uncommitted changes · 10 commit(s) on no remote
○ /repo-wt-osdash [osdash/abc] safe
● /repo-wt-research [research/def] uncommitted changes
● /repo-wt-social [team/social] uncommitted changes
commit or push the flagged worktrees before any cleanup —
`git -C <path> stash` or a throwaway WIP commit is enough.
That's real output from one of our machines — four of five worktrees were holding work that a cleanup would have eaten. The key column is the flags: uncommitted changes and N commit(s) on no remote are the two failure modes spelled out per worktree. git rev-list HEAD --not --remotes is the load-bearing trick: it counts commits reachable from this worktree's HEAD but present on no remote-tracking branch — exactly the commits that vanish if the branch is deleted, whether or not an upstream was ever set.
It exits non-zero when anything is at risk, so it drops straight into a pre-cleanup check:
worktree-doctor --quiet && some-cleanup-script # only proceeds if everything is safe
--quiet prints just the at-risk worktrees, so a clean fleet is silent and a risky one is loud.
Why this beats "just be careful"
Three things make worktree loss insidious in a fleet, and visibility kills all three:
- It's invisible by default.
git statusonly shows you the worktree you're standing in. With a dozen agents in a dozen directories, you have no single view of which ones are dirty — untilworktree-doctorgives you one. - The dangerous state looks identical to the safe one. A worktree with 10 unpushed commits and one with everything pushed are the same directory from the outside. The only way to tell is to ask git, per worktree, which is exactly the loop the tool runs for you.
- Cleanup is often automated. The whole point of a fleet is that you don't babysit it. If a script or a tool prunes worktrees, the human is never in the loop to notice the dirty one — unless the prune is gated on a check that fails loudly.
The honest caveats
It's a point-in-time snapshot, not a daemon — it tells you the risk now, so run it before any cleanup, not once a week. "On no remote" is measured against your remote-tracking refs, so git fetch first if they might be stale (the tool works on what git currently knows). And it deliberately treats the main worktree like any other: your primary checkout can be dirty and unpushed too, and it should show up red when it is.
The real lesson
Running agents in worktrees is the right pattern — but it quietly multiplies the number of places uncommitted work can hide, and the failure is total and silent when it happens. The cheap insurance is a single command that turns "I hope nothing's dirty" into a list. Pair it with the discipline from the recovery post — make agents commit early and often — and the two together keep an entire fleet on the recoverable side of the line: commit removes failure mode one, push removes failure mode two, and worktree-doctor tells you when you've missed either.
We build and run autonomous agent fleets on Claude Code in production. If you're scaling past a handful of parallel agents, talk to us.
Get the tool → worktree-doctor in agent-ops — open source (MIT), a single dependency-free script, part of our toolkit for running coding agents in production.
Found this useful?
- You're Running Five Agents on One Repo. Who Stops Them Overwriting Each Other?
- Your Agent Did the Work, Then It Vanished. Here's How to Get It Back.
- Your Claude Code Session Is Permanently Stuck on a 400. Don't /clear — Do This.
- The One Kind of Agent Work You Can't Recover — and How to Stop Losing It
- Your Agent Will Eventually Run git reset --hard. Stop It at the Door.
- Your Agent Reads Text You Can't See. Frisk It First.
- You're Running a Dozen Agents. Which One Is Stuck?
- What's Actually In Your Claude Code Session File (and a Tool to Read It)
- The Agent Wrote the Code in Minutes. Reviewing It Takes Hours. Here's Why.
- Your Claude Agent Re-Reads Its Whole Prompt Every Turn. Here's the 10× You're Leaving On the Table.
- Your Agent Can Read Everything Your Shell Can. Have You Looked?
- The Loosest Line in Your Repo Is in .claude/settings.json
- The Most Expensive File in Your Repo Runs on Every Single Turn
- Your Skill's Description Is the Whole Ballgame
- Your Repo Already Knows How To Build Itself. Put That In the CLAUDE.md.
Related posts
The boring part: governance that enforces, not displays
Most "AI governance" is a dashboard. It shows you what an agent spent, what it touched, what it decided — after the fact, in a panel nobody refreshes until the bill arrives. A display is not a control. A control is the t…
Your Launch Deserves a Real Demo Video, Not a Screen Recording With Captions
Most product launches skip the demo video entirely, and the ones that don't ship one usually reach for the fastest option: a raw screen recording, maybe some auto-generated captions, posted as-is. It's better than nothin…
The MCP Ecosystem Is Growing Fast — and Quietly Becoming a Directory of Hosted Services
We [recently measured](/insights/in-the-registry-is-not-runs-2) whether the servers in the official MCP registry actually *run* (short version: 84% are remote-only, and under half of the installable ones boot clean). Whi…
Installing a Skill Usually Means Running a Stranger's Code
The pitch for Claude Code "skills" is that they're just *instructions* — a `SKILL.md` file with some markdown telling the agent how to do a task. That framing makes them feel safe to install. A prompt can't hurt you; wor…