mirror of
https://github.com/obra/superpowers.git
synced 2026-06-12 05:39:05 +08:00
docs(windows): trim polyglot hook implementation copy
This commit is contained in:
@@ -53,74 +53,36 @@ hooks/
|
|||||||
|
|
||||||
The path is quoted because `${CLAUDE_PLUGIN_ROOT}` may contain spaces.
|
The path is quoted because `${CLAUDE_PLUGIN_ROOT}` may contain spaces.
|
||||||
|
|
||||||
## How `run-hook.cmd` Works
|
## How `run-hook.cmd` Works at a High Level
|
||||||
|
|
||||||
`run-hook.cmd` is a polyglot script — valid syntax in both CMD and bash:
|
`run-hook.cmd` is a polyglot script: Windows treats the first block as batch
|
||||||
|
commands, while Unix shells treat that block as a no-op heredoc and continue
|
||||||
|
after it.
|
||||||
|
|
||||||
```cmd
|
Do not copy an implementation from this document. Read `hooks/run-hook.cmd`
|
||||||
: << 'CMDBLOCK'
|
directly when changing the dispatcher, and run `tests/hooks/test-session-start.sh`
|
||||||
@echo off
|
afterward.
|
||||||
REM Cross-platform polyglot wrapper for hook scripts.
|
|
||||||
REM On Windows: cmd.exe runs the batch portion, which finds and calls bash.
|
|
||||||
REM On Unix: the shell interprets this as a script (: is a no-op in bash).
|
|
||||||
REM
|
|
||||||
REM Hook scripts use extensionless filenames (e.g. "session-start" not
|
|
||||||
REM "session-start.sh") so Claude Code's Windows auto-detection -- which
|
|
||||||
REM prepends "bash" to any command containing .sh -- doesn't interfere.
|
|
||||||
REM
|
|
||||||
REM Usage: run-hook.cmd <script-name> [args...]
|
|
||||||
|
|
||||||
if "%~1"=="" (
|
|
||||||
echo run-hook.cmd: missing script name >&2
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
|
|
||||||
set "HOOK_DIR=%~dp0"
|
|
||||||
|
|
||||||
REM Try Git for Windows bash in standard locations
|
|
||||||
if exist "C:\Program Files\Git\bin\bash.exe" (
|
|
||||||
"C:\Program Files\Git\bin\bash.exe" "%HOOK_DIR%%~1" %2 %3 %4 %5 %6 %7 %8 %9
|
|
||||||
exit /b %ERRORLEVEL%
|
|
||||||
)
|
|
||||||
if exist "C:\Program Files (x86)\Git\bin\bash.exe" (
|
|
||||||
"C:\Program Files (x86)\Git\bin\bash.exe" "%HOOK_DIR%%~1" %2 %3 %4 %5 %6 %7 %8 %9
|
|
||||||
exit /b %ERRORLEVEL%
|
|
||||||
)
|
|
||||||
|
|
||||||
REM Try bash on PATH (e.g. user-installed Git Bash, MSYS2, Cygwin)
|
|
||||||
where bash >nul 2>nul
|
|
||||||
if %ERRORLEVEL% equ 0 (
|
|
||||||
bash "%HOOK_DIR%%~1" %2 %3 %4 %5 %6 %7 %8 %9
|
|
||||||
exit /b %ERRORLEVEL%
|
|
||||||
)
|
|
||||||
|
|
||||||
REM No bash found - exit silently rather than error
|
|
||||||
REM (plugin still works, just without SessionStart context injection)
|
|
||||||
exit /b 0
|
|
||||||
CMDBLOCK
|
|
||||||
|
|
||||||
# Unix: run the named script directly
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
||||||
SCRIPT_NAME="$1"
|
|
||||||
shift
|
|
||||||
exec bash "${SCRIPT_DIR}/${SCRIPT_NAME}" "$@"
|
|
||||||
```
|
|
||||||
|
|
||||||
### How it works on Windows (CMD.exe)
|
### How it works on Windows (CMD.exe)
|
||||||
|
|
||||||
1. `: << 'CMDBLOCK'` — CMD sees `:` as a label (no-op) and ignores `<< 'CMDBLOCK'`
|
1. The batch section validates the script name and resolves the hook directory
|
||||||
2. The batch section validates the script name, resolves `HOOK_DIR` from the dispatcher's own location, then tries bash in three places:
|
from the dispatcher's own location.
|
||||||
|
2. It tries bash in three places:
|
||||||
- `C:\Program Files\Git\bin\bash.exe`
|
- `C:\Program Files\Git\bin\bash.exe`
|
||||||
- `C:\Program Files (x86)\Git\bin\bash.exe`
|
- `C:\Program Files (x86)\Git\bin\bash.exe`
|
||||||
- `bash` on `PATH` (MSYS2, Cygwin, or a non-default Git install)
|
- `bash` on `PATH` (MSYS2, Cygwin, or a non-default Git install)
|
||||||
3. If no bash is found, the dispatcher exits `0` silently — the plugin continues working, it just skips the hook
|
3. If bash is found, it runs the named extensionless hook script from the hooks
|
||||||
4. `exit /b` stops CMD before it reaches the Unix section
|
directory.
|
||||||
|
4. If no bash is found, the dispatcher exits `0` silently — the plugin
|
||||||
|
continues working, it just skips the hook.
|
||||||
|
5. `exit /b` stops CMD before it reaches the Unix section.
|
||||||
|
|
||||||
### How it works on Unix (bash/sh)
|
### How it works on Unix (bash/sh)
|
||||||
|
|
||||||
1. `: << 'CMDBLOCK'` — `:` is a no-op; `<< 'CMDBLOCK'` opens a heredoc
|
1. `: << 'CMDBLOCK'` opens a heredoc on a no-op command.
|
||||||
2. The entire CMD batch block is consumed by the heredoc (ignored)
|
2. The entire CMD batch block is consumed by the heredoc and ignored.
|
||||||
3. After `CMDBLOCK`, bash resolves the script directory and `exec`s the named extensionless script directly
|
3. After `CMDBLOCK`, bash resolves the script directory and `exec`s the named
|
||||||
|
extensionless script directly.
|
||||||
|
|
||||||
### Key design decisions
|
### Key design decisions
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user