Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion hooks/hooks.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PLUGIN_ROOT}/hooks/session-start.sh"
"command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/run-hook.cmd\" session-start"
}
]
}
Expand Down
34 changes: 24 additions & 10 deletions hooks/run-hook.cmd
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
: << 'CMDBLOCK'
@echo off
REM ============================================================================
REM DEPRECATED: This polyglot wrapper is no longer used as of Claude Code 2.1.x
REM Polyglot wrapper to run .sh scripts cross-platform
REM ============================================================================
REM
REM Claude Code 2.1.x changed the Windows execution model for hooks:
Expand All @@ -18,26 +18,40 @@ REM became:
REM bash "run-hook.cmd" session-start.sh
REM ...and bash cannot execute a .cmd file.
REM
REM The fix: hooks.json now calls session-start.sh directly. Claude Code 2.1.x
REM handles the bash invocation automatically on Windows.
REM Solution: Pass script names WITHOUT the .sh suffix in hooks.json, and
REM auto-append .sh inside this wrapper. This avoids Claude Code's
REM .sh detection while maintaining cross-platform compatibility.
REM
REM This file is kept for reference and potential backward compatibility.
REM Usage: run-hook.cmd <script-name-without-sh> [args...]
REM Example: run-hook.cmd session-start (will execute session-start.sh)
REM ============================================================================
REM
REM Original purpose: Polyglot wrapper to run .sh scripts cross-platform
REM Usage: run-hook.cmd <script-name> [args...]
REM The script should be in the same directory as this wrapper

if "%~1"=="" (
echo run-hook.cmd: missing script name >&2
exit /b 1
)
"C:\Program Files\Git\bin\bash.exe" -l "%~dp0%~1" %2 %3 %4 %5 %6 %7 %8 %9
set "SCRIPT_NAME=%~1"
shift
REM Auto-append .sh suffix to avoid Claude Code 2.1.x auto-detecting .sh and prepending bash
REM Disable MSYS2 path conversion to prevent corruption of forwarded arguments
set "MSYS2_ARG_CONV_EXCL=*"
REM Use CLAUDE_BASH_EXE if set, otherwise default to Git Bash
REM Note: %* is not affected by shift in batch, so we use shift inside bash -c to skip the script name
if defined CLAUDE_BASH_EXE (
"%CLAUDE_BASH_EXE%" -l -c "shift; \"$(cygpath -u \"$CLAUDE_PLUGIN_ROOT\")/hooks/%SCRIPT_NAME%.sh\" \"$@\"" -- %*
) else (
"C:\Program Files\Git\bin\bash.exe" -l -c "shift; \"$(cygpath -u \"$CLAUDE_PLUGIN_ROOT\")/hooks/%SCRIPT_NAME%.sh\" \"$@\"" -- %*
)
exit /b
CMDBLOCK

# Unix shell runs from here
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
SCRIPT_NAME="$1"
if [ -z "$SCRIPT_NAME" ]; then
echo "run-hook.cmd: missing script name" >&2
exit 1
fi
shift
"${SCRIPT_DIR}/${SCRIPT_NAME}" "$@"
# Auto-append .sh suffix to match Windows behavior
"${SCRIPT_DIR}/${SCRIPT_NAME}.sh" "$@"