[BUG] EnterWorktree/ExitWorktree pins session cwd globally and makes EnterWorktree bind to the wrong repository
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet (related but distinct ones are listed at the bottom)
- [x] This is a single bug report
- [x] I am using the latest version of Claude Code
What's Wrong?
Using the worktree tools leaves the session working directory permanently pinned. After EnterWorktree then ExitWorktree (either keep or remove), every Bash command appends Shell cwd was reset to <ExitWorktree restore dir> and cd never persists, including when the user types cd via the ! prefix.
Worse, the EnterWorktree tool resolves the "current repository" from that pinned cwd, so once the session is pinned it operates on the wrong repository: a subsequent EnterWorktree created a worktree and branch in an unrelated sibling repository, and EnterWorktree(path=<a correct, registered worktree>) was rejected as "not a registered worktree of <pinned repo>".
No in-session recovery exists. /add-dir <abs> widens the permitted directory set but does not re-anchor the project directory or what ExitWorktree restores to. Only fully restarting Claude Code clears the pin.
What Should Happen?
ExitWorktree should restore the cwd to the session's original launch directory and leave it mutable (the Bash tool docs state cwd persistence is the default). EnterWorktree should resolve its target repository from the session's actual repository context rather than a stale pinned cwd, so it never creates worktrees in an unrelated repository, and EnterWorktree(path=...) should accept a registered worktree of the repository the session is logically working in.
Error Messages/Logs
Shell cwd was reset to /Users/<user>/<repoA>
Cannot enter worktree: /Users/<user>/<repoA>/.claude/worktrees/<name> is not a registered worktree of /Users/<user>/<repoB>.
Steps to Reproduce
- Launch Claude Code in repo A (a git repository).
- In a Bash call,
cdinto a sibling git repository B (for example to read a file there), so the persisted Bash cwd is now B. - Call
EnterWorktree. It creates the worktree off B (the cwd-derived repo), not A. - Call
ExitWorktree(removeorkeep). - Every subsequent Bash command prints
Shell cwd was reset to <B>;cdto any path, by the agent or by the user via the!prefix, does not persist. - Call
EnterWorktree(path=<a real, registered worktree of A>). It is rejected as not a worktree of B. - Only a full Claude Code restart restores a mutable cwd.
Claude Model
Opus
Is this a regression?
I don't know (the worktree tools are recent; there is no known prior-working baseline)
Claude Code Version
2.1.143 (Claude Code)
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
zsh
Related but distinct issues
- #42844 / #42837: generic mid-session
cdregression attributed to a customstatusLine. This report has no customstatusLineand is triggered purely by the worktree tools, and it additionally surfaces the wrong-repository binding. - #40968: Windows, auto-spawned worktrees and a session stuck in a deleted-worktree cwd.
- #48967:
EnterWorktreecreating worktrees under.claude/. - #52958: agent
isolation: "worktree"cwd leak into the parent checkout.
This issue is specifically the EnterWorktree/ExitWorktree restore-anchor pin plus the resulting wrong-repository binding of EnterWorktree, with a full restart as the only recovery.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗