If you really want stop hooks in Codex, here's something I tried

Resolved 💬 3 comments Opened Mar 10, 2026 by DMontgomery40 Closed Mar 10, 2026

I ran into a pretty ugly automation-integrity problem in a real Codex setup and ended up hardening it locally.

Public writeup:
https://gist.github.com/DMontgomery40/f11535bb6e458d8a25018e996504f10e

Short version:

  • the Codex path I was using had notify, but not a true blocking stop-hook equivalent
  • that made it too easy for automated loops to present unsupported or fake-green conclusions as if they were verified
  • I patched a local Codex fork to add a real blocking stop_hook config that runs synchronously before turn completion, receives the full hook payload JSON on stdin, and aborts completion on nonzero exit
  • I added a core integration test proving the stop hook aborts turn completion and receives the full payload
  • because the currently shipped npm-installed codex binary would reject an unknown global config key, I had to inject the hook through codex exec -c 'stop_hook=[...]' instead of safely dropping it straight into ~/.codex/config.toml
  • I then moved the dangerous worker loops off the desktop automation runner and onto cron + codex exec, while preserving originator identity with export CODEX_INTERNAL_ORIGINATOR_OVERRIDE="Codex Desktop"

The broader point is the one I want to put on the record:

If OpenAI accepted good external PRs instead of rejecting uninvited PRs outright, Codex users as a whole could plausibly be safer from reward hacking and fake-green automation behavior like this. This kind of stop-hook / automation-integrity work is exactly the sort of thing that should have a real path upstream when it is concrete, test-backed, and broadly useful.

Requests:

  1. Add a real supported blocking stop-hook path to Codex, not just fire-and-forget notify behavior.
  2. Make sure the hook can receive the full turn payload and deterministically abort completion.
  3. Consider exposing an officially supported contribution path for concrete safety-improving changes like this, even if it is curated/reviewed instead of fully open-ended.

I have not opened an upstream PR. The gist above documents the local patch, the operational mess around it, the workarounds, and the exact failure modes that motivated it.

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗