[BUG] Windows / Desktop Code tab: Bash `cd` into an additional working directory silently re-targets the session's primary working directory (Workflow scripts land under another project's slug)
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
A main-thread Bash command such as cd "C:\Users\<user>\Documents\<other-dir>" && ls (no prompt, per the permissions docs: "A cd into a path inside your working directory or an additional directory is also read-only") leaves the shell in <other-dir>. Immediately after that command, still within the same turn, the harness treats <other-dir> as the session's primary working directory:
- Before its next step the model receives:
```
<system-reminder>
# Environment update
- Primary working directory: C:\Users\<user>\Documents\<other-dir> (was C:\Users\<user>\Documents\<project>)
</system-reminder>
``type:"attachment"
In the transcript this is , attachment.type:"environment", changes[{field:"workingDirectory", from:…}]. The cwd field of subsequent records also changes. In one observed case the cd` ran at 13:14:26, the reminder was stored at 13:14:30 and the model's next message came at 13:14:34.
- Workflow tool scripts are then saved under the other directory's project slug,
~/.claude/projects/C--Users-<user>-Documents-<other-dir>/<session>/workflows/scripts/*.js, not under<project>'s slug. On this machine (counted 2026-09-30 18:47 CEST) there are 21 such scripts in 9 foreign slug folders, against 35 in the correct one. The oldest is from 2026-08-31. Those foreign folders contain only scripts, with no transcripts or memory. WhetherresumeFromRunIdstill finds these runs was not tested. - The documented way back is
ccd_directory__change_directory, which has two problems:
- It apparently needs approval. The tool description shown to the model says "the user sees and approves that exact folder (in bypass permissions mode it is granted without asking)". In auto mode, 10.6 s, 12.9 s and 15.3 s passed between call and result in the 3 observed calls. That this was the approval wait is inferred from the delay, not measured.
- It applies only at the end of the turn. The tool result says "The session's working directory will move to this folder when the current turn ends. Until then, use this exact absolute path…". Until then the only visible effect was that
<project>was added toadditionalWorkingDirectories(in 2 of the 3 observed calls; in the third it was already listed).
- Consequence without a human present: the turn keeps running with the foreign primary directory. In one observed session, a Workflow run started about 2.5 minutes after the
change_directorycall and its script went to the foreign slug. The primary directory came back 6 minutes after the call, 7 s after acdto a path outside the allowed directories; whether the "Shell cwd was reset to …" that such acdtriggers, or the end of the turn, brought it back was not determined. In a second session (2026-09-24) the pattern was the same:change_directorycall, turn ended 39 s later, the primary-directory change was recorded only with the next user prompt about 20 minutes later.
Subagent transcripts show no such change. Since 2026-09-15 they contain 2,308 Bash commands starting with cd (386 transcript files) with 0 working-directory changes and 0 "Shell cwd was reset" messages. In 4 cases (Workflow subagents) a standalone pwd afterwards returned the project directory. The mechanism behind the difference was not verified.
Where it appears to come from (read from the minified 2.1.284 bundle, so function identities are inferred from proximity): after each Bash/PowerShell command the harness resets the shell cwd to originalCwd only when the current cwd is outside the allowed directories, unless CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR is truthy, in which case it resets after every command. The environment snapshot that produces "Primary working directory: … (was …)" takes its cwd from the shell's current cwd.
What Should Happen?
These are questions, not requests:
- Is it intended that a Bash
cdinto an additional working directory changes the session's primary working directory, including the project slug that Workflow uses for its scripts, when switching back needs user approval and applies only at end of turn? - Should
CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR=1be the default for the Desktop Code tab, as #35058 asked for in March?
Error Messages/Logs
Steps to Reproduce
- In the Desktop Code tab, open a session on
C:\Users\<user>\Documents\<project>withC:\Users\<user>\Documentsas an additional working directory. Permission mode auto.CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIRnot set. - Ask Claude to run
cd "C:/Users/<user>/Documents/<other-dir>" && pwdvia Bash (<other-dir>is any folder underDocumentsother than<project>). - Still in the same turn, an "Environment update — Primary working directory … (was …)" reminder arrives before the model's next step, and the transcript
cwdfield changes to<other-dir>. Expected: a standalonepwdin a later Bash call also returns<other-dir>. - Start any Workflow. Its script is written under the
<other-dir>slug in~/.claude/projects/.
Claude Model
Not sure / Multiple models
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.1.284
Platform
Other
Operating System
Windows
Terminal/Shell
Other
Additional Information
- Related, locked: #35058 "[BUG] Bash tool
cdwithin project root persists across calls by default — breaks statusline, enables silent directory drift" (Windows 11, 2.1.76, opened 2026-03-16). It was closed as a duplicate of #31471 on 2026-03-20 and locked on 2026-03-27; #31471 is closednot_plannedand locked. That issue predates the Environment update reminder and the Workflow slug effect. - Related, different: #81291 (
${CLAUDE_PROJECT_DIR}resolves against a drifted cwd after a mid-session cd; closednot_planned) and #97902 (parallel Bash calls share the shell's working directory; open). - Not this report: #42837 and #42844 describe the opposite behavior (
cdno longer persisting, macOS, April 2026); both closed.
Claude Code Version / Platform / OS / Shell
- Claude Code 2.1.284, running as the Code tab of Claude Desktop (transcript
entrypoint: claude-desktop). The "Environment update" reminder described below was seen on every version from 2.1.260 to 2.1.284 present in local transcripts; the underlyingcdpersistence is present from 2.1.209 (oldest local transcript) on. - Claude Desktop 2.16120.0.0 (Windows Store/MSIX package
Claude_2.16120.0.0, package folder created 2026-09-29). The Desktop version at earlier dates is not known. The last local Desktop log (2026-08-22) shows Desktop 1.34493.1 with Code 2.1.234. - Windows 10 Pro 10.0.19045. Bash tool = Git Bash.
- Session config: primary working directory
C:\Users\<user>\Documents\<project>, additional working directoriesC:\Users\<user>\DocumentsandC:\Users\<user>\.claude. Permission mode: auto.
Is this a regression? / Onset
Unclear. The following is what the local data show:
- The
cdpersistence (transcriptcwdchanging aftercdinto an additional directory) is present from the oldest local transcript (2026-07-14, 2.1.209). Nothing older is on disk. - The "Environment update — Primary working directory" attachment appears in transcripts from 2.1.260 on (first
environmentrecord 2026-09-04, firstworkingDirectorychange 2026-09-05). Before that, no context attachments of that family (environment,instructions,session_context, …) are stored at all. So the data cannot tell whether the model started receiving the reminder in 2.1.260, or whether it was only first persisted then. - The Workflow-slug effect predates 2.1.260: first seen 2026-08-31, in a session that ran 2.1.247/2.1.255/2.1.258.
- The user has shared the same additional directories (
Documents,.claude) with sessions for a long time and noticed problems only around mid-September. The transcripts show no change in any of the channels above around 2026-09-15. Whatever changed then (for examplechange_directoryapproval behavior or the Desktop version) was not measured.
Frequency (local transcripts, main threads only)
- Measured 2026-09-15 to 2026-09-30 18:05 CEST: 133 primary-directory switches in 28 sessions (29 transcript files) out of 93 main-session transcripts. In the same period the main thread ran 454 Bash commands starting with
cd; 133 of them caused a switch (the rest went to the directory the shell was already in, or outside the allowed directories). The shapes of the switching commands werecd X && …90×,cd X; …26× and other or not attributable 17×. Of 98 moves away from the project directory, 40 never returned within the same session. - Measured 2026-09-05 to 2026-09-30: 408 "Environment update" working-directory changes in total.
- Measured 2026-07-14 to 2026-09-04 (2.1.209–2.1.258): 332 main-thread
cdcommands intoDocuments/…or.claude/…changed the transcriptcwdfield with no Environment update reminder stored.
Workaround (verified once)
Add "CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR": "1" to env in ~/.claude/settings.json. This took effect in the already running Desktop session, without a restart. Settings were saved at 18:21:38 CEST. At 18:21:51, cd "…/Documents/<other-dir>" && pwd printed <other-dir>, and at 18:21:55 a standalone pwd printed the project directory. No environment / workingDirectory record followed in any main transcript. Observation time after the change is short (local transcript data end at 18:37), and this is one measurement in one session.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗