[BUG] Bash tool cd within project root persists across calls by default — breaks statusline, enables silent directory drift
[BUG] Bash tool cd within project root persists across calls by default — breaks statusline, enables silent directory drift
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report
- [x] I am using the latest version of Claude Code
What's Wrong?
When the Bash tool executes cd to a subdirectory within the project root, the new working directory persists across subsequent Bash tool calls. Only cd outside the project root triggers a CWD reset.
This causes two concrete problems:
- Statusline breaks: A
statusLinecommand that relies onpwd(e.g., showing git branch/status) loses context after a subagent or the model itself runscdto a subdirectory. The statusline then reports incorrect git information or fails entirely.
- Silent directory drift: When subagents perform
cdto explore other directories (especially via/add-dir), the main session's CWD silently changes. The user has no indication that subsequent commands will run in a different directory. In one real session, a subagent'scdshifted CWD to an entirely different repository (added via/add-dir) for 17 minutes and 114 log entries before it was reset.
What Should Happen?
CWD should reset to the project root after every Bash tool call, regardless of whether cd targeted a path inside or outside the project. This is what CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR=1 does — but it's not the default, and it's completely undocumented.
Steps to Reproduce
Test 1 — cd within project (default behavior, no env var)
- Start Claude Code in a project directory (e.g.,
/home/user/my-project/) - Run Bash:
cd src && pwd→ outputs/home/user/my-project/src - Run Bash:
pwd→ outputs/home/user/my-project/src(persisted — wrong)
Test 2 — cd outside project (default behavior, no env var)
- Run Bash:
cd /tmp && pwd→ outputs/tmp - Run Bash:
pwd→ outputs/home/user/my-project/(reset — correct)
Test 3 — with CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR=1
- Set
CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR=1insettings.jsonenv - Restart Claude Code
- Run Bash:
cd src && pwd→ outputs/home/user/my-project/src - Run Bash:
pwd→ outputs/home/user/my-project/(reset — correct)
Real-world impact (session evidence)
In a real session using a git worktree, the following CWD transitions were observed in the JSONL log:
| Time | CWD changed to | Trigger |
|------|----------------|---------|
| 13:19 | repo-B (different repo, added via /add-dir) | Subagent cd |
| 13:19 | Back to project root (repo-A worktree) | Reset |
| 13:19 | repo-B again | Another subagent cd |
| 13:19 | Back to project root | Reset |
| 13:35 | repo-B | Subagent cd — persisted for 17 minutes |
| 13:52 | Back to project root | Reset |
During the 13:35–13:52 window, 114 JSONL log entries had "cwd" pointing to repo-B instead of the actual project root. Any Bash commands during that period would have executed in the wrong repository. The user had no visual indication of this — the CWD shift was completely silent.
The inconsistency
| Scenario | Default behavior | With env var =1 |
|----------|-----------------|-------------------|
| cd outside project | Reset + visible message | Reset (silent) |
| cd within project | No reset (persists) | Reset (silent) |
| cd to /add-dir path | No reset (persists) | ? (not tested) |
The env var also suppresses the "Shell cwd was reset" message, making the reset silent in all cases.
Questions for the team
- Why isn't
CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR=1the default? The variable has existed since v1.0.18, so the team clearly identified the problem. The current default breaks the statusline and enables silent directory drift.
- Why is this variable undocumented? Issue #9359 requested documentation and was closed as "not planned". The variable doesn't appear in the settings docs or any official reference.
- Should
/add-dirdirectories be treated as "within project"? The current behavior allowscdto an/add-dirpath to persist, which is arguably even more dangerous than within-project persistence since it's a completely different repository.
Proposed fix
Change the default to CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR=1 (always reset CWD to project root). Users who need the old behavior can set =0. Also document the variable.
Error Messages/Logs
No error messages — the issue is silent by nature, which makes it worse.
Claude Model
Opus 4.6
Is this a regression?
No — this has been the behavior since at least v1.0.18 (when the env var was introduced as a workaround)
Claude Code Version
2.1.76
Platform
Anthropic API (Max subscription)
Operating System
Windows 11 Pro (10.0.26200) with Git Bash
Terminal/Shell
Windows Terminal + Git Bash
Additional Information
Related issues:
- #9359 — Documentation request for
CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR(closed "not planned") - #11067 — Bash Tool Not Respecting Working Directory
- #14300 — Shell initialization breaks workspace boundary
- #16361 — Working directory does not persist between Bash commands on Windows
- #7442 — Claude will frequently
cdand then forget its working directory
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗