Skip to content

Hooks spawn visible Git Bash windows on Windows (add shell: powershell) #79

@renatasofianet

Description

@renatasofianet

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

  1. Windows 11, Git for Windows installed, Claude Code installed
  2. Install vercel-plugin@0.42.1
  3. Open Claude Code
  4. Three black bash --login -i -c node "..." windows flash on startup, one per SessionStart hook

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:

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions