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 via CLAUDE_CODE_SHELL
- Bash version: GNU bash 5.2.26(1)-release (x86_64-pc-msys)
Steps to Reproduce
- On Windows, set
CLAUDE_CODE_SHELL to Git Bash in settings.json:
{ "env": { "CLAUDE_CODE_SHELL": "C:\\Program Files\\Git\\bin\\bash.exe" } }
- Install any plugin with hooks (e.g.,
superpowers from superpowers-marketplace, which has a SessionStart hook)
- Start a new Claude Code session
- Observe
SessionStart:startup hook error message
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.
Bug Description
On Windows with
CLAUDE_CODE_SHELLset 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
C:\Program Files\Git\bin\bash.exe) configured viaCLAUDE_CODE_SHELLSteps to Reproduce
CLAUDE_CODE_SHELLto Git Bash insettings.json:{ "env": { "CLAUDE_CODE_SHELL": "C:\\Program Files\\Git\\bin\\bash.exe" } }superpowersfrom superpowers-marketplace, which has aSessionStarthook)SessionStart:startup hook errormessageRoot Cause
When Claude Code executes a hook command like:
It resolves
${CLAUDE_PLUGIN_ROOT}to a Windows-format path with backslashes:Git Bash interprets
\U,\u,\.,\p,\s, etc. as escape sequences, resulting in a garbled path:Debug Log Evidence
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
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_SHELLpoints to Git Bash (or any MSYS2/Cygwin-based shell), convert resolved${CLAUDE_PLUGIN_ROOT}paths fromC:\...to/c/...format before executing hook commands.