Clarify or fire Stop hook when a turn is interrupted with Esc
What variant of Codex are you using?
CLI / TUI
Which version are you using?
codex-cli 0.130.0
What operating system are you using?
Linux Fedora 42, kernel 6.17.8-200.fc42.x86_64
Bug description
When an active Codex turn is interrupted or aborted mid-run, for example by pressing Esc, the Stop hook does not appear to run.
I am not sure whether this is intended behavior. The hooks documentation lists Stop as a supported hook event, and the app-server interrupt docs describe interrupted turns as completing with status interrupted. From an integration point of view, it is unclear whether an interrupted turn should be considered a stop/completion for hook purposes.
This matters for integrations that use hooks as the source of truth for external session state. In https://github.com/njbrake/agent-of-empires/issues/1126 , for example, a Codex Stop hook writes the session status back to idle. If UserPromptSubmit, PreToolUse, or PostToolUse previously marked the session as running, then pressing Esc can leave the external status stuck on Running even though Codex is no longer doing work.
Expected behavior
One of these would be reasonable:
Stopfires when a running turn is interrupted withEsc.- Codex documents that
Stoponly fires for normally completed turns, not interrupted turns. - Codex exposes a separate hook/event for interrupted or cancelled turns, so integrations can reliably clear running state.
Actual behavior
After interrupting an active turn with Esc, the configured Stop hook does not appear to run. External hook-driven state can remain stuck in a running state until another hook event fires or the session is restarted.
Steps to reproduce
- Configure a simple
Stophook in~/.codex/hooks.jsonthat appends a timestamp to a log file. - Start Codex CLI/TUI.
- Submit a prompt that runs long enough to interrupt.
- Press
Escwhile Codex is actively working. - Check the hook log file.
Expected: the Stop hook either runs, or there is a documented separate interrupt/cancel event.
Actual: no Stop hook entry appears to be written for the interrupted turn.
Impact
This makes hook-based lifecycle integrations hard to keep correct. A tool can observe that a turn started, but cannot reliably observe that it ended if the user interrupts it.
If skipping Stop on interrupt is intentional, documenting that explicitly would help. If not intentional, firing Stop or adding an interrupt-specific hook would make the lifecycle contract much clearer.
Related context
Possibly related but not the same failure mode:
- #21160 reports hooks not firing after rate-limit stops or live hook config edits.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗