[BUG] Native installer on Windows: bash hooks resolve to WSL bash.exe instead of Git Bash, causing TUI hang with broken timeout
Preflight Checklist
- [x] I have searched existing issues and this has not 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 is Wrong?
On Windows 11 with the native installer (v2.1.81), hooks that invoke bash resolve to C:\Windows\System32\bash.exe (the WSL launcher stub) instead of Git Bash (C:\Program Files\Git\bin\bash.exe). This causes hooks to hang indefinitely, freezing the entire TUI — no input accepted, no commands execute, and the configured timeout on the hook is ignored.
Root Cause
The native installer (claude.exe) spawns hook subprocesses using the system PATH rather than inheriting the launching terminal PATH. On Windows 10/11, C:\Windows\System32\bash.exe (WSL stub) exists by default — even without a full WSL distribution installed. This stub takes priority over Git Bash in the system PATH.
When the hook runs under WSL bash, it enters a different environment that lacks the user SSH keys, jq, git config, and other tools, causing the script to hang waiting for input or network access.
Two Sub-Bugs
- PATH resolution change (breaking): Prior versions (launched from Git Bash terminal) inherited the terminal PATH, so
bashcorrectly resolved to Git Bash. v2.1.81 native installer changed this behavior without documentation.
- Hook timeout does not kill the process: Even with
"timeout": 30000configured on the hook, the TUI freezes completely. The timeout mechanism fails to terminate the hung subprocess.
Steps to Reproduce
- Install Claude Code via native installer on Windows 11
- Have Git for Windows installed (
C:\Program Files\Git\bin\bash.exe) - Confirm WSL stub exists:
where.exe bashshowsC:\Windows\System32\bash.exebefore Git Bash - Add a bash hook in
settings.json:
``json``
{
"hooks": {
"SessionStart": [{
"hooks": [{
"type": "command",
"command": "bash \"C:/Users/MyUser/myscript.sh\"",
"timeout": 30000
}]
}]
}
}
- Launch
claudefrom Git Bash - The TUI freezes — no prompt appears, no input accepted
Expected Behavior
- Hooks should either inherit the launching terminal PATH, or Claude Code should prefer Git Bash over WSL stub on Windows
- At minimum, the
timeoutsetting should work and kill hung hook subprocesses instead of freezing the entire TUI
Workaround
Use a Node.js wrapper that calls Git Bash via execFileSync with an absolute path, bypassing PATH resolution entirely:
// bash-wrapper.js
const { execFileSync } = require("child_process");
const fs = require("fs");
const gitBash = "C:/Program Files/Git/bin/bash.exe";
if (!fs.existsSync(gitBash)) process.exit(1);
try {
execFileSync(gitBash, process.argv.slice(2), {
stdio: "inherit", timeout: 30000, windowsHide: true
});
} catch (e) { process.exit(e.status || 0); }
Then in hooks: node bash-wrapper.js myscript.sh
Environment
- Claude Code: v2.1.81 (native installer)
- OS: Windows 11
- Terminal: Git Bash (MINGW64)
- Git:
C:\Program Files\Git\cmd\git.exe where.exe bashoutput:
```
C:\Windows\System32\bash.exe
C:\Users\Gower\AppData\Local\Microsoft\WindowsApps\bash.exe
C:\Program Files\Git\bin\bash.exe` is NOT in system PATH)
(Git Bash at
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗