| name | claude-windows-hook-fix |
|---|---|
| description | Fix for Claude Code v2.1.x hooks not working on Windows. Patches cli.js to properly invoke bash as a login shell, enabling MSYS path translation. Use when Windows hooks fail with "No such file or directory" errors. |
| version | 1.0.0 |
| author | Zac Cook |
| platforms | windows |
| claude-code-versions | 2.1.x |
Claude Code v2.1.x on Windows has a critical bug where all hooks fail with errors like:
/bin/bash: /c/hooks/stop.sh: No such file or directory
This occurs even when the files exist and are accessible. The bug affects ALL hook types:
- SessionStart
- UserPromptSubmit
- PreToolUse
- PostToolUse
- Stop
- PreCompact
Claude Code executes hooks using Node.js spawn with shell: true:
hB7(V, [], {env:F, cwd:j1(), shell:!0})On Windows, Claude Code sets process.env.SHELL to the Git Bash path. When shell: true is used, Node.js invokes bash, but without the MSYS/MinGW environment that provides path translation (/c/ → C:\).
The bash process runs in a "bare" mode without:
- MSYS path translation
- Proper
$HOME(points to/home/userinstead of/c/Users/user) - MinGW environment variables
Run this command to patch Claude Code:
sed -i 's/hB7(V,\[\],{env:F,cwd:j1(),shell:!0})/hB7(process.env.SHELL||"bash",["-l","-c",V],{env:F,cwd:j1(),shell:!1})/g' "$(npm root -g)/@anthropic-ai/claude-code/cli.js"Before:
hB7(V, [], {env:F, cwd:j1(), shell:!0})After:
hB7(process.env.SHELL||"bash", ["-l","-c",V], {env:F, cwd:j1(), shell:!1})process.env.SHELL||"bash"- Uses bash path directly as the executable["-l", "-c", V]- Key flags:-l= Login shell (loads full MSYS environment including path translation)-c= Command modeV= The hook command string
shell:!1(shell: false) - Spawns bash directly, avoiding double-shell issues
The -l flag is critical - it makes bash initialize as a login shell, which loads /etc/profile and user profile scripts that set up the MSYS environment.
# Backup original
cp "$(npm root -g)/@anthropic-ai/claude-code/cli.js" "$(npm root -g)/@anthropic-ai/claude-code/cli.js.backup"
# Apply patch
sed -i 's/hB7(V,\[\],{env:F,cwd:j1(),shell:!0})/hB7(process.env.SHELL||"bash",["-l","-c",V],{env:F,cwd:j1(),shell:!1})/g' "$(npm root -g)/@anthropic-ai/claude-code/cli.js"grep -o 'process.env.SHELL.*\-l.*\-c' "$(npm root -g)/@anthropic-ai/claude-code/cli.js"Should output something containing: process.env.SHELL||"bash",["-l","-c"
cp "$(npm root -g)/@anthropic-ai/claude-code/cli.js.backup" "$(npm root -g)/@anthropic-ai/claude-code/cli.js"After any Claude Code update, re-run the patch command.
Consider creating a post-install script or alias:
alias claude-fix='sed -i '\''s/hB7(V,\[\],{env:F,cwd:j1(),shell:!0})/hB7(process.env.SHELL||"bash",["-l","-c",V],{env:F,cwd:j1(),shell:!1})/g'\'' "$(npm root -g)/@anthropic-ai/claude-code/cli.js"'With the patch applied, use Unix-style paths in your hooks:
{
"hooks": {
"Stop": [{
"hooks": [{
"type": "command",
"command": "/c/hooks/stop.sh"
}]
}]
}
}- Confirmed affected: Claude Code v2.1.9, v2.1.11
- Likely affected: All v2.1.x versions on Windows
- Platform: Windows with Git Bash
After applying the patch:
- Close all terminals
- Open a fresh terminal
- Run
claude - Verify no hook errors appear
- Test hooks execute correctly
Windows: %APPDATA%\npm\node_modules\@anthropic-ai\claude-code\cli.js
Unix path: C:/Users/<user>/AppData/Roaming/npm/node_modules/@anthropic-ai/claude-code/cli.js
The patched code is in the hook execution function. The original code at approximately line 63 (in minified form) handles spawning hook commands. The hB7 function is a wrapper around Node.js spawn.
Claude Code sets these on Windows:
SHELL→ Path to Git Bash (e.g.,C:\Program Files\Git\bin\bash.exe)CLAUDECODE=1CLAUDE_CODE_SSE_PORT→ SSE communication port
The fix ensures bash receives these AND initializes its own MSYS environment via the login shell flag.