DEV Community

Cover image for Claude Code's --worktree Could Delete a Branch on Exit Without Asking. 2.1.304 Fixes It
Gabriel Anhaia
Gabriel Anhaia

Posted on AI-assisted

Claude Code's --worktree Could Delete a Branch on Exit Without Asking. 2.1.304 Fixes It


On October 19, Anthropic published Claude Code 2.1.304. Most of its long changelog is plugin plumbing and interface fixes. One line in the middle is the one to read first:

Fixed claude --worktree removing the worktree and its branch without asking at exit when HEAD was detached or on another branch, which could lose commits

If you start Claude Code sessions with --worktree, update first. Then spend two minutes checking whether an earlier session took some of your work with it.

What the flag is supposed to do at exit

claude --worktree feature-auth (or -w) creates a separate checkout under .claude/worktrees/feature-auth/ on a new branch named worktree-feature-auth, according to the worktrees docs. It's how you run two Claude Code sessions on one repo without them editing the same files. Underneath it is a plain git worktree.

The exit is where the care is supposed to go. The docs say Claude checks the worktree for "changed or untracked files, uncommitted work inside checked-out submodules, and new commits." A clean worktree from an unnamed session is removed with its branch automatically. A worktree with work in it gets a prompt: keep it or remove it. Removing, in the docs' words, "deletes the worktree directory and its branch, along with all the work in them."

According to the release note, that prompt was skipped in two states: HEAD detached, or HEAD on a branch other than the one Claude created. Both are easy to reach. Check out a tag to reproduce a bug, git switch to another branch to try something, or let the agent do either, and the worktree is no longer on worktree-<name>. The release note doesn't say which versions were affected or why the check misread the state, and I haven't reproduced the bug myself.

Why lost commits are hard to see afterwards

Commits made on a detached HEAD belong to no branch. The git checkout docs say that once nothing refers to such a commit, it "will be deleted by the routine Git garbage collection process, unless we create a reference before that happens." A deleted branch leaves the same kind of orphan behind for any commit that only that branch pointed at.

The window isn't zero, though. git gc keeps unreachable loose objects for a grace period whose "default is 2 weeks ago," configurable with gc.pruneExpire. So a commit lost this way may still be in your object database, with nothing pointing at it. The sooner you look, the better your odds.

Look for orphaned commits

Run this from the repository's main checkout. It prints the 20 newest commits that no branch or tag points at, including ones only a reflog still remembers:

cd ~/code/app
git fsck --unreachable --no-reflogs 2>/dev/null \
  | awk '$2 == "commit" {print $3}' \
  | while read -r sha; do
      git log -1 --format='%ci %h %s' "$sha"
    done | sort -r | head -20
Enter fullscreen mode Exit fullscreen mode

Per the git fsck docs, --unreachable prints "objects that exist but that aren't reachable from any of the reference nodes," and --no-reflogs stops a reflog entry from counting as a reference. Expect noise: old amended and rebased commits show up too. Look for subjects from a recent Claude Code session. When you find one, give it a name before anything else:

git branch rescue/feature-auth 1a2b3c4
Enter fullscreen mode Exit fullscreen mode

Swap in the hash from your own output. This finds commits only. Uncommitted edits that lived only in a deleted worktree directory won't come back this way.

Update, and know which channel you're on

claude --version
claude update
Enter fullscreen mode Exit fullscreen mode

Native installs update in the background, and updates "take effect the next time you start Claude Code," per the setup docs. Homebrew, WinGet and Linux package installs don't auto-update by default. The channel matters too: stable serves "a version that is typically about one week old," and the Homebrew claude-code cask tracks stable. So brew upgrade claude-code may not reach 2.1.304 for a while, while claude-code@latest gets new versions "as soon as they ship." For npm, the docs say to run npm install -g @anthropic-ai/claude-code@latest.

Until you're on 2.1.304, check where HEAD is before you leave a --worktree session. git branch --show-current prints nothing on a detached HEAD. If it prints nothing, or anything other than worktree-<name>, first put a branch on HEAD with git branch keep/<name> so its commits have a name, then switch back to worktree-<name> before you exit.

Four smaller fixes in the same release

The 2.1.304 notes have a few more lines worth a look:

  • rm -r of a mounted drive or a top-level folder (/Volumes, /media, WSL's /mnt/c) now gets "the safety prompt that rm -rf /Applications gets."
  • CLAUDE_CODE_AUTO_COMPACT_WINDOW=200k was "silently setting a 100K window." The env var docs now say suffixed values "require v2.1.304 or later," so on an older version write 200000.
  • On Pro and Max plans, resuming an inactive conversation warns you when it "would use a noticeable share of your 5-hour usage limit."
  • A plugin could keep a headless run going "past --max-turns, Stop, or ended input by spawning subagents." That's fixed.

Classmethod's write-up of the release lists the same worktree fix first among its major fixes, and suggests that anyone who set the compact-window variable check which value was actually in effect.

Where Hermes fits, and where it doesn't

I build Hermes IDE, so weigh this section with that in mind. Hermes creates its own worktree for each task, on a hermes/<name> branch, and starts the agent inside it (README). A Hermes task doesn't go through claude --worktree's exit check at all. Whether its worktree stays is your choice when you close the session.

The Hermes IDE Review Desk's Worktrees tab listing one Hermes worktree each for orders-api, web-app and orders-types, with branch, task, age and disk size
The Review Desk's Worktrees tab in Hermes 2.3.4: each task's hermes/ branch, age and disk size, plus free disk space.

That doesn't make Hermes immune to this class of bug. Its own 2.2.9 release on October 12 fixed one: "A worktree you choose to keep when closing a session is no longer deleted automatically later" (release notes). Any tool that cleans up worktrees for you can get this wrong, which is why the git fsck check above is worth keeping, whichever tool you use. Hermes is source-available (BSL 1.1) and runs on macOS, Windows and Linux. It isn't affiliated with Anthropic.

Have you ever lost work to an agent's cleanup step, and did git fsck get it back? Tell me in the comments.


If this was useful

If you run several agents in worktrees, Hermes IDE gives each task its own branch and lists every worktree in one place, and it's built in the open on GitHub.

The compact-window bug above is a small case of a bigger habit: knowing what your agent actually carries into its context. The Prompt Engineering Pocket Guide covers how to shape that context on purpose, so you know which compact window you're running and why.

Prompt Engineering Pocket Guide: Techniques for Getting the Most from LLMs

Top comments (0)