Hook scripts fail on Windows: backslash paths misinterpreted by Git Bash

Resolved 💬 3 comments Opened Jan 30, 2026 by RyanSparkc Closed Mar 5, 2026

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

  1. On Windows, set CLAUDE_CODE_SHELL to Git Bash in settings.json:

``json
{ "env": { "CLAUDE_CODE_SHELL": "C:\\Program Files\\Git\\bin\\bash.exe" } }
``

  1. Install any plugin with hooks (e.g., superpowers from superpowers-marketplace, which has a SessionStart hook)
  2. Start a new Claude Code session
  3. 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.

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗