Summary
Codex emits PreToolUse for shell tools started via exec_command, but in some cases it never emits the matching PostToolUse.
This appears to happen specifically when the command does not complete on the initial exec_command call and instead completes later through the long-running session / polling path.
Expected behavior
Every tool call that emits PreToolUse should emit exactly one matching PostToolUse when the tool finishes, regardless of whether it:
- completes immediately on the initial tool call, or
- completes later through the session continuation / polling flow
Actual behavior
PostToolUse is emitted for commands that complete immediately, but is missing for commands that:
- start via
exec_command
- return a running session
- later complete through the session / polling path
Evidence
In one reproduced case, a single turn produced:
7 PreToolUse
2 PostToolUse
The transcript for that same turn showed that the missing tool calls did in fact complete successfully later, including exit codes and output, but no PostToolUse event was emitted for them.
The missing cases were long-running shell commands that first returned a session and later completed through polling. The two cases that did get PostToolUse were commands that completed directly on the initial exec_command path.
Impact
Consumers that rely on hooks to model tool lifecycle get incomplete traces:
- tools appear to start but never finish
- duration and status are missing
- downstream systems cannot reliably pair pre/post tool events
Root-cause hypothesis
The hook integration appears to emit PostToolUse only for the immediate completion path, but not for tool completion that happens later through the exec session continuation / polling path.
Suggested fix
Emit PostToolUse when the tool actually completes, regardless of whether completion happens:
- during the initial
exec_command, or
- during later session polling / continuation
The emitted event should use the original tool call ID so consumers can pair it with the earlier PreToolUse.
Summary
Codex emits
PreToolUsefor shell tools started viaexec_command, but in some cases it never emits the matchingPostToolUse.This appears to happen specifically when the command does not complete on the initial
exec_commandcall and instead completes later through the long-running session / polling path.Expected behavior
Every tool call that emits
PreToolUseshould emit exactly one matchingPostToolUsewhen the tool finishes, regardless of whether it:Actual behavior
PostToolUseis emitted for commands that complete immediately, but is missing for commands that:exec_commandEvidence
In one reproduced case, a single turn produced:
7PreToolUse2PostToolUseThe transcript for that same turn showed that the missing tool calls did in fact complete successfully later, including exit codes and output, but no
PostToolUseevent was emitted for them.The missing cases were long-running shell commands that first returned a session and later completed through polling. The two cases that did get
PostToolUsewere commands that completed directly on the initialexec_commandpath.Impact
Consumers that rely on hooks to model tool lifecycle get incomplete traces:
Root-cause hypothesis
The hook integration appears to emit
PostToolUseonly for the immediate completion path, but not for tool completion that happens later through the exec session continuation / polling path.Suggested fix
Emit
PostToolUsewhen the tool actually completes, regardless of whether completion happens:exec_command, orThe emitted event should use the original tool call ID so consumers can pair it with the earlier
PreToolUse.