[BUG] Edit/Read silently target the main worktree when given an absolute path that elides `.claude/worktrees/<name>/`

Resolved 💬 3 comments Opened May 13, 2026 by michaeljancsy Closed May 17, 2026

Summary

When a Claude Code session is spawned in a sub-agent worktree under .claude/worktrees/<name>/, the **Edit, Write, and Read tools accept absolute paths that resolve to the main worktree** (i.e. the canonical repo root) rather than to the active worktree. There is no warning. This is technically correct behavior — the paths are absolute and valid — but in practice it's a trap because:

  1. The model can easily generate the wrong absolute form. If the project is at /Users/me/Projects/Foo/, the model latches onto that as "the path of the repo" and produces /Users/me/Projects/Foo/src/file.swift, not /Users/me/Projects/Foo/.claude/worktrees/strange-cray/src/file.swift.
  2. Edit + Read are mutually consistent at the wrong path. If Edit writes to the main worktree, a subsequent Read shows the edit there. The model has no signal anything is wrong.
  3. Bash tool calls using relative paths off the agent's CWD resolve correctly to the worktree, so git status, git diff, grep etc. show no changes. The model sees "Edit succeeded ✓; git shows nothing" and misdiagnoses it as a write failure, caching issue, or disk problem.

Repro

  1. Use Claude Code's parallel-agent / sub-agent worktree feature so an agent session lands in .claude/worktrees/<name>/ (CWD is set correctly in the system prompt).
  2. Ask the model to edit a file. The model produces an absolute path like /Users/me/Projects/Foo/src/file.swift (omitting .claude/worktrees/<name>/).
  3. Edit tool returns "The file ... has been updated successfully."
  4. Run git status (Bash, relative CWD) — clean.
  5. Read the same absolute path via Read — shows the edit.
  6. Read the relative path via Bash cat / awk — original content.

Why it's confusing

Edit and Read tools' "view of the file" agree with each other (both read the main worktree). Bash tools' view disagrees (relative paths resolve to the agent's actual worktree). The discrepancy looks like a write-vs-read cache split or a disk-full silent-failure pattern (which is what I diagnosed it as before realizing the paths were targeting the wrong tree).

Real-session impact

This bit me yesterday on PR https://github.com/<repo>/pull/318. The Read tool was showing me ghost lines from my own (lost) edits that didn't exist on disk — except they DID exist on disk, just in the wrong worktree. Hours wasted debugging "disk full + write cache invalidation" before I noticed the absolute paths in my Edit calls were missing the .claude/worktrees/<name>/ segment. Eventually had to switch to Python/sed via Bash (which used relative paths and Just Worked) to land the edits in the right place. Other side effect: stale "drafts" left behind in the main worktree showed up as uncommitted modifications when the user tried to fast-forward main after the PR merged.

Suggested mitigations (any one would help)

  • Cheapest: Edit/Write/Read emit a one-line note in the tool result when the resolved path is outside the active worktree (e.g. "note: this path is outside the current worktree at .claude/worktrees/strange-cray/; intended?"). Model would notice and self-correct on the next turn.
  • System prompt: include the worktree-prefixed absolute path explicitly alongside the bare CWD ("when constructing absolute paths, anchor them at <worktree-absolute-path>, not <repo-canonical-path>"). Low cost, instruction-following only.
  • Stronger (riskier): auto-rewrite absolute paths that fall under the main worktree to their worktree-prefixed equivalent when there's an active worktree. Risk: legitimate cross-worktree edits become impossible without an escape hatch.

Environment

  • macOS 26.2 (Tahoe)
  • Claude Code CLI 2.1.128 (also reproduced on 2.1.111 in another worktree)
  • Multiple concurrent sub-agent worktrees active

🤖 Generated with Claude Code

View original on GitHub ↗

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