Bash tool cwd silently re-homes into sibling git worktrees mid-session (multi-session/agent environments)
Summary
In a repository using multiple .claude/worktrees/* worktrees with several
concurrent Claude Code sessions/agents, the Bash tool's working directory
silently drifts to a different worktree between tool calls — without anycd issued — and EnterWorktree does not durably pin it. File-relative
commands then read/write a sibling agent's tree while reporting success.
Observed (2026-08-07, macOS, darwin 25.6.0)
- One session's shell homed through three different worktrees within a
single working window (t15-envelope → r3-session → t3-engine), verified
by git rev-parse --show-toplevel asserts between consecutive calls.
- A second session, launched for worktree A, found its shell bound into
worktree B (a sibling agent's) and correctly stopped work.
- Concrete damage class (caught, recoverable): an agent's
git reset --soft <sha> intended for its own tree executed inside a
SIBLING's worktree — both trees sat at commits where the sha existed, so
sha-based assertions passed in the wrong tree. The sibling branch ref
moved and had to be reflog-restored. A soft reset was survivable;
--hard/checkout/restore from the same drifted cwd would have
destroyed uncommitted work.
- Also observed: a freshly spawned agent's ~180-file staged index consistent
with a soft-reset executed in the wrong tree by another drifted shell.
Why it's dangerous
git rev-parse HEAD-style guards are VACUOUS as tree identity checks when
multiple worktrees sit at identical commits. Teams will not notice the
drift until a tree-mutating command lands in a neighbor's checkout.
File-relative proof commands (test runs, greps) silently retarget and can
read green against the wrong tree.
Workarounds we adopted (may help repro/triage)
- Assert
git branch --show-current(not sha) inside every Bash batch. - Move all tree-mutating operations to remote machines reached by explicit
ssh (immune — no cwd inheritance).
- Treat local worktrees as untrusted byte sources while any drift is
possible.
Environment
- claude-code CLI on macOS (darwin 25.6.0), multiple concurrent sessions
(orchestrator + spawned agents), git worktrees under
<repo>/.claude/worktrees/.
- Possibly related to background-shell reuse across agents; the drift
correlates with concurrent agent activity in sibling worktrees.
(Fuller timestamps/reflog excerpts available on request.)