mirror of
https://github.com/obra/superpowers.git
synced 2026-07-17 23:44:04 +08:00
fix(hooks): dispatch the SessionStart hook via Git Bash on Windows
The SessionStart command string starts with a quoted path, which breaks
both Windows shells Claude Code may hand it to: PowerShell parses the
leading quoted string as an expression and dies on the next bareword
('Unexpected token session-start', #1751), and cmd.exe's /c quote rule
drops the outer quotes when the path contains a metacharacter, so a
profile dir like C:\Users\Name(External) truncates the command at the
'(' (#1918). Either way the bootstrap silently never loads.
Declare shell: "bash" on the hook. Claude Code >= 2.1.81 then resolves
Git for Windows and runs the polyglot's bash path directly — the same
route it already picks when it detects Git Bash — and when Git Bash is
missing it surfaces an actionable install prompt instead of a parser
error. Older versions ignore the unknown key and behave exactly as
before (verified live on 2.0.77 and 2.1.80).
Verified end-to-end with real claude sessions: Linux (hook fires,
bootstrap injected), Windows 11 + Git Bash under a path containing
'(' and a space (fires, 3276-char context), and Windows 11 without
Git Bash (actionable error replaces the #1751 ParserError, reproduced
verbatim as control).
Fixes #1751
Fixes #1918
This commit is contained in:
@@ -143,6 +143,27 @@ for (const forbiddenText of forbiddenTexts) {
|
||||
|
||||
echo "SessionStart hook output tests"
|
||||
|
||||
# Registration shape: the hook must declare shell:"bash" so Claude Code on
|
||||
# Windows dispatches via Git Bash (or fails with an actionable error) instead
|
||||
# of PowerShell/cmd.exe, whose parsers break on the quoted command string
|
||||
# (PowerShell ParserError; cmd.exe quote-stripping on paths with metacharacters).
|
||||
if node -e '
|
||||
const hooks = JSON.parse(require("fs").readFileSync(process.argv[1], "utf8"));
|
||||
const entry = hooks.hooks.SessionStart[0].hooks[0];
|
||||
if (entry.shell !== "bash") {
|
||||
console.error(`SessionStart hook shell is ${JSON.stringify(entry.shell)}, expected "bash"`);
|
||||
process.exit(1);
|
||||
}
|
||||
if (!/run-hook\.cmd" session-start$/.test(entry.command)) {
|
||||
console.error(`unexpected SessionStart command shape: ${entry.command}`);
|
||||
process.exit(1);
|
||||
}
|
||||
' "$REPO_ROOT/hooks/hooks.json"; then
|
||||
pass "hooks.json registers SessionStart with shell:bash dispatch"
|
||||
else
|
||||
fail "hooks.json registers SessionStart with shell:bash dispatch"
|
||||
fi
|
||||
|
||||
claude_home="$(make_home claude-code)"
|
||||
assert_command_output \
|
||||
"Claude Code emits nested SessionStart additionalContext" \
|
||||
|
||||
Reference in New Issue
Block a user