how to clean up Claude Code worktrees safely

Where Claude Code keeps its worktrees, what it removes itself, and how to clean up the rest with git without losing work. With real output.

The short answer

Claude Code removes some of its worktrees itself and leaves others, on purpose. To clean up the rest, list them with git worktree list, check each one for work that exists only there, remove the clean ones with git worktree remove, delete the leftover branches with git branch -d, and run git worktree prune for folders that are already gone.

Where they live

With claude --worktree <name> (or -w), Claude Code creates the worktree at .claude/worktrees/<name>/ in your repository, on a new branch called worktree-<name> (docs). If you leave the name out, it picks one such as bright-running-fox. The desktop app uses the same folder by default and lets you change it in its settings. Some older reports describe a different folder, ~/.claude-worktrees/<project>/ (issue 26725), so if .claude/worktrees is empty on your machine, look there too.

$ git worktree list
~/code/web                                      cb3c050 [main]
~/code/web/.claude/worktrees/bright-running-fox cb3c050 [worktree-bright-running-fox]
~/code/web/.claude/worktrees/checkout-redesign  8efbfad [worktree-checkout-redesign]
~/code/web/.claude/worktrees/headless-run       cb3c050 [worktree-headless-run] locked
~/code/web/.claude/worktrees/old-spike          102cd2c [worktree-old-spike]

The first line is your main checkout. A folder under .claude/worktrees and a branch starting with worktree- are the quickest way to recognise Claude Code's work. The locked marker is explained below.

What Claude Code cleans up, and what it keeps

This is what the official docs say about removal:

  • A session you end with /exit and that changed nothing, started without a name: the worktree and its branch are removed automatically.
  • A named session, or one with changes or new commits: Claude asks whether to keep or remove it. Keeping leaves the folder and the branch in place.
  • Non-interactive runs (claude -p): there is no exit prompt, so these worktrees are not cleaned up and can stay locked.
  • Subagent worktrees (isolation: worktree): removed when the subagent finishes without changes. Ones with changes stay until a periodic sweep removes those older than cleanupPeriodDays, 30 days by default, and that sweep leaves anything with changed, untracked or unpushed work.

Two more cases come from user reports, not the docs. A crash or a closed terminal never reaches the exit step, which is how stale worktrees pile up (issue 26725). And the VS Code extension was reported to skip cleanup when you close the tab (issue 31488, now closed, so check your version).

Everything that holds work is kept deliberately, and that is the right call. It is also why the folder fills up.

Find the stale ones

Sort the branches by their last commit to see which worktrees have been idle the longest:

$ git for-each-ref --sort=committerdate 'refs/heads/worktree-*' --format='%(committerdate:short)  %(refname:short)'
2026-08-01  worktree-bright-running-fox
2026-08-01  worktree-headless-run
2026-08-20  worktree-old-spike
2026-10-15  worktree-checkout-redesign

And see how much space each one takes:

$ du -sh .claude/worktrees/*
 12K .claude/worktrees/bright-running-fox
 12K .claude/worktrees/checkout-redesign
8.0K .claude/worktrees/headless-run
 12K .claude/worktrees/old-spike

These are tiny because the test repository is tiny. Each worktree is a full copy of your files, and one with dependencies installed is far larger.

Claude Code locks a worktree while an agent is running in it. A locked marker in the list means a run is active, or ended without releasing the lock. A prunable marker means the folder is gone. Both matter below.

Check before you remove anything

The exit prompt exists because a worktree can hold the only copy of someone's work. Check the same two things Claude does. First, commits that are not in your main branch:

$ git log --oneline main..worktree-checkout-redesign
8efbfad redesign checkout

Second, files that were never committed:

$ git -C .claude/worktrees/bright-running-fox status --short
?? notes.txt

Empty output means clean. Anything listed lives only in that folder. Git refuses to remove such a worktree, which is a stop sign and not an obstacle:

$ git worktree remove .claude/worktrees/bright-running-fox
fatal: '.claude/worktrees/bright-running-fox' contains modified or untracked files, use --force to delete it

The first guide goes through these checks in more detail, including what to do when the branch is not merged.

Remove them

For a clean worktree that is not locked, git worktree remove followed by git branch -d is all it takes. A locked one needs one extra step, because git will not remove it:

$ git worktree remove .claude/worktrees/headless-run
fatal: cannot remove a locked working tree, lock reason: claude agent running (pid 4242)
use 'remove -f -f' to override or unlock first

Make sure no agent is really still running there, because that is what the lock says. If it is stale, unlock, remove, and delete the branch:

$ git worktree unlock .claude/worktrees/headless-run
$ git worktree remove .claude/worktrees/headless-run
$ git branch -d worktree-headless-run
Deleted branch worktree-headless-run (was cb3c050).

If the folder is already gone, the worktree shows as prunable and git worktree prune forgets it:

$ git worktree list
~/code/web                                      cb3c050 [main]
~/code/web/.claude/worktrees/old-spike          102cd2c [worktree-old-spike] prunable

$ git worktree prune -v
Removing worktrees/old-spike: gitdir file points to non-existent location

Prune only forgets worktrees whose folders are missing. It does not delete the branch, and a worktree on an external drive that is not plugged in also looks missing, so plug the drive in first.

The "already exists" error when you start again

A cleanup that removed git's record but not the folder leaves a directory behind. The next claude -w with the same name then fails, because git will not create a worktree in a folder that already has files in it. This was reported and the issue is closed, but the same state can come from a crash. You see git's own message:

$ git worktree add .claude/worktrees/benchmark_only -b worktree-benchmark_only
Preparing worktree (new branch 'worktree-benchmark_only')
fatal: '.claude/worktrees/benchmark_only' already exists

git worktree list does not show it, because git no longer knows about it. Look inside the folder before you delete it, since it may hold files you want, and then remove the leftover folder by hand.

Stop the pile growing

  • Ignore the folder. The docs suggest adding .claude/worktrees/ to your .gitignore. Without it, every worktree shows up as untracked files in your main checkout:
    $ git status --short
    ?? .claude/
    
    $ echo ".claude/worktrees/" >> .gitignore
    $ git status --short
    ?? .gitignore
  • End terminal sessions with /exit. That is when Claude runs its keep-or-remove check.
  • In the desktop app, archive a session when you are done with it, so its worktree goes with it.
  • Look now and then. git worktree list takes a second and shows what git itself knows, whatever any tool believes.

When there are dozens

A few worktrees are easy to handle by hand. After weeks of parallel agents there can be dozens across several repositories, and the checks above have to be run for each one. That is what Lopper automates, described below. It recognises Claude Code's worktrees by their folder and branch names, along with those from Cursor, Codex and Conductor, and shows for each one whether it is safe to remove.