lysosome

Guide · git worktrees

Clean up the git worktrees your coding agents left behind

Updated · Scott Havird

short answer

In each repository, run git worktree list. For every worktree you no longer use, make sure git status is clean and its commits are merged or pushed, then run git worktree remove <path> (without --force) and git worktree prune. To check every repository at once, lysosome worktrees ~/code does those checks read-only and lists what is safe to remove.

Why agent worktrees pile up

A git worktree is a second working folder attached to the same repository, checked out on its own branch. Coding agents use them so several tasks can run in parallel without touching your main checkout: Claude Code's --worktree mode, Cursor's parallel agents and most multi-agent setups create one per task.

Nothing removes them when the task is done. The worktree itself is a full copy of the tracked files, and the bigger cost is what gets built inside it: each one usually gets its own node_modules, Rust target/ or Python .venv. pnpm hard-links packages from a shared store, so its installs cost less, but npm, Yarn, Cargo and virtualenvs make a full copy per worktree. A few weeks of agent work can leave dozens of multi-gigabyte folders nobody will open again.

Where they live

Created byUsual location
Claude Code (claude --worktree)<repo>/.claude/worktrees/<name>
Cursor parallel agents~/.cursor/worktrees/<repo>/<name>
git worktree add, scripts, other agentsAnywhere you or the tool chose, often a sibling folder or ~/.worktrees

The main repository keeps a record of each one in .git/worktrees/. If a worktree folder is deleted by hand, that record stays behind until git worktree prune clears it.

Check sizes and state by hand

List the worktrees of one repository and see how much space they take:

git -C ~/code/shop worktree list
du -sh ~/code/shop/.claude/worktrees/* | sort -h

To find linked worktrees across many repositories, look for .git files: a linked worktree has a small .git file pointing back at its repository instead of a .git folder. Submodules have one too, so check each hit.

find ~/code ~/.cursor/worktrees -maxdepth 6 -name .git -type f 2>/dev/null

Before removing a worktree, check three things inside it:

cd ~/code/shop/.claude/worktrees/checkout-v2
git status --short              # uncommitted or untracked files?
git log --oneline @{u}..HEAD    # commits that aren't on the upstream branch
git -C ~/code/shop branch --merged main   # is the branch merged into main?

If @{u} fails, the branch has no upstream, so its commits may exist only in this worktree. git worktree list also marks worktrees that are locked (someone asked git to keep it) or prunable (the folder is already gone).

Squash merges are the common trap: after a squash-merged pull request, git still reports the branch's commits as unmerged, because the merged commit has a different hash. Check the pull request itself, for example with gh pr list --state merged --head <branch>.

Remove them safely by hand

git -C ~/code/shop worktree remove ~/code/shop/.claude/worktrees/checkout-v2
git -C ~/code/shop worktree prune
git -C ~/code/shop branch -d feat/checkout-v2   # optional; -d refuses unmerged branches

Want to keep a worktree but get the space back? Delete only its build and dependency folders (node_modules, target, .venv); the next install or build recreates them. The build artifacts guide covers how to do that safely.

How lysosome does it

The open-source lysosome CLI runs the same checks for every worktree under the folders you give it, without changing anything:

lysosome worktrees ~/code ~/.cursor/worktrees   # read-only report
lysosome worktrees --days 14                    # call anything idle 14+ days dormant (default 30)
lysosome clean ~/code --worktrees               # dry run: what would be removed
lysosome clean ~/code --worktrees --yes         # remove the REMOVABLE ones

Each worktree gets a status and a reason:

clean analyzes each worktree again right before acting and skips it if anything changed. It runs git worktree remove without --force, then git worktree prune, keeps the branch, moves ignored files that aren't build output (like .env) to the Trash first, and writes every action to a log. To keep the worktrees and free only their dependencies and build output, use lysosome clean ~/code --strip-artifacts --tier regenerable_expensive.

If you use Claude Code, the lysosome plugin (/plugin install lysosome --marketplace lysosome-dev/cli) checks a worktree read-only when its session ends and tells the next session what is safe to reclaim. The Mac app goes further: it ties each worktree to the Claude Code or Cursor session that made it, so you can tell a live task from a forgotten one.