Skip to content

Fix: Windows hook commands PowerShell could not parse (#859, #848) - #915

Open
abdulwahabone wants to merge 1 commit into
mainfrom
fix/859-windows-hook-shell-neutral
Open

abdulwahabone wants to merge 1 commit into
mainfrom
fix/859-windows-hook-shell-neutral

Conversation

@abdulwahabone

@abdulwahabone abdulwahabone commented Oct 2, 2026 •

Copy link
Copy Markdown
Collaborator

Grok runs a hook's command and Codex runs commandWindows in the session shell, which is PowerShell by default on Windows. We wrote the POSIX guard for Grok, cmd.exe if exist (...) for Codex, and a bare "<path>" hook from impeccable hooks on. PowerShell rejects all three, so the hook never ran. Every writer now emits cmd /c if exist "<path>\impeccable.cmd" "<path>\impeccable.cmd" hook, from one Rust builder shared by install and hooks on plus its twin in hooks.js. Unix output and Gemini's output are unchanged, and Grok gets no commandWindows key.

Fixes #859
Fixes #848

Nothing here ran on Windows locally. The new Windows-only test windows_form_runs_the_shim_in_each_harness_shell spawns 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 /C fallback) against a stub shim that saves its stdin and exits 3. It passed on rust-windows at 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=cmd still 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.
  • PowerShell's -Command reports any native failure as exit 1, so the launcher's exact code survives only under cmd.exe and Git Bash.
  • An absolute install path containing $, 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.json is staged because tests/hook-build.test.mjs deep-equals it against the builder (same as 14d2641). Existing installs pick up the new string from npx impeccable update once an engine release carries this.

Validation on macOS: cargo test --workspace --no-fail-fast (818 passed; the one failure, impeccable-comp-verbs artifact_cleanup_failure_blocks_the_gate, also fails on this machine on unmodified main), bun run build, and bun run test against this branch's release binary.

Prepared with AI assistance.

🤖 Generated with Claude Code

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>
@abdulwahabone
abdulwahabone requested a review from pbakaus as a code owner October 2, 2026 05:39
@greptile-apps

greptile-apps Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 5/5

[Medium risk] Fixes Windows hook command parsing in PowerShell.

The PR appears safe to merge with its documented Windows shell and path limitations.

Summary

This PR changes Windows Codex and Grok hook commands to run a guarded .cmd launcher through cmd /c.

  • Shares the Rust command builder between installation and hooks on, with a matching JavaScript builder.
  • Adds Windows shell tests for event delivery, exit behavior, and missing launchers.
Diagram
%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A[JavaScript build or Rust install] --> B[Windows hook command]
  C[hooks on] --> B
  B --> D[Session shell]
  D --> E[cmd /c if exist]
  E --> F[impeccable.cmd hook]
Loading

Reviews (3) · Last reviewed commit: "Fix: Windows hook commands PowerShell co..."

Comment thread crates/skills/src/hook_manifest.rs
Comment thread crates/context/src/hook_markers.rs
@abdulwahabone

Copy link
Copy Markdown
Collaborator Author

@greptileai both threads are answered and resolved: the cross-OS Grok manifest is the single-command constraint (update on the other OS rewrites it), and GROK_SHELL=cmd is the documented limit that rust-windows confirmed. Please re-review.

Comment thread .codex/hooks.json
Comment thread crates/context/src/hook_markers.rs
@abdulwahabone

Copy link
Copy Markdown
Collaborator Author

@greptileai both new threads are answered and resolved: .codex/hooks.json is deep-equaled against the builder by tests/hook-build.test.mjs, and the absolute-path expansion case is a documented limit with no cross-shell escape. Please re-review.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant