[BUG] :Hooks always executed via `/usr/bin/bash` on Windows, ignoring `shell` setting
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?
Environment
- OS: Windows 11
- Claude Code Version: Latest
- Shell: PowerShell
- Git Bash: Installed (required for Git, not preferred for Claude Code hooks)
---
Describe the Bug
On Windows, every hook command defined in settings.json is executed via:
/usr/bin/bash --login -i -c <command>
This causes a Git Bash terminal window to visibly pop up on screen every time a hook fires (SessionStart, PostToolUse, statusLine). With multiple hooks configured, multiple bash windows appear simultaneously, stealing focus and disrupting workflow.
This happens regardless of the shell setting in settings.json.
What Should Happen?
---
Expected Behavior
- Hooks should respect the
shellsetting insettings.json - When
"shell": "powershell.exe"is configured, hooks should run via PowerShell - No unexpected terminal windows should appear during hook execution
- At minimum, hooks should run with
windowsHide: trueto suppress the window
Actual Behavior
Every hook is wrapped in /usr/bin/bash --login -i -c <command>, causing:
- Multiple Git Bash windows popping up simultaneously
- Windows stealing focus during active work
- Poor experience on Windows with PowerShell as preferred shell
---
Error Messages/Logs
Steps to Reproduce
---
Steps to Reproduce
- Install Claude Code on Windows with Git Bash installed
- Configure hooks in
settings.json:
{
"hooks": {
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "node \"C:/Users/username/.claude/hooks/my-hook.js\""
}
]
}
]
},
"shell": "powershell.exe",
"shellArgs": ["-NoProfile", "-Command"]
}
- Start Claude Code
- Observe Git Bash window(s) popping up on every hook execution
Possible Fix
When spawning hook processes on Windows, use the configured shell from settings.json, or at minimum pass windowsHide: true to the Node.js spawn/exec call so the window is suppressed:
spawn(command, args, {
windowsHide: true, // Prevents window popup on Windows
shell: configuredShell || false
})
---
Claude Model
Sonnet (default)
Is this a regression?
Last Working Version
_No response_
Claude Code Version
2.1.72 (Claude Code)
Platform
Operating System
Windows
Terminal/Shell
PowerShell
Additional Information
Additional Context
- Using
get-shit-done-ccGSD plugin with 3 hooks (SessionStart, PostToolUse, statusLine) - All hooks are simple Node.js scripts
- Full node.exe path in commands does not resolve the issue — bash wrapping happens at Claude Code level, before the command is executed
- The
"shell": "powershell.exe"setting works for the terminal but is completely ignored for hook execution
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗