Agent `isolation: "worktree"` leaks cwd into parent checkout mid-session, destroying untracked files
Summary
When spawning a subagent via the Agent tool with isolation: "worktree", the subagent's shell/tool context can leak its cwd back into the parent repo checkout partway through a long session. The parent session's subsequent git checkout in the main checkout then destroys untracked files in the subagent's worktree because both are pointing at the same working tree at that moment.
Hit this twice in a single session today — once in the parent and once inside a long-running subagent — which is what prompted the report.
Environment
- Claude Code: 2.1.119
- Platform: darwin 24.6.0
- Repo shape: standard git repo with prior
.claude/worktrees/agent-<id>/subfolders - Session length: ~6+ hours, many subagent spawns
What happened
- Parent session cwd:
/Users/tre/<repo>/ - Spawned an Agent with
isolation: "worktree"andrun_in_background: true. Subagent worktree created at/Users/tre/<repo>/.claude/worktrees/agent-<id>/. - Subagent worked for several minutes creating files + staging edits.
- At some point mid-session, the subagent's tool-call cwd appeared to shift to
/Users/tre/<repo>/(the parent checkout). The subagent continued its work, butgitcommands now targeted the parent's working tree. - Meanwhile the parent session — unaware of the overlap — performed a
git stash -u+git checkout <other-branch>in the main checkout. Thegit checkoutsilently removed the subagent's untracked files from the parent working tree (because they WERE the parent working tree at that moment). - Subagent recovered by recreating the two lost files from memory inside its proper worktree path, re-applying staged patches, and proceeding. But this required the subagent to notice the loss — if it had reported "done" at that step, the files would have vanished.
A parallel instance: the parent session itself encountered feature/<subagent-branch> checked out in the main checkout with uncommitted work from the subagent, suggesting the subagent's output had been landing in the parent checkout, not the worktree.
Expected behavior
isolation: "worktree" should guarantee that, for the lifetime of the subagent:
- The subagent's file-write and
gitoperations target only its worktree path - The parent session's destructive
gitoperations (checkout, reset, stash-pop, etc.) that would collide with a live subagent's worktree are either (a) warned about or (b) refused until the subagent completes
Right now the contract reads as "isolation" but the observed behavior is "shared working tree with a separate branch name."
Reproducibility
- Not reliably minimal-reproducible — appears keyed on long-session cwd-state drift. Two independent occurrences in a single ~6-hour parent session.
- Both occurrences involved subagents that ran
gitcommands multiple times across a multi-step workflow (checkout → edits → stage → commit → push). - No explicit
cdwas ever issued by the subagent in either case; the cwd drift was implicit.
Suggested mitigations (ordered cheapest to most invasive)
- Pin cwd per-subagent at tool dispatch time. Every Bash / Edit / Write call from a worktree-isolated subagent should resolve relative paths against the worktree root, not the shell's current cwd.
- Warn on parent-checkout destructive
gitops while a worktree-isolated subagent is active. Block or confirm beforegit checkout,git reset --hard,git stash popin the parent if a child worktree overlaps. - Expose a
pwdassertion in the subagent brief contract so the subagent can self-verifypwd === worktreePathat key checkpoints (session start, before each commit). - Make
git stash -uworktree-aware so untracked files in a child worktree aren't collected into the parent stash by mistake.
Even #1 alone would close the observed failure modes.
Downstream impact
The workaround is for the subagent to stay vigilant — recreate from memory when loss is detected. That's obviously not scalable: an agent that "completes successfully" while silently losing untracked work is the failure mode to design against.
This issue has 6 comments on GitHub. Read the full discussion on GitHub ↗