Agent `isolation: "worktree"` leaks cwd into parent checkout mid-session, destroying untracked files

Resolved 💬 6 comments Opened Apr 24, 2026 by tre-jones Closed Jun 1, 2026

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

  1. Parent session cwd: /Users/tre/<repo>/
  2. Spawned an Agent with isolation: "worktree" and run_in_background: true. Subagent worktree created at /Users/tre/<repo>/.claude/worktrees/agent-<id>/.
  3. Subagent worked for several minutes creating files + staging edits.
  4. 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, but git commands now targeted the parent's working tree.
  5. Meanwhile the parent session — unaware of the overlap — performed a git stash -u + git checkout <other-branch> in the main checkout. The git checkout silently removed the subagent's untracked files from the parent working tree (because they WERE the parent working tree at that moment).
  6. 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 git operations target only its worktree path
  • The parent session's destructive git operations (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 git commands multiple times across a multi-step workflow (checkout → edits → stage → commit → push).
  • No explicit cd was ever issued by the subagent in either case; the cwd drift was implicit.

Suggested mitigations (ordered cheapest to most invasive)

  1. 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.
  2. Warn on parent-checkout destructive git ops while a worktree-isolated subagent is active. Block or confirm before git checkout, git reset --hard, git stash pop in the parent if a child worktree overlaps.
  3. Expose a pwd assertion in the subagent brief contract so the subagent can self-verify pwd === worktreePath at key checkpoints (session start, before each commit).
  4. Make git stash -u worktree-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.

View original on GitHub ↗

This issue has 6 comments on GitHub. Read the full discussion on GitHub ↗