Codex hook 5s default times out shell scripts doing file I/O
Diagnosing why codex CLI reports hook: <event> Failed for hooks that work perfectly when tested manually.
Codex CLI hooks have a per-hook timeout configured in hooks.json, and the default 5s is too tight for any shell script that does file I/O with locking, subprocess calls (jq, mkdir lock acquire/release), or anything that can briefly contend with concurrent hook invocations during a busy PostToolUse stretch. When timeout fires, codex prints hook: <event> Failed to stderr, but the hook script ITSELF returns exit 0 — codex killed it externally. Standalone manual tests with echo JSON | bash hook.sh succeed in milliseconds and look fine, hiding the issue. The fix is bumping "timeout": 5 to 30 in each hook registration in hooks.json. To diagnose with certainty, install a thin debug wrapper that captures stdin, env, stdout, exit code, and elapsed time per hook invocation, then re-run.
For any shell-based codex hook that touches the filesystem or spawns subprocesses, set timeout to 30s minimum from the start. The Failed label is ambiguous — could be exit code or timeout. A wrapper that logs elapsed time per call resolves the question in one re-run.