docs: describe the :; label-line wrapper mechanism (#571)

This commit is contained in:
Drew Ritter
2026-08-05 15:16:30 -07:00
parent d80fc1808a
commit f2bbe9ff92
2 changed files with 15 additions and 9 deletions
+4 -2
View File
@@ -745,8 +745,10 @@ single file that's valid as both a Windows batch script and a Unix shell script.
On Windows, `cmd.exe` runs the batch portion, which locates `bash` (Git for
Windows, then `bash` on PATH) and runs the named hook script; if no bash is
found it exits cleanly so the harness still works, just without injection. On
Unix, the leading `:` makes the batch block a no-op and the shell runs the
script directly.
Unix, the shell executes the leading `:;` lines and `exec`s the hook script
before reaching the batch block (cmd.exe skips those lines as labels).
Heredocs are banned throughout hooks/ — see issue #571 and the fence test
`tests/hooks/test-no-heredocs-in-hooks.sh`.
Two rules this enforces, which you must respect:
+11 -7
View File
@@ -65,9 +65,9 @@ The path is quoted because `${CLAUDE_PLUGIN_ROOT}` may contain spaces.
## How `run-hook.cmd` Works at a High Level
`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.
`run-hook.cmd` is a polyglot script: its first lines start with `:;`, which
cmd.exe skips as labels and Unix shells execute — the shell execs the hook
before ever reaching the batch block that Windows runs.
Do not copy an implementation from this document. Read `hooks/run-hook.cmd`
directly when changing the dispatcher, and run `tests/hooks/test-session-start.sh`
@@ -89,10 +89,14 @@ afterward.
### How it works on Unix (bash/sh)
1. `: << 'CMDBLOCK'` opens a heredoc on a no-op command.
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.
1. Each leading `:;` line is a no-op label to cmd.exe but real commands to a
POSIX shell.
2. The shell checks bash exists (silent exit 0 if not), resolves the script
directory CDPATH-proof, and `exec`s the named extensionless script — it
never reads the batch block at all.
3. Heredocs are banned in this file and all hooks/ executables (issue #571:
bash >= 5.1 pre-fork pipe writes deadlock on macOS under pipe pressure);
`tests/hooks/test-no-heredocs-in-hooks.sh` enforces the ban.
### Key design decisions