Hooks spawn visible Git Bash windows on Windows (add shell: powershell)
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 287
- Forks
- 58
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 17
Description
Problem
On Windows, every hook in hooks/hooks.json opens a visible Git Bash console window on session start (and one more on session end). With three SessionStart hooks, three black bash windows pop up briefly every time Claude Code starts.
Window title:
/usr/bin/bash --login -i -c node "/c/Users/.../plugins/cache/.../hooks/session-start-seen-skills.mjs"
The -i (interactive) flag is what forces Git Bash to show a real terminal window.
Reproduction
- Windows 11, Git for Windows installed, Claude Code installed
- Install
vercel-plugin@0.42.1 - Open Claude Code
- Three black
bash --login -i -c node "..."windows flash on startup, one perSessionStarthook
Root cause
Claude Code''s Windows harness wraps every hook command string in bash --login -i -c "<cmd>" when no shell field is set on the hook.
Anthropic closed both upstream feature requests for hiding the console window:
- anthropics/claude-code#19012 — closed as not planned
- anthropics/claude-code#17230 — closed as not planned
So no fix is coming from the harness side; it has to be configured per-hook by plugins.
Suggested fix
Per the official hooks reference, each command hook accepts a "shell" field with values "bash" (default) or "powershell". Setting "shell": "powershell" makes the harness spawn the command via PowerShell directly, with no bash --login -i wrapping, and PowerShell is spawned hidden on Windows.
Patch for hooks/hooks.json:
{
"hooks": {
"SessionStart": [
{
"matcher": "startup|resume|clear|compact",
"hooks": [
{
"type": "command",
- "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/session-start-seen-skills.mjs\""
+ "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/session-start-seen-skills.mjs\"",
+ "shell": "powershell"
},
{
"type": "command",
- "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/session-start-profiler.mjs\""
+ "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/session-start-profiler.mjs\"",
+ "shell": "powershell"
},
{
"type": "command",
- "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/inject-claude-md.mjs\""
+ "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/inject-claude-md.mjs\"",
+ "shell": "powershell"
}
]
}
],
"SessionEnd": [
{
"hooks": [
{
"type": "command",
- "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/session-end-cleanup.mjs\""
+ "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/session-end-cleanup.mjs\"",
+ "shell": "powershell"
}
]
}
]
}
}
Verified locally on 2026-05-10 with vercel-plugin 0.42.1 — applying the patch eliminates the visible bash windows. The hooks themselves still execute correctly (skill injection, profiler, cleanup all working).
This change is safe on macOS/Linux because "shell": "powershell" is only honored on Windows; on Unix the harness falls back to its default behavior. (Worth confirming with a quick CI run on the existing platform-hook-compat tests.)
Environment
- OS: Windows 11 Home 10.0.26200
- Claude Code: v2.1.x (bundled
claude.exe, ~226MB) - vercel-plugin: 0.42.1
- Git Bash:
C:\Program Files\Git\bin\bash.exe - Node: bundled with Claude Code
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Review hooks/hooks.json and the existing platform-hook-compat tests first. Check the SessionStart and SessionEnd command hooks and confirm the Windows shell configuration is applied consistently. Run the compatibility tests and verify on Windows that the hooks still execute without visible Git Bash windows.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- node.js, powershell
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 1/5
- Estimated time
- Under an hour
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 82/100