Windows: Bash tool degrades severely over session/machine uptime (MSYS2 fork-emulation + Desktop Heap exhaustion) - consider optional WSL backend
On Windows, the Bash tool shells out through Git Bash (MSYS2). Over the course of a session — and worse, over hours of machine uptime — subprocess spawn cost through this path degrades dramatically, independent of CPU load.
Measured this session (fresh Windows machine, Git for Windows' bundled bash.exe):
- 20 sequential
git rev-parse HEADcalls: PowerShell tool completed in 2.44s (~0.12s/spawn); the Bash tool timed out at 60s+ without finishing. - A 5-iteration retry: 9.97s wall time, of which only ~0.12s was actual CPU (
user+sys) — almost the entire cost is spawn overhead, not work.
More extensive standing investigation (separate log, summarized numbers):
- Git Bash spawn cost ranges from ~0.06-0.08s/spawn immediately after a full machine reboot to 1-4.7s/spawn (and outright 60-130s timeouts on a 20-iteration loop) after hours of uptime — a 40-70x regression that a reboot fully resets and nothing short of a reboot reliably fixes.
- Native Win32 process creation (PowerShell/cmd.exe spawning
curl.exeetc.) stays flat at ~0.03-0.08s/spawn regardless of uptime, session age, or restart state — isolating the problem specifically to MSYS2/Cygwin-style fork-emulation, not a general Windows/EDR tax. - Ruled out as causes: EDR/AV overhead (tested directly), CPU contention (removed ~3 cores of sustained 100% load from runaway orphan processes, spawn cost didn't improve), orphaned processes (real, additive, but not the dominant driver).
- Root cause pattern matches Windows Desktop Heap exhaustion: a fixed, per-session kernel resource that backs every console object MSYS2's fork-emulation allocates per spawn, fragments/doesn't reliably reclaim until logoff, and is architecturally unrelated to WSL2 (which forks inside a Linux VM and never touches it).
Confirmed as a real alternative, but not usable today: C:\Windows\System32\bash.exe (the WSL launcher Windows ships) is a genuinely different, much faster path — measured ~235-260ms/spawn once warm (vs 1-3s/spawn on degraded Git Bash), and structurally immune to the degradation since it never touches MSYS2 fork-emulation or the console subsystem. However, pointing CLAUDE_CODE_GIT_BASH_PATH at it breaks every path-touching tool call: it only understands /mnt/c/..., not the /c/... convention Claude Code assumes for Git Bash, nor raw C:\... paths.
Feature request: an officially supported WSL backend for the Bash tool on Windows — i.e. CLAUDE_CODE_GIT_BASH_PATH (or a new dedicated variable) accepting a WSL distro target, with Claude Code translating the paths it generates/passes (/c/... or C:\... → /mnt/c/...) before invoking the shell. This would let Windows users with heavy Bash-tool subprocess fan-out (test suites, loops, multi-step scripts) opt into a backend that doesn't degrade over the session, without the fragility of a hand-rolled wrapper script.
Happy to share the full historical investigation log (multiple runs across reboot/restart/session-age axes) if useful.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗