Detached worktrees from subagent isolation accumulate silently with no lifecycle management
Bug description
When subagents use isolation: "worktree", Claude Code creates detached HEAD worktree copies but has no built-in mechanism to clean them up. Because they're detached (not on any branch), they're invisible to normal git workflows — git branch won't show them, and there's no branch name to notice or track. They accumulate silently across sessions, especially when sessions crash or are interrupted before cleanup can occur.
Impact
On a 32GB Apple Silicon machine running local LLM inference, this caused two near-OOM incidents in consecutive sessions:
| Date | Orphaned detached worktrees | Disk consumed | Disk remaining |
|------|----------------------------|---------------|----------------|
| 2026-05-12 | 615 | ~21 GB | Low (caused working directory corruption) |
| 2026-05-13 | 764 | ~36 GB | 220 MB (near-OOM after 8GB model download) |
Each detached worktree is a full copy of the repo (~50MB). A session with heavy subagent use can create dozens. Without cleanup, this compounds across sessions. All 764 worktrees were (detached HEAD) — none on named branches.
Expected behavior
Claude Code should manage worktree lifecycle automatically:
- Clean up detached worktrees when the creating subagent completes (success or failure)
- Sweep orphaned detached worktrees on session start
- Clean up all session-owned worktrees on session end, including on crash/SIGKILL (via a startup sweep on next launch)
- Warn or enforce a ceiling on total worktree count/disk usage
Current workaround
User-configured hooks in settings.local.json:
SessionStarthook to sweep orphans from prior crashed sessionsPostToolUsehook onAgentmatcher to clean up after each subagent
{
"hooks": {
"SessionStart": [{
"hooks": [{
"type": "command",
"command": "git worktree prune; WDIR=<worktree-path>; if [ -d \"$WDIR\" ]; then ACTIVE=$(git worktree list --porcelain | grep '^worktree ' | sed 's/^worktree //' | sort); for d in \"$WDIR\"/*/; do [ -d \"$d\" ] || continue; REAL=$(cd \"$d\" && pwd -P); echo \"$ACTIVE\" | grep -qF \"$REAL\" || rm -rf \"$d\"; done; fi"
}]
}],
"PostToolUse": [{
"matcher": "Agent",
"hooks": [{
"type": "command",
"command": "<same cleanup command>"
}]
}]
}
}
This covers ~95% of cases but requires manual setup per project, and doesn't protect against hook misconfiguration or settings file corruption.
Reproduction
- Run a session that spawns multiple subagents with
isolation: "worktree" - Kill the session mid-work (Ctrl+C, terminal close, crash)
- Repeat across several sessions
- Check:
git worktree list | wc -l— all entries will show(detached HEAD) - Check:
du -sh <worktree-path>/— disk grows unbounded
Environment
- macOS 26.0.1, Apple M1 Max, 32GB RAM
- Claude Code (CLI)
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗