Hook scripts fail on Windows: backslash paths misinterpreted by Git Bash
Bug Description
On Windows with CLAUDE_CODE_SHELL set to Git Bash, all plugin hook scripts fail because ${CLAUDE_PLUGIN_ROOT} is resolved to a Windows backslash path (e.g., C:\Users\...\hooks\session-start.sh), which Git Bash interprets as escape sequences instead of path separators.
Environment
- OS: Windows 11
- Claude Code version: 2.1.23
- Shell: Git Bash (
C:\Program Files\Git\bin\bash.exe) configured viaCLAUDE_CODE_SHELL - Bash version: GNU bash 5.2.26(1)-release (x86_64-pc-msys)
Steps to Reproduce
- On Windows, set
CLAUDE_CODE_SHELLto Git Bash insettings.json:
``json``
{ "env": { "CLAUDE_CODE_SHELL": "C:\\Program Files\\Git\\bin\\bash.exe" } }
- Install any plugin with hooks (e.g.,
superpowersfrom superpowers-marketplace, which has aSessionStarthook) - Start a new Claude Code session
- Observe
SessionStart:startup hook errormessage
Root Cause
When Claude Code executes a hook command like:
${CLAUDE_PLUGIN_ROOT}/hooks/session-start.sh
It resolves ${CLAUDE_PLUGIN_ROOT} to a Windows-format path with backslashes:
C:\Users\username\.claude\plugins\cache\superpowers-marketplace\superpowers\4.1.1\hooks\session-start.sh
Git Bash interprets \U, \u, \., \p, \s, etc. as escape sequences, resulting in a garbled path:
C:Usersusername.claudepluginscache... command not found
Debug Log Evidence
[DEBUG] Getting matching hook commands for SessionStart with query: startup
[DEBUG] Found 1 hook matchers in settings
[DEBUG] Matched 1 unique hooks for query "startup" (1 before deduplication)
[DEBUG] Hook output does not start with {, treating as plain text
The hook produces output (the "command not found" error message) instead of the expected JSON, so Claude Code falls back to treating it as plain text.
Reproduction Test
# This is what Claude Code effectively does:
"C:\Program Files\Git\bin\bash.exe" -c 'C:\Users\username\.claude\plugins\cache\superpowers-marketplace\superpowers\4.1.1\hooks\session-start.sh'
# Output: /usr/bin/bash: line 1: C:Usersusername.claudeplugins...session-start.sh: command not found
# Correct behavior with Unix-style path:
"C:\Program Files\Git\bin\bash.exe" -c '/c/Users/username/.claude/plugins/cache/superpowers-marketplace/superpowers/4.1.1/hooks/session-start.sh'
# Output: valid JSON
Affected Plugins
Any plugin using shell script hooks is affected. Confirmed with:
superpowers(SessionStart hook)security-guidance(PreToolUse hook)
Expected Behavior
Claude Code should convert Windows backslash paths to forward-slash or POSIX-style paths (e.g., /c/Users/...) before passing them to Git Bash for execution.
Suggested Fix
When CLAUDE_CODE_SHELL points to Git Bash (or any MSYS2/Cygwin-based shell), convert resolved ${CLAUDE_PLUGIN_ROOT} paths from C:\... to /c/... format before executing hook commands.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗