Grok runs a hook's `command` and Codex runs `commandWindows` in the session
shell, which is PowerShell by default on Windows. Impeccable wrote the POSIX
guard for Grok and cmd.exe `if exist (...)` syntax for Codex, and `hooks on`
wrote a bare quoted path; PowerShell rejects all three, so the hook never ran.
Every writer now emits `cmd /c if exist "<path>\impeccable.cmd"
"<path>\impeccable.cmd" <verb>`: one Rust builder shared by install and
`hooks on`, and its twin in the build's hooks.js. Unix output is unchanged
and Grok gets no `commandWindows` key. `.codex/hooks.json` is regenerated
because hook-build.test.mjs deep-equals it against the builder.
A Windows-only test spawns the string the way each harness does (PowerShell
5.1 and 7, Git Bash, cmd.exe). It has never executed; the Windows CI job is
its first run.
Prepared with AI assistance (Claude Code).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Grok runs a hook's
commandand Codex runscommandWindowsin the session shell, which is PowerShell by default on Windows. We wrote the POSIX guard for Grok, cmd.exeif exist (...)for Codex, and a bare"<path>" hookfromimpeccable hooks on. PowerShell rejects all three, so the hook never ran. Every writer now emitscmd /c if exist "<path>\impeccable.cmd" "<path>\impeccable.cmd" hook, from one Rust builder shared by install andhooks onplus its twin inhooks.js. Unix output and Gemini's output are unchanged, and Grok gets nocommandWindowskey.Fixes #859
Fixes #848
Nothing here ran on Windows locally. The new Windows-only test
windows_form_runs_the_shim_in_each_harness_shellspawns the string the way each harness does (PowerShell 5.1 and 7 with-Command, Git Bash with MSYS path conversion off, cmd.exe behind Codex's raw/Cfallback) against a stub shim that saves its stdin and exits 3. It passed onrust-windowsat e0dd6f9, for a relative path and for an absolute path with a space: in each of those four shells the shim ran, received the piped event, and a missing shim exited 0.Known limits:
GROK_SHELL=cmdstill does not run the hook, which differs from the expected behavior in [Bug] Grok Build on Windows ParserErrors the POSIX hook command #859. Grok passes the line as a plain argument, so the quotes reach cmd.exe as\"and the guard finds nothing and exits 0. The same CI run confirmed this, and the test pins it as a gap.-Commandreports any native failure as exit 1, so the launcher's exact code survives only under cmd.exe and Git Bash.$, a backtick, or%VAR%is not handled.@0xenzyme @saulwadeleon if you have a moment: CI covers the shells, but a run through the harness itself (not the string typed by hand, the quoting differs) would settle it. Useful cases are pwsh 7, Windows PowerShell 5.1, an install path with a space, a missing launcher, and whether the hook actually received the event (a finding shown, or the hook audit log written), not only exit 0.
.codex/hooks.jsonis staged becausetests/hook-build.test.mjsdeep-equals it against the builder (same as 14d2641). Existing installs pick up the new string fromnpx impeccable updateonce an engine release carries this.Validation on macOS:
cargo test --workspace --no-fail-fast(818 passed; the one failure,impeccable-comp-verbsartifact_cleanup_failure_blocks_the_gate, also fails on this machine on unmodified main),bun run build, andbun run testagainst this branch's release binary.Prepared with AI assistance.
🤖 Generated with Claude Code