Windows: all Claude-marketplace plugin hooks fail — hook bash resolves to the WSL shim; async hook protocol unsupported; failures report only 'Failed' with no diagnostics

Open 💬 2 comments Opened Aug 13, 2026 by scarsai-cr0w-agent
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

Environment

  • Codex CLI 0.144.1, 0.146.0, 0.147.0 (identical behavior on all three), npm install
  • Windows 11 Pro 10.0.26200
  • Plugins from the claude-plugins-official marketplace: security-guidance 2.0.7, superpowers 6.3.0, ralph-loop 1.0.0
  • WSL installed (Ubuntu default distro), Git for Windows installed

Summary

On Windows, every hook declared by Claude-marketplace plugins reports Failed on every fresh codex exec run — all four phases (SessionStart, UserPromptSubmit, PostToolUse, Stop). The root cause is that Codex resolves the hook interpreter bash via PATH. On a default Windows setup, PATH bash is the WindowsApps WSL shim (%LOCALAPPDATA%\Microsoft\WindowsApps\bash.exe), and WSL bash cannot execute Windows-style script paths:

$ bash "C:\Users\<user>\.codex\plugins\cache\claude-plugins-official\security-guidance\2.0.7\hooks\sg-python.sh"
/bin/bash: C:UsersAJCam.codexpluginscacheclaude-plugins-officialsecurity-guidance2.0.7hookssg-python.sh: No such file or directory
(exit 127)

Since effectively all Claude-marketplace plugin hooks are bash <script> commands, every hook fails out of the box on Windows. Claude Code runs these same hooks successfully on the same machine because it resolves bash to Git Bash rather than PATH-first.

Workaround / proof: prepending C:\Program Files\Git\bin to PATH (so bash = Git Bash) immediately fixes most phases with unmodified plugin files: UserPromptSubmit Completed, all PostToolUse Completed, security-guidance Stop Completed.

Requests

1. Resolve hook bash like Claude Code does on Windows

PATH-first resolution lands on the WSL shim and breaks every Claude-marketplace hook. Suggested: prefer Git Bash (git --exec-path discovery or the standard install locations) for bash hook commands on Windows, falling back to PATH.

2. Support (or gracefully degrade) the async hook protocol

security-guidance's SessionStart hook (ensure_agent_sdk.py) replies with Claude's async hook protocol:

{"async": true, "asyncTimeout": 180000}

and exits 0. Codex marks the phase Failed. Expected: either honor the async contract or treat a well-formed async reply as success.

3. Hook failures surface as the bare word Failed with no diagnostics

  • The transcript prints only hook: <Phase> Failed.
  • RUST_LOG=trace surfaces exec-policy and websocket telemetry but no hook error reason.
  • The app log DB records hook/started / hook/completed events with no failure detail.
  • Additionally, a hook whose hooks.json hash is not in the trusted set is silently skipped with no output at all, which is indistinguishable from "did not fire" and cost us several rounds of misdiagnosis (an edited hook file gets a new hash and simply vanishes from the run).

Expected: print or log the exit code / stderr / spawn error of a failed hook, and indicate when a hook was skipped as untrusted.

4. Remaining divergence (unresolved)

ralph-loop's Stop hook (stop-hook.sh) exits 0 when run by hand under Git Bash with CLAUDE_PLUGIN_ROOT set and JSON on stdin, yet still reports Failed inside Codex's hook runtime even after the bash fix. Without failure diagnostics (point 3) we could not determine why; likely stdin/env shape divergence from Claude's hook contract.

Reproduction

  1. Windows machine with WSL installed (so PATH bash = WSL shim) and any claude-plugins-official plugin with hooks installed and trusted (e.g. security-guidance).
  2. codex exec any prompt in any workspace.
  3. Observe hook: SessionStart Failed, hook: UserPromptSubmit Failed, hook: PostToolUse Failed (per tool call), hook: Stop Failed.
  4. Prepend Git Bash to PATH and re-run: UserPromptSubmit / PostToolUse / security-guidance Stop complete; SessionStart still fails on the async reply (point 2).

View original on GitHub ↗

2 Comments

github-actions[bot] contributor · 15 days ago

Potential duplicates detected. Please review them and close your issue if it is a duplicate.

  • #37362

Powered by Codex Action

jdcodes1 · 9 days ago

Confirmed on main @ 1f41cc5d92: hook commands on Windows run through cmd.exe /C "<command_line>" with no interpreter special-casing — build_command / default_shell_command in codex-rs/hooks/src/engine/command_runner.rs#L372-L420. So bash <script> resolves via cmd's PATH search, which on stock Windows lands on the WindowsApps WSL shim, and WSL bash mangles the Windows path exactly as your exit-127 capture shows. There is no Git-Bash discovery anywhere in the hooks crate.

Your request 1 is the right fix and cheap: when a hook command's program is bash on Windows, prefer Git Bash (via git --exec-path-relative discovery or the standard Git\bin\bash.exe locations), falling back to PATH — mirroring what Claude Code does on the same machine, per your test. For request 3 (diagnostics): the runner already captures exit_code/stdout/stderr in HandlerRunResult (#L360-L369); surfacing the exit code and a stderr tail wherever "Failed" is rendered would have made this self-diagnosing instead of requiring your shim forensics.