Skip to content

SessionStart hook fails on Windows — hooks.json points to .sh file which CMD.exe cannot execute #491

@azereki

Description

@azereki

Description

The SessionStart hook fails on Windows with the error:

SessionStart:startup hook error

Root Cause

Claude Code runs hook commands through CMD.exe on Windows. The current hooks.json points directly to a .sh file:

"command": "${CLAUDE_PLUGIN_ROOT}/hooks/session-start.sh"

CMD.exe cannot execute .sh files — it either errors or tries to open them in a text editor.

Context

The plugin previously used a polyglot run-hook.cmd wrapper (still present in hooks/run-hook.cmd), but it was removed from hooks.json based on the assumption that Claude Code 2.1.x auto-detects .sh files and prepends bash on Windows. As of Claude Code 2.1.44, this auto-detection does not appear to work for plugin hooks. The run-hook.cmd file itself documents this change:

After (2.1.x): Claude Code now auto-detects .sh files in hook commands
               and prepends "bash " on Windows.

The plugin's own documentation at docs/windows/polyglot-hooks.md describes the correct pattern with .cmd wrappers and even lists this exact failure mode under Troubleshooting:

Script opens in text editor instead of running
The hooks.json is pointing directly to the .sh file. Point to the .cmd wrapper instead.

Environment

  • Windows 10
  • Claude Code 2.1.44
  • Git for Windows installed at default path
  • Shell: Git Bash

Reproduction

  1. Install superpowers plugin on Windows
  2. Start a new Claude Code session
  3. Observe SessionStart:startup hook error

Fix

Create a polyglot session-start.cmd wrapper and update hooks.json to reference it:

hooks/session-start.cmd:

: << 'CMDBLOCK'
@echo off
"C:\Program Files\Git\bin\bash.exe" -l "%~dp0session-start.sh"
exit /b
CMDBLOCK

# Unix shell runs from here
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)"
"${SCRIPT_DIR}/session-start.sh"

hooks/hooks.json:

{
  "hooks": {
    "SessionStart": [
      {
        "matcher": "startup|resume|clear|compact",
        "hooks": [
          {
            "type": "command",
            "command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/session-start.cmd\"",
            "async": false
          }
        ]
      }
    ]
  }
}

Verified working on Windows 10 via cmd /c invocation.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions