Subagent worktrees not auto-cleaned when reviewer writes scratch files
Summary
When a subagent is dispatched via the Agent tool with isolation: "worktree", the agent-SDK's auto-cleanup hook does not fire reliably on subagent teardown if the subagent has written any scratch file inside its worktree during the dispatch. The worktree ends up in locked state per git worktree list and persists indefinitely, accumulating one stray worktree per dispatch.
Reproducer
- Dispatch a
general-purposesubagent via the Agent tool withisolation: "worktree". - The subagent writes any file under its worktree path during the run (e.g.
git show <sha>:<path> > /tmp/<file>where/tmp/happens to land inside the worktree, ortee-ing evaluator output to a path inside the worktree). - The subagent finishes and returns its summary normally.
- Inspect the parent repo:
git worktree listshows the agent's worktree still present, marked(detached HEAD) locked. The auto-createdworktree-agent-<id>branch is still listed ingit branch.
When the subagent makes zero filesystem changes inside the worktree, auto-cleanup fires correctly and git worktree list is clean. The breakage correlates with reviewer-side scratch writes.
Observed in the wild
Three consecutive PRs in a single project chain (PRs #18, #19, #20 in ArkaneSapien/hiatus, dispatched roughly weekly apart, all using general-purpose agents under isolation: "worktree") exhibited the same failure mode. In every case:
- The worktree is at the PR base SHA or some intermediate commit.
nothing to commit, working tree clean— no uncommitted work.git worktree listreports the worktree as(detached HEAD) locked. The lock state is what blocks auto-cleanup.
Manual recovery (used three times now)
git worktree unlock /path/to/.claude/worktrees/agent-<id>
git worktree remove --force /path/to/.claude/worktrees/agent-<id>
git branch -D worktree-agent-<id>
The auto-created branch ref persists even after worktree remove --force (tracked separately from the worktree dir), so the third branch -D step is required to actually clean up git branch -a output.
Suggested fix
When a subagent exits, the SDK should treat its worktree as transient by definition:
git worktree unlock <path>if the worktree is locked.git worktree remove --force <path>regardless of dirty state.git branch -D worktree-agent-<id>to drop the ref.
The current behaviour appears to use git worktree remove (without --force), which fails when the worktree has any modifications. Subagent worktrees are inherently transient — there's no reason to preserve them across exits. If a future use case needs post-exit inspection (debugging the subagent's filesystem state), an opt-in keepWorktree: true flag would be cleaner than the current default behaviour.
Impact
- Confuses subsequent review passes. Each new dispatched subagent sees the leftover worktree(s) in
git worktree listand either flags them as suspicious (one reviewer in our chain flagged a leftover as a security finding before being corrected) or wastes context investigating. - Accumulates over time. Three review passes on a single PR × multiple PRs per milestone could leave a dozen stray worktrees before anyone notices. Each holds an inode-level snapshot of the repo.
- Pollutes review-comment audit trails. Three Linear comments across our PRs had to mention this leftover — workflow-debt baked into project audit logs.
Workaround in place
We've added a dispatch-time cleanup block to our project's CLAUDE.md (https://github.com/ArkaneSapien/hiatus/pull/21) that we append to every code-reviewer subagent's prompt before dispatching. The block instructs the subagent to run git worktree unlock + remove --force + branch -D on its own worktree before exiting. This works in practice but is brittle (relies on every dispatched subagent following the prepended instructions, plus a parent-side belt-and-braces check) — the right fix is SDK-side.
We chose to keep the workaround in CLAUDE.md rather than in the skill template at ~/.agents/skills/requesting-code-review/ because that skill is managed by an obra/superpowers sync that overwrites local edits — any in-place edit there gets silently lost on next sync.
Environment
- Claude Code CLI (Mac).
- Agent tool dispatches with
subagent_type: "general-purpose"andisolation: "worktree". - Subagent worktrees created at
<repo>/.claude/worktrees/agent-<id>.
Happy to provide more reproductions or test a candidate fix.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗