Hooks: expose one quiescence-aware terminal event per tool call
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 125k
- Forks
- 19.4k
- PR merge metrics
- PR metrics pending
Description
What variant of Codex are you using?
CLI (codex-cli 0.153.3; unchanged in 0.153.4)
What feature would you like to see?
Codex CLI 0.153.3 (unchanged in 0.153.4, released 2026-09-04) documents PreToolUse and PostToolUse hooks that carry a tool_use_id, but user hooks have no exact terminal notification for every tool call.
Missing public cases include: a call blocked by a PreToolUse hook (no further hook fires for that tool_use_id), cancellation without a PostToolUse payload, and interruption while a unified-exec process remains alive (no PostToolUse until a later write_stdin observes termination — a detached process may never get one). At Stop, a blocked call and a live detached command are indistinguishable to a hook that audits filesystem effects per tool_use_id.
Core already contains useful primitives (as read in the main branch around early September 2026): ToolFinishInput { call_id, outcome } with Completed, Blocked, Failed { handler_executed } and Aborted; and an asynchronous ExecCommandEnd { call_id, turn_id, process_id, ... } emitted when a host-managed process exits. ToolFinish alone is not a quiescence guarantee: dispatch may finish while a detached process remains alive.
Related issues (this request is narrower and complementary): #24907 and #34289 ask for a failure branch or failure fields on PostToolUse; #32505 asks for structured terminal status on the terminal event of nested code-mode calls; #21753 tracks parity with Claude Code hooks. None of them covers a call blocked by PreToolUse, a cancellation that produces no PostToolUse, or a detached unified-exec process still alive after dispatch — the three cases where an exactly-once terminal event with an explicit quiescence claim is needed.
Request: expose one exactly-once public hook event per tool_use_id, for example:
{
"hook_event_name": "ToolTerminal",
"session_id": "...",
"turn_id": "...",
"tool_use_id": "...",
"outcome": "blocked|completed|failed|cancelled",
"executed": true,
"writers_quiesced": true,
"quiescence_scope": "host_managed"
}
Required semantics: calls blocked before execution terminate with executed: false; detached commands terminate only after the managed process exits and output is drained; cancellation/interruption never claim quiescence while a managed process remains alive; the event is emitted exactly once per tool_use_id; unmanaged descendants are an explicit exclusion (quiescence_scope).
Suggested regression matrix: blocked PreToolUse; cancellation before/after handler start; detached completion without write_stdin; interruption while the process remains alive, followed by managed-process termination.
Motivation: a post-condition hook that snapshots a watched tree before each tool call and compares after it needs to know when a given call can no longer write. Claude Code's PostToolBatch (lists every tool_use_id of the batch, including blocked ones) and PostToolUseFailure close this gap on the other engine; a PostToolUse made universal with the fields above would be equivalent.
Additional information
No response
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by tracing the mentioned ToolFinishInput and ExecCommandEnd primitives through PreToolUse, PostToolUse, Stop, and unified-exec handling. Use the suggested regression matrix to check blocked, cancelled, detached, and interrupted calls; done means one terminal event per tool_use_id with accurate outcome, execution, and quiescence fields.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- backend-api-design, cli
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100