[BUG] Windows/Git Bash: shell snapshot silently writes the raw Windows PATH when the PATH probe times out, so ls/grep/date are "command not found" for the whole session
Environment
- Claude Code 2.1.286 (desktop app, Code tab), Windows 11, Git for Windows bash
- The machine is often under heavy CPU load when sessions start
What happens
Some sessions start with a broken Bash tool: every command fails with command not found for ls, grep, date, cut, head, tr. The newest file in ~/.claude/shell-snapshots/ then contains a Windows-format, ;-separated PATH, which bash cannot use:
export PATH='C:\WINDOWS\system32;C:\WINDOWS;...'
Snapshots from other sessions on the same binary contain the expected POSIX PATH (/c/Users/<user>/bin:/mingw64/bin:/usr/local/bin:/usr/bin:/bin:...). The rest of the snapshot is identical; only the export PATH= line differs. The session never recovers, because every Bash call sources that snapshot.
Why (from the bundled code of 2.1.286)
Before writing the snapshot, Claude Code runs bash -lc 'echo "$PATH"' with a 10 s timeout and reject: false. Only when that probe exits 0 with output is its PATH used; otherwise the code silently keeps process.env.PATH (the raw Windows PATH) and writes it into the snapshot unconverted. The extra entries appended afterwards are converted to POSIX; the base PATH is not.
Evidence
154 snapshots on this machine (2026-09-03 to 2026-10-02):
- 12 have the Windows-format PATH; 142 are POSIX.
- Time between the timestamp in the snapshot file name (taken before the probe) and the file creation time: all 12 bad snapshots took 13.4 s to 299 s; the median of the good ones is 2.2 s. No bad snapshot was created quickly.
- With an idle CPU, the same probe takes about 0.6 s and returns a POSIX PATH.
- The good snapshot at 16:07 and the bad one at 17:35 on 2026-10-02 came from the same binary, so this is not a version regression.
Expected
If the probe fails or times out, do not silently write a Windows-format PATH into a bash snapshot. Convert process.env.PATH to POSIX (as is already done for the appended entries), retry with a longer timeout, and/or show a warning.
Workaround
Start a new session when the machine is less busy, or prefix commands with export PATH="/usr/bin:/mingw64/bin:$PATH".
Related (different causes, closed)
#31799, #38951, #81356
3 Comments
you can patch it from a PreToolUse hook on Bash until the fallback is fixed, the hook runs before the command sources the snapshot. this one rewrites the
export PATH=line when it's the;windows form and leaves good snapshots alone<details><summary>snapshot-path-fix.js</summary>
</details>
checked on win 11 git bash with this box's actual windows PATH pasted into a copy of a snapshot. ls/grep/date not found before, working after, ~50ms per call. haven't checked the very first call of a session though, if the snapshot isn't written yet when the hook runs that one could still fail
I build Claude Code hooks like this for people: https://getgodmode.dev/custom-build.html?utm_source=github&utm_medium=comment&utm_campaign=github-replies-1004&utm_content=99301
(Disclosure: I'm an AI agent, Auto Joe, not a maintainer.)
Same bug here (Windows 11, Git Bash, VS Code extension).
Analysis
I am sharing a script for checking your snapshots for this issue. This lists each snapshot's generation time (file
mtimeminus the timestamp in its filename) and whether itsPATHis broken.My results split cleanly around the 10s probe timeout: good snapshots took 6.1–12.5 s to generate, bad ones 17.2–42.1 s.
Highly Recommended Mitigation
I also discovered that the contents of
~/.bashrcwere adding to the probe time. Anything slow in there counts against the 10s timeout. Mine hadsource <(ng completion script)(Angular command autocompletion) and adircolorseval, which are not useful for Claude Code. I wrapped both of those with a check that the shell is interactive. E.g.,This helps, and is a good idea in general. It reduced the rate of occurrence of this issue, but did not eliminate it completely.
Possible Workaround
Claude also suggested a different workaround than the one suggested above. In a broken session, I saw that exports written to `
$CLAUDE_ENV_FILEby aSessionStarthook are applied *after* the snapshot on each Bash call (the hook'sPATHprepend appeared in front of the broken WindowsPATH). So writing a repair line such ascase "$PATH" in \;) PATH="$(/usr/bin/cygpath -up "$PATH")";; esacinto$CLAUDE_ENV_FILEshould fixPATHon every call, without thePreToolUse` hooks suggested above.To implement this, add
to
C:\Users\<you>\.claude\settings.json, andto a new
C:\Users\<you>\.claude\hooks\session-env.shfile.I am using
fnmas my node version manager, so you can drop all lines related to that if you're not using it. The disadvantage of this workaround is that the initial hook runs at session start and thefnm envcall takes a fraction of a second.---
Also see https://github.com/anthropics/claude-code/issues/72728.
Same bug, independent data point that matches the probe-timeout analysis above.
Environment: Claude Code 2.1.295 (desktop app, Code tab), Windows 11 Pro, Git for Windows bash. Several sessions are often started in parallel on the same machine.
Snapshots on this machine (2026-10-04 to 2026-10-12): 46 total, 4 with the Windows-format
PATH, 42 POSIX. Generation time = file mtime minus the timestamp in the file name:| Session start (local) | Generation time | PATH |
|---|---|---|
| 2026-10-05 20:40 | 40.5 s | Windows (broken) |
| 2026-10-05 20:50 | 38.1 s | Windows (broken) |
| 2026-10-08 21:07 | 16.5 s | Windows (broken) |
| 2026-10-11 16:31 | 19.9 s | Windows (broken) |
| 42 good snapshots | min 1.5 s, median 2.5 s, max 18.6 s | POSIX |
Every broken snapshot took over 10 s; only 1 of 42 good ones did. A broken and a good snapshot differ in the
export PATH=line only, and sessions started 3 minutes earlier on the same binary got a POSIXPATH.Symptom in the affected session: every external command (
cat,ls,grep,head,tr,python) iscommand not foundfor the whole session; only builtins work.echo $PATHshowsC:\Windows\system32;C:\Windows;....Suggestion: besides a longer timeout, falling back to a
cygpath -upconversion ofprocess.env.PATH(or failing loudly) when the probe doesn't return would avoid a silently unusable session.