Repository navigation
Full Claude Code Hook Parity (29+) #21753
Description
Activity
Indexed hook tickets (canonical
hookslabel, state as of May 8, 2026):- [CLOSED/COMPLETED] Event Hooks #2109 - Event Hooks
Event Hooks #2109 - [OPEN] Notify not getting triggered #8929 - Notify not getting triggered
Notify not getting triggered #8929 - [OPEN] Please give us a hook for custom compaction #11912 - Please give us a hook for custom compaction
Please give us a hook for custom compaction #11912 - [CLOSED/NOT_PLANNED] Better notification for multi-agent #12341 - Better notification for multi-agent
Better notification for multi-agent #12341 - [CLOSED/COMPLETED] Add PreToolUse and PostToolUse hook events for code quality enforcement #14754 - Add PreToolUse and PostToolUse hook events for code quality enforcement
Add PreToolUse and PostToolUse hook events for code quality enforcement #14754 - [CLOSED/NOT_PLANNED] Add a native pre-turn dynamic context hook for time-sensitive metadata #14814 - Add a native pre-turn dynamic context hook for time-sensitive metadata
Add a native pre-turn dynamic context hook for time-sensitive metadata #14814 - [CLOSED/DUPLICATE] Proposal: add PreToolUse/PostToolUse lifecycle hooks to Codex hooks engine #14882 - Proposal: add PreToolUse/PostToolUse lifecycle hooks to Codex hooks engine
Proposal: add PreToolUse/PostToolUse lifecycle hooks to Codex hooks engine #14882 - [CLOSED/COMPLETED] UserPromptSubmit and SessionStart hooks fire simultaneously on first prompt #15266 - UserPromptSubmit and SessionStart hooks fire simultaneously on first prompt
UserPromptSubmit and SessionStart hooks fire simultaneously on first prompt #15266 - [CLOSED/DUPLICATE] SessionStart not firing on session start instead it fires on first user prompt submission #15269 - SessionStart not firing on session start instead it fires on first user prompt submission
SessionStart not firing on session start instead it fires on first user prompt submission #15269 - [CLOSED/COMPLETED] Add blocking PermissionRequest hook for external approval UIs #15311 - Add blocking PermissionRequest hook for external approval UIs
Add blocking PermissionRequest hook for external approval UIs #15311 - [CLOSED/NOT_PLANNED] Expose CollabAgentSpawn{Begin,End} as hook events #15486 - Expose CollabAgentSpawn{Begin,End} as hook events
Expose CollabAgentSpawn{Begin,End} as hook events #15486 - [CLOSED/DUPLICATE] Expose AfterToolUse in hooks.json and support codex_hooks on Windows #15490 - Expose AfterToolUse in hooks.json and support codex_hooks on Windows
Expose AfterToolUse in hooks.json and support codex_hooks on Windows #15490 - [CLOSED/COMPLETED] Support suppressing hook status messages in TUI (suppressOutput is a no-op) #15497 - Support suppressing hook status messages in TUI (suppressOutput is a no-op)
Support suppressing hook status messages in TUI (suppressOutput is a no-op) #15497 - [CLOSED/DUPLICATE] Add pre_compact and post_compact hooks for context compaction #16098 - Add pre_compact and post_compact hooks for context compaction
Add pre_compact and post_compact hooks for context compaction #16098 - [OPEN] Hooks: distinguish subagent events from main agent #16226 - Hooks: distinguish subagent events from main agent
Hooks: distinguish subagent events from main agent #16226 - [CLOSED/COMPLETED] Hooks: PostToolUse is missing for tools that complete via exec session / polling path #16246 - Hooks: PostToolUse is missing for tools that complete via exec session / polling path
Hooks: PostToolUse is missing for tools that complete via exec session / polling path #16246 - [CLOSED/COMPLETED] hooks: add permission request event for parity with claude code's auto-approve flow #16301 - hooks: add permission request event for parity with claude code's auto-approve flow
hooks: add permission request event for parity with claude code's auto-approve flow #16301 - [OPEN] Hooks should support stable bundle/plugin context for reusable hook scripts #16466 - Hooks should support stable bundle/plugin context for reusable hook scripts
Hooks should support stable bundle/plugin context for reusable hook scripts #16466 - [OPEN] Feature request: official machine-readable event surface for approvals and turn lifecycle #16484 - Feature request: official machine-readable event surface for approvals and turn lifecycle
Feature request: official machine-readable event surface for approvals and turn lifecycle #16484 - [OPEN] Render
UserPromptSubmit.additionalContextas multiline hook context in the TUI #16486 - RenderUserPromptSubmit.additionalContextas multiline hook context in the TUI
RenderUserPromptSubmit.additionalContextas multiline hook context in the TUI #16486 - [CLOSED/COMPLETED] ApplyPatchHandler doesn't emit PreToolUse/PostToolUse hook event. Hooks only fire for Bash tool. #16732 - ApplyPatchHandler doesn't emit PreToolUse/PostToolUse hook event. Hooks only fire for Bash tool.
ApplyPatchHandler doesn't emit PreToolUse/PostToolUse hook event. Hooks only fire for Bash tool. #16732 - [CLOSED/DUPLICATE] Hooks log output is very noisy #16743 - Hooks log output is very noisy
Hooks log output is very noisy #16743 - [OPEN] Codex CLI renders hook additionalContext as visible developer message #16933 - Codex CLI renders hook additionalContext as visible developer message
Codex CLI renders hook additionalContext as visible developer message #16933 - [CLOSED/DUPLICATE] tui: suppress hook notifications when there is nothing to display #16993 - tui: suppress hook notifications when there is nothing to display
tui: suppress hook notifications when there is nothing to display #16993 - [CLOSED/DUPLICATE] Add hook_report_level config to suppress routine hook chatter #17105 - Add hook_report_level config to suppress routine hook chatter
Add hook_report_level config to suppress routine hook chatter #17105 - [OPEN] Add PreSkillUse and PostSkillUse hooks for explicit and implicit skill usage #17132 - Add PreSkillUse and PostSkillUse hooks for explicit and implicit skill usage
Add PreSkillUse and PostSkillUse hooks for explicit and implicit skill usage #17132 - [OPEN] Pre and PostCompact hooks #17148 - Pre and PostCompact hooks
Pre and PostCompact hooks #17148 - [CLOSED/DUPLICATE] Hook execution audit logs clutter session terminal output #17321 - Hook execution audit logs clutter session terminal output
Hook execution audit logs clutter session terminal output #17321 - [CLOSED/COMPLETED] Plugin manifests define
hooks, but plugin hooks are not loaded into the Codex hooks runtime #17331 - Plugin manifests definehooks, but plugin hooks are not loaded into the Codex hooks runtime
Plugin manifests definehooks, but plugin hooks are not loaded into the Codex hooks runtime #17331 - [OPEN] Feature Request: Add TaskCompleted Hook Event #17333 - Feature Request: Add TaskCompleted Hook Event
Feature Request: Add TaskCompleted Hook Event #17333 - [OPEN] Feature request: expose native composer suggestion hooks/API for local plugins #17341 - Feature request: expose native composer suggestion hooks/API for local plugins
Feature request: expose native composer suggestion hooks/API for local plugins #17341 - [CLOSED/DUPLICATE] Add SessionEnd hook #17421 - Add SessionEnd hook
Add SessionEnd hook #17421 - [OPEN] Force hook usage approval with config #17422 - Force hook usage approval with config
Force hook usage approval with config #17422 - [CLOSED/COMPLETED] Enable hooks on Windows #17478 - Enable hooks on Windows
Enable hooks on Windows #17478 - [CLOSED/DUPLICATE] Codex Desktop shows background hook transcript noise, while the TUI does not #17479 - Codex Desktop shows background hook transcript noise, while the TUI does not
Codex Desktop shows background hook transcript noise, while the TUI does not #17479 - [OPEN] Greeting message hook #17518 - Greeting message hook
Greeting message hook #17518 - [OPEN] codex_hooks do not fire in interactive sessions when configured via repo-local .codex/config.toml #17532 - codex_hooks do not fire in interactive sessions when configured via repo-local .codex/config.toml
codex_hooks do not fire in interactive sessions when configured via repo-local .codex/config.toml #17532 - [OPEN] Hot-reload hook configuration during a live session #17636 - Hot-reload hook configuration during a live session
Hot-reload hook configuration during a live session #17636 - [CLOSED/DUPLICATE] File write operations do not fire PreToolUse/PostToolUse hooks #17794 - File write operations do not fire PreToolUse/PostToolUse hooks
File write operations do not fire PreToolUse/PostToolUse hooks #17794 - [CLOSED/COMPLETED] Add hook support for IDE extension and Codex app #17930 - Add hook support for IDE extension and Codex app
Add hook support for IDE extension and Codex app #17930 - [OPEN] MCP hook #18051 - MCP hook
MCP hook #18051 - [OPEN] 【BUG】Codex CLI hooks fail silently on Linux/Windows when editing large files #18067 - 【BUG】Codex CLI hooks fail silently on Linux/Windows when editing large files
【BUG】Codex CLI hooks fail silently on Linux/Windows when editing large files #18067 - [CLOSED/COMPLETED] Hook support not working in IDE extension and Codex app #18090 - Hook support not working in IDE extension and Codex app
Hook support not working in IDE extension and Codex app #18090 - [CLOSED/COMPLETED] Support "Edit|Write" matcher in PostToolUse and PreToolUse #18295 - Support "Edit|Write" matcher in PostToolUse and PreToolUse
Support "Edit|Write" matcher in PostToolUse and PreToolUse #18295 - [OPEN] [Feature request] Extend PreToolUse hooks beyond Bash + implement updatedInput rewrite #18491 - [Feature request] Extend PreToolUse hooks beyond Bash + implement updatedInput rewrite
[Feature request] Extend PreToolUse hooks beyond Bash + implement updatedInput rewrite #18491 - [OPEN] Ambients Suggestions feature uses
UserPromptSubmithook withoutStophook afterwards #18541 - Ambients Suggestions feature usesUserPromptSubmithook withoutStophook afterwards
Ambients Suggestions feature usesUserPromptSubmithook withoutStophook afterwards #18541 - [CLOSED/NOT_PLANNED] Codex exec does not fire Stop / SessionStop / PostToolUse hooks (only UserPromptSubmit fires) #18607 - Codex exec does not fire Stop / SessionStop / PostToolUse hooks (only UserPromptSubmit fires)
Codex exec does not fire Stop / SessionStop / PostToolUse hooks (only UserPromptSubmit fires) #18607 - [OPEN] Stop hook invalid JSON error is too opaque for unsupported fields #18887 - Stop hook invalid JSON error is too opaque for unsupported fields
Stop hook invalid JSON error is too opaque for unsupported fields #18887 - [CLOSED/COMPLETED] Add a post-compaction hook for deterministic memory reinjection #19061 - Add a post-compaction hook for deterministic memory reinjection
Add a post-compaction hook for deterministic memory reinjection #19061 - [CLOSED/COMPLETED] codex-cli 0.124.0 fails to start when hook config is present and codex_hooks is enabled #19199 - codex-cli 0.124.0 fails to start when hook config is present and codex_hooks is enabled
codex-cli 0.124.0 fails to start when hook config is present and codex_hooks is enabled #19199 - [OPEN] Expose TUI question prompts ("Implement this plan?", reasoning scope, etc.) to the external hook system #19328 - Expose TUI question prompts ("Implement this plan?", reasoning scope, etc.) to the external hook system
Expose TUI question prompts ("Implement this plan?", reasoning scope, etc.) to the external hook system #19328 - [CLOSED/DUPLICATE] Error starting chat - invalid configuration #19364 - Error starting chat - invalid configuration
Error starting chat - invalid configuration #19364 - [OPEN] Allow Codex hooks to run silently without rendering completed hook entries #19383 - Allow Codex hooks to run silently without rendering completed hook entries
Allow Codex hooks to run silently without rendering completed hook entries #19383 - [OPEN] Support additionalContext in PreToolUse hooks or clarify Claude-style hook parity #19385 - Support additionalContext in PreToolUse hooks or clarify Claude-style hook parity
Support additionalContext in PreToolUse hooks or clarify Claude-style hook parity #19385 - [OPEN] Docs: SessionStart source field omits clear value #19666 - Docs: SessionStart source field omits clear value
Docs: SessionStart source field omits clear value #19666 - [CLOSED/NOT_PLANNED] Hooks do not fire in interactive sessions (v0.125.0) #19780 - Hooks do not fire in interactive sessions (v0.125.0)
Hooks do not fire in interactive sessions (v0.125.0) #19780 - [OPEN] Expose plan-mode-prompt and approval-requested through top-level notify #19921 - Expose plan-mode-prompt and approval-requested through top-level notify
Expose plan-mode-prompt and approval-requested through top-level notify #19921 - [OPEN] Inconsistent PreToolUse hook coverage across tool handlers (most tools never emit hook events) #20204 - Inconsistent PreToolUse hook coverage across tool handlers (most tools never emit hook events)
Inconsistent PreToolUse hook coverage across tool handlers (most tools never emit hook events) #20204 - [CLOSED/NOT_PLANNED] Add
SessionEndhook event for session/thread shutdown #20374 - AddSessionEndhook event for session/thread shutdown
AddSessionEndhook event for session/thread shutdown #20374 - [CLOSED/COMPLETED] Expose hook capabilities and a session-exit hook for integrations #20603 - Expose hook capabilities and a session-exit hook for integrations
Expose hook capabilities and a session-exit hook for integrations #20603 - [OPEN] Built-in image generation does not appear to emit PreToolUse hooks #20616 - Built-in image generation does not appear to emit PreToolUse hooks
Built-in image generation does not appear to emit PreToolUse hooks #20616 - [OPEN] Expose root/subagent metadata in hook payloads #20675 - Expose root/subagent metadata in hook payloads
Expose root/subagent metadata in hook payloads #20675 - [OPEN] Add an option to collapse hook-injected context in the CLI transcript #20766 - Add an option to collapse hook-injected context in the CLI transcript
Add an option to collapse hook-injected context in the CLI transcript #20766 - [OPEN] Blocking stop hook continuation can fail with invalid local message id #20783 - Blocking stop hook continuation can fail with invalid local message id
Blocking stop hook continuation can fail with invalid local message id #20783 - [CLOSED/COMPLETED] SessionStart hook on resume can report
hook timed out after 60seven when the hook exits 0 in ~4s #20862 - SessionStart hook on resume can reporthook timed out after 60seven when the hook exits 0 in ~4s
SessionStart hook on resume can reporthook timed out after 60seven when the hook exits 0 in ~4s #20862 - [OPEN] Native apply_patch lacks per-call workdir context for Hooks in multi-worktree repositories #20879 - Native apply_patch lacks per-call workdir context for Hooks in multi-worktree repositories
Native apply_patch lacks per-call workdir context for Hooks in multi-worktree repositories #20879 - [CLOSED/COMPLETED] Proposal: repo-scoped experience compiler hooks for memory, evals, briefs, and skills #20985 - Proposal: repo-scoped experience compiler hooks for memory, evals, briefs, and skills
Proposal: repo-scoped experience compiler hooks for memory, evals, briefs, and skills #20985 - [CLOSED/NOT_PLANNED] Deprecation notice links to malformed hooks docs URL (
/codex/hooks.returns 404) #21148 - Deprecation notice links to malformed hooks docs URL (/codex/hooks.returns 404)
Deprecation notice links to malformed hooks docs URL (/codex/hooks.returns 404) #21148 - [OPEN] Hooks stop firing after rate-limit stops or live hooks.json edits #21160 - Hooks stop firing after rate-limit stops or live hooks.json edits
Hooks stop firing after rate-limit stops or live hooks.json edits #21160 - [OPEN] Provide a supported way for local IDE/wrapper installers to request trust for installed hooks #21615 - Provide a supported way for local IDE/wrapper installers to request trust for installed hooks
Provide a supported way for local IDE/wrapper installers to request trust for installed hooks #21615 - [OPEN] Hooks no longer run after Codex Desktop update #21639 - Hooks no longer run after Codex Desktop update
Hooks no longer run after Codex Desktop update #21639 - [OPEN] Codex Rules: per-session cache for additionalContext (Claude Code InstructionsLoaded parity) #21675 - Codex Rules: per-session cache for additionalContext (Claude Code InstructionsLoaded parity)
Codex Rules: per-session cache for additionalContext (Claude Code InstructionsLoaded parity) #21675 - [OPEN] Allow hook additionalContext to be model-visible but hidden from TUI #21696 - Allow hook additionalContext to be model-visible but hidden from TUI
Allow hook additionalContext to be model-visible but hidden from TUI #21696 - [OPEN] Running hooks (Start, Stop, any other) hooks do not show up nor run in actual since today (8th May) #21723 - Running hooks (Start, Stop, any other) hooks do not show up nor run in actual since today (8th May)
Running hooks (Start, Stop, any other) hooks do not show up nor run in actual since today (8th May) #21723 - [OPEN] Enable Codex to promote recurring fixes into reusable approved local playbooks #21748 - Enable Codex to promote recurring fixes into reusable approved local playbooks
Enable Codex to promote recurring fixes into reusable approved local playbooks #21748
Reacted by Ignat Remizov- [CLOSED/COMPLETED] Event Hooks #2109 - Event Hooks
- addedenhancementNew feature or requestNew feature or requesthooksIssues related to event hooksIssues related to event hooks
on May 8, 2026 Potential duplicates detected. Please review them and close your issue if it is a duplicate.
- Inconsistent PreToolUse hook coverage across tool handlers (most tools never emit hook events) #20204
- Codex Rules: per-session cache for additionalContext (Claude Code InstructionsLoaded parity) #21675
- Expose root/subagent metadata in hook payloads #20675
- Expose hook capabilities and a session-exit hook for integrations #20603
- Add
SessionEndhook event for session/thread shutdown #20374
Powered by Codex Action
Missing the SessionEnd hook atm.
- added a commit that references this issue
on May 12, 2026 - added a commit that references this issue
on May 12, 2026 SessionStart is now not correct imo, as it does not fire when we start a new session.
why would SessionStart not fire when the agent is ready to receive input (a valid use case we have and want this event for)? UserPromptSubmit is the event that gets triggered on you guessed it, the moment a user submits a prompt. So imo it's completely missing the goal when those timings are the same?
Claude Code does it correct, so why not honor the same?
Thanks for tracking full Claude Code hook parity here. I want to add a concrete integration use case from the audio-notification ecosystem.
Tools like PeonPing/OpenPeon consume agent lifecycle events and map them to sound-pack categories. OpenPeon has a small cross-tool event taxonomy (CESP v1):
session.start: coding session/workspace openstask.acknowledge: work was accepted and processing startedtask.complete: a unit of work finished successfullytask.error: work failedinput.required: the agent is blocked on user input or approvalresource.limit: rate/token/quota/context limit- optional:
user.spam,session.end,task.progress
Spec reference: https://github.com/PeonPing/openpeon/blob/main/spec/cesp-v1.md
The important missing user experience is immediate feedback when the user submits a prompt. Today, legacy
notifyintegrations can play a sound reliably at end-of-turn, but they cannot reliably distinguish the earlier lifecycle transitions that sound packs care about. For example,UserPromptSubmit/ turn-start should map totask.acknowledge, whilePermissionRequestmaps toinput.required,Stop/ successful turn completion maps totask.complete, and tool or turn failures map totask.error.A useful minimum for audio and accessibility tools would be:
Codex hook/event Suggested CESP mapping Why it matters SessionStartsession.startSignal a workspace/session is ready UserPromptSubmittask.acknowledgePlay a confirmation sound immediately after the user sends a prompt PermissionRequestinput.requiredAlert the user that Codex is blocked PostToolUsesuccesstask.progressor tool-specific progressIndicate long work is advancing explicit tool/turn failure task.errorDistinguish failures from normal completion Stopsuccessful turntask.completeEnd-of-turn completion sound session/thread close session.endCleanup/disconnect signal rate/context/quota events resource.limitNotify limits without scraping UI text The ask is not Peon-specific support. It is a stable, documented, machine-readable lifecycle hook surface that works consistently across Codex CLI, TUI/Desktop, IDE/app-server surfaces, and plugins where possible. If the shipped hook system already has
UserPromptSubmit,PermissionRequest,SessionStart, andStop, documenting their config shape, payload contract, trust flow, and cross-surface availability would unlock these integrations without requiring tool-specific one-offs.This would also let existing
notifyremain a simple compatibility path while richer integrations use lifecycle hooks directly.Keesan12's point above, that event identity is not the same as policy meaning, is the load-bearing one in this thread. Name-parity with Claude Code is necessary but not sufficient if the cross-runtime semantics differ. The
deferenforcement tier in world-model-mcp is concrete field evidence for this.I shipped
deferas a third PreToolUse decision (betweenallowanddeny) precisely because the binary deny/allow/ask space did not survive contact with headless agents. A constraint withseverity = warningandviolation_count >= 3is too soft for deny (the agent is doing real work and the warning was advisory the first two times) and too hard forask(no human is in the loop). The right answer is to pause the agent and surface the recurring violation, which is a fourth runtime semantic that "allow / deny / ask" cannot express. Codex's existingpermissionDecisionenum carries the parity name but not the policy meaning, so any wrapper that needs the fourth state has to invent it on top.Concretely for the runtime matrix, the contract gap Keesan12 named maps to fields that already deserve to be first-class on every hook payload:
Field Purpose blockingWhether the hook can halt the transition authorityAdvisory versus authoritative, distinguishes a soft warning from a hard policy terminal_forWhether a stop applies to the child, the root, or neither resume_capableWhether the runtime can recover after the hook runs A fifth field I would add from shipping world-model-mcp against Claude Code, Cursor, pi, and now Codex:
decision_provenance, listing where the decision came from (config file, AGENTS.md constraint, learned violation history, runtime user input). Without it, audit replay is guesswork because the samedenycan mean four different things depending on which layer asserted it.Two specific matrix observations from the v0.7.5 Codex adapter integration:
-
The
PostToolUseFailuregap (Missing) is the harder version of the contradiction-detection problem. Today, memory layers that watch for "the agent claimed X, then the next edit overwrote X" have to infer the failure from generic PostToolUse payloads plus subsequent state. A first-class failure event with a typedfailure_kindenum (validation_error, runtime_error, user_correction, model_correction) would let memory layers attribute corrections honestly. world-model-mcp currently flags thesynthesizedconfidence tier for any fact that was never explicitly corroborated, but the failure-attribution path is still inference-driven. -
The
InstructionsLoadedgap (Missing) blocks deterministic memory reinjection parity. Today, world-model-mcp's PostCompact hook can inject curated state asadditionalContext, but there is no signal back to the next hook that says "this turn's instructions were just hydrated from external memory, here is what was loaded." A hook that fires when instructions are loaded, with asource_of_truthfield naming the layer that supplied them, would let downstream hooks reconcile what the model now believes against the external memory source. This pairs with the per-item provenance discussion happening on [PROPOSAL] Expose compact/session lifecycle hooks for external memory layers anthropics/claude-code#47023.
Adapter (Codex): https://github.com/SaravananJaichandar/world-model-mcp/tree/main/adapters/codex
-
Focused repro:
UserPromptSubmitblock/warning reasons are not visible in Codex DesktopI hit a concrete
UserPromptSubmitvisibility gap while testing a Windows PowerShell hook payload lab.Environment
- Codex Desktop on Windows
- Bundled CLI observed locally:
codex-cli 0.131.0-alpha.9 - Managed hooks configured through
C:\ProgramData\OpenAI\Codex\requirements.toml - Hook handler: Windows PowerShell 5.1-compatible script
- Events registered:
UserPromptSubmit,PreToolUse,PostToolUse
Expected behavior
When a
UserPromptSubmithook blocks or stops a prompt, Codex Desktop should show the user-facing reason somewhere visible in the app, similar to howPreToolUseblock reasons surface as messages such asCommand blocked by PreToolUse hook: ....Likewise, when a
UserPromptSubmithook returns a warning/system message without blocking, the warning should be visible to the user if the docs describe it as asystemMessage/warning surface.Actual behavior
The prompt can be blocked, but Codex Desktop only shows a generic
Not Sentmarker. The hook-provided reason/message is not visible in the app.A non-blocking
systemMessagewas consumed internally, but was not shown visibly in Desktop.Repro matrix
All hook responses were written to stdout as raw UTF-8 bytes with no BOM, no newline, and no extra text unless noted otherwise.
- JSON block payload, exit 0:
{"decision":"block","reason":"ZENITY_BLOCK_TEST: simulated Codex hook block from policy lab","systemMessage":"ZENITY_BLOCK_TEST: simulated Codex hook block from policy lab"}Result: prompt blocked, Desktop showed only
Not Sent; reason/systemMessage was not visible.- JSON stop payload, exit 0:
{"continue":false,"stopReason":"ZENITY_BLOCK_TEST: simulated Codex hook block from policy lab","systemMessage":"ZENITY_BLOCK_TEST: simulated Codex hook block from policy lab"}Result: prompt did not go through, but no visible reason/message was shown.
- Non-blocking warning payload, exit 0:
{"systemMessage":"ZENITY_WARN_UI_PROBE: Codex hook systemMessage visibility test","hookSpecificOutput":{"hookEventName":"UserPromptSubmit","additionalContext":"ZENITY_WARN_UI_PROBE: Codex hook systemMessage visibility test"}}Result: prompt went through. The message appeared to be consumed as hidden/developer context, but it was not visible in the app.
- System-message-only payload, exit 0:
{"systemMessage":"ZENITY_SYSTEM_MESSAGE_ONLY_PROBE: visible warning test"}Result: prompt went through; no visible warning/message appeared in the app.
- Plain text stdout with exit 2:
ZENITY_STDOUT2_PROBE: blocked via raw stdout textResult: hook ran and exited 2, but the prompt still went through normally. Raw stdout does not appear to be a block/display channel for
UserPromptSubmit.- Stderr with exit 2:
Result: did not produce a useful visible message in Desktop.
Notes
PreToolUseblocking did surface its message correctly during the same testing, so the visible-message gap appears specific toUserPromptSubmitin Desktop.A likely relevant source path is
codex-rs/core/src/hook_runtime.rs: theimpl From<UserPromptSubmitOutcome> for ContextInjectingHookOutcomecurrently destructuresstop_reason: _, so thestopReasonis discarded before the runtime outcome is returned. There may also be a Desktop UI gap for renderingHookCompletedEventfeedback/system messages for stopped user prompts.Temporary workaround: launch an out-of-band Windows MessageBox from the hook for blocked
UserPromptSubmitevents, while keeping stdout protocol-clean. That works, but it is not an in-app UX and should not be necessary for policy/enforcement hooks.Reacted by Felix RathThe field that matters for hooks is not only event name parity. It is whether a hook decision becomes visible, durable, and actionable at the right boundary.
For
UserPromptSubmit, I would treat a blocking hook as an admission decision on the prompt, before any agent work starts.Minimum event result shape:
- hook event id;
- session id;
- prompt attempt id;
- decision: allow, warn, block;
- reason/message intended for the user;
- model-visible: true/false;
- terminal_for: prompt_attempt or none;
- retry_allowed: true/false.
If the hook blocks and the user never sees the reason, the system is technically enforcing policy but operationally failing the approval loop. The user needs to know whether to edit the prompt, retry, or escalate.
Acceptance tests:
- blocking
UserPromptSubmitreason is shown in Desktop and CLI; - warning reason is visible without aborting the prompt;
- blocked prompt does not start a model/tool run;
- event logs preserve the decision and reason without leaking hidden hook output into the transcript.
14 remaining items
v0.9.2 of world-model-mcp shipped with the multi-seed replication. The +10.2 pts paired delta I cited in this thread on 2026-06-24 as Claude Code-side evidence for hook-contract value does not replicate at seed 2 on a pre-registered 17-instance subset. Load-bearing replication is 0 of 7; mean paired delta across two seeds is +0.24 per instance with bootstrap 95% CI [0.00, 0.47]. The architectural argument for parity (typed events, decision/authority semantics, blocking PreCompact, payload schema versioning) is unchanged; the empirical magnitude of the effect-size example is now honestly bounded.
Honest update per SEED_PLAN.md acceptance criterion B locked 2026-06-25. Posting on the same thread where the original claim was made.
Multi-seed appendix: https://github.com/SaravananJaichandar/world-model-mcp/blob/main/benchmarks/repeat-mistake/RESULTS.md
v0.10.0 update: world-model-mcp now runs across seven runtimes via three new adapters (OpenClaw, Hermes Agent, Continue). Each new adapter continues the pattern that Codex's PreToolUse / PostToolUse / PostCompact / SessionStart hook coverage established: same
hook_helperandinject_helperPython code drives all seven adapters, only the manifest format differs. The Codex adapter itself is unchanged in this release.Two implementation notes from the E2E runs that other adapter authors may hit: OpenClaw's process spawn doesn't inherit shell PATH (absolute interpreter paths required — install command now defaults to
sys.executableand rejects relative overrides), and Hermes' 1327-line commented reference config.yaml needs ruamel.yaml round-trip mode rather than pyyaml to survive a merge without stripping documentation. Both handled preemptively in the v0.10 install commands. Release: https://github.com/SaravananJaichandar/world-model-mcp/releases/tag/v0.10.0I filed #32753 for a Multi-agent V2 observability regression: after inter-agent messages were encrypted, operators lost every supported way to inspect the exact instructions and follow-up messages sent to subagents. This is broader than hook parity; hooks are only one possible way to restore the missing causal audit trail.
I’d like to propose a focused implementation of the missing
PermissionDeniedlifecycle event tracked here.I understand that external PRs are invitation-only, so I am not opening a pull request without explicit maintainer approval. I have a working local prototype and would like to confirm the event contract and intended scope first.
Proposed contract
- Add
PermissionDeniedas a first-class hook event. - Offer it only after an approval result is final and normalized.
- Emit it for
Denied,TimedOut, andAbort, plus non-allow network-policy amendment results. - Emit the generic event for every decision source and use
decision_sourceas the matcher input:auto_reviewuserhook
- This lets a handler use
^auto_review$without hard-coding source suppression into the runtime. - Keep the event observational: handler output cannot approve the action, replace the rejection, request another review, or otherwise modify the final decision.
- Preserve the original rejection even if the hook command fails.
The proposed command input includes the normal session/turn/cwd/model context plus:
{ "hook_event_name": "PermissionDenied", "decision_source": "auto_review", "decision": "denied", "tool_name": "Bash", "tool_input": {}, "message": "<existing user-facing rejection text>" }The implementation covers generic tool approval, MCP approval, network approval, and Unix escalation paths. It also adds the event to config parsing, hook schemas, managed-hook requirements, app-server v2 schemas, analytics, and the TUI hook browser.
This is related to #23465, but is deliberately post-decision and observational rather than changing the existing blocking
PermissionRequestcontract.Prototype validation
- Focused hook, protocol, config, app-server-protocol, core, MCP, Guardian, and TUI tests pass.
- The relevant TUI snapshots and generated hook/config/app-server schemas are updated.
- A release binary builds and
codex doctorreports 17 checks OK with no warnings or failures outside the harness sandbox. - A live smoke test confirmed that an approved request emits no denial notification, while an automatic-review denial prevents execution and delivers exactly one
PermissionDeniednotification. - A full local
just testrun completed 12,499/12,510 tests successfully. Eight of the eleven failures passed when rerun serially; the remaining three appear environment/context-sensitive and are still being baseline-audited before any PR would be marked ready.
Before I prepare an invited PR, could a maintainer please confirm:
- Should the generic event be emitted for every final denial source, with source-specific behavior handled entirely by matchers?
- Are
auto_review,user, andhookthe desired external source labels? - Should non-allow network amendments normalize to
decision = "denied"? - Should the first PR include the app-server/TUI/schema surfaces, or would you prefer a narrower staged landing?
- If this direction aligns with the intended hooks architecture, would you be willing to invite a PR for the implementation?
I’m happy to adapt the prototype to the maintainers’ preferred payload, naming, staging, and test requirements.
- Add
world-model-mcp (OSS memory MCP) already ships a Codex adapter. The hook events it hard-depends on today are
PostToolUseandUserPromptSubmit. If Codex lands full parity with Claude Code's hook surface (SessionStart,SessionEnd,Stop,PreCompact,Notification,SubagentStop), we'd wire the missing ones in the next release without a schema change. Thecontent_type: rule | fact | procedurerouting added in v0.11.1 is agent-agnostic.One concrete request that would help third-party integrations. When a hook fires, pass the raw event payload untouched. Claude Code's convention of a stable JSON envelope with
tool_name,tool_input,tool_response, andsession_idis what makes cross-agent parity actually work in practice. If Codex normalizes fields between hook types, downstream MCP servers have to write per-agent shims that break every release.Watching this issue.
- added 4 commits that reference this issue
on Jul 22, 2026 Update (2026-07-30): I completed the MCP elicitation notification change as a separate, focused implementation. PostCompact context reinjection is tracked independently in #17148.
Proposed MCP notification contract:
- reuse the existing legacy
notifyargv; - spawn it immediately before Codex emits the native
ElicitationRequest; - emit only
type,server-name, andrequest-mode(form,openai/form, orurl); - exclude request content/schema, URL, request id, cwd, client, and session id;
- log notify spawn failures without delaying or blocking native elicitation;
- after a successful spawn, keep the notifier detached without waiting for its eventual exit status.
Focused validation:
codex-hooks: 129/129 tests passed, including payload privacy and legacy wire-shape coverage;- core integration test confirms that a notify spawn failure does not prevent native elicitation.
Would this lifecycle point and payload shape be acceptable as a public compatibility contract?
I have not opened a PR because external contributions require an explicit maintainer invitation. If this direction aligns with the intended hooks architecture, I would be happy to prepare the focused implementation for review.
- reuse the existing legacy
I maintain https://github.com/pickypg/ai-agent-macropad, an agent-agnostic hardware/status integration that consumes lifecycle hooks from Claude Code and Codex CLI. Codex’s current core events already let us support session, tool, permission, and completion states. However, the lack of a reliable PostToolUseFailure signal means failed tools cannot be represented correctly, and the absence of a Notification/waiting-for-user event prevents portable “needs attention” behavior across agents.
A needs-attention hook is especially valuable: it tells users when an AI needs their input but does not already have it. That attention state is easy to miss when several agents are running concurrently, and a visible or hardware notification lets users return to the right session promptly. Supporting these lifecycle signals would make cross-agent tooling substantially more reliable.
The recent PermissionDenied, raw-payload, PostToolUseFailure, and needs-attention use cases make the contract boundary more concrete.
Rather than add another event-name proposal, I think the next useful artifact is the small vendor-neutral conformance fixture discussed earlier.
I can make it executable around four cases:
final permission denial is observable but cannot regain execution authority;
tool failure is represented explicitly rather than inferred from PostToolUse;
waiting-for-user / notification state is observable without being an authorization signal;
the original event payload is preserved so downstream integrations do not need per-runtime shims.
The core invariant would remain:
event != notification != authorization != execution
This would not prescribe Codex internals; it would only provide deterministic fixtures that Codex, adapters, and third-party integrations could run against the same boundary contract.
If that is still useful for this tracker, I’m happy to publish the JSON Schema + minimal fixtures as the next concrete artifact.I found a concrete example supporting the need for a more explicit Codex hook contract across CLI and Desktop.
A custom
SessionStarthook on macOS failed because it expected an obsoleteAGENTS.mdsection. The hook returnedcontinue: false, but the user-visible result was effectively a prompt that never started. The CLI process exited successfully, yet no agent message was produced. The Desktop surface would have little reason to distinguish that from an app-server or model hang unless the hook failure were surfaced explicitly.The practical fix was local:
- resolve the canonical instruction source instead of a stale compatibility path;
- make optional instruction sections non-fatal;
- expose hook failure details in a structured field;
- avoid unsupported response fields on events that cannot emit them;
- test both the standalone and bundled Codex binaries;
- use ephemeral test sessions before touching persistent history.
The broader product request is for first-class observability around
InstructionsLoaded,HookFailure, and the source path or configuration layer that caused the hook to run. A failed blocking hook should produce a clear error state with a retry or disable path, rather than leaving the composer in an indefinite loading state. This is especially important because Desktop, CLI, app-server, plugins, and subagents may not currently expose hook failures consistently.safal207 commented
on Aug 25, 2026 More actions@AdiedX this is a useful concrete boundary case for the vendor-neutral fixture discussed above.
It shows that hook conformance needs to keep control outcome and user-visible feedback as separate claims:
continue: false/ block can successfully prevent the prompt from being dispatched;- that does not imply the denial reason was surfaced to the user;
- conversely, a visible warning does not imply the hook had execution authority.
I would add a deterministic
UserPromptSubmitfixture with two independent assertions:- authority/control: the prompt is not dispatched after the final block/stop decision;
- feedback/observability: the structured reason remains available to the surface and is rendered (or is explicitly reported as unsupported), rather than disappearing into hidden context.
The contrast you observed with
PreToolUseis especially useful because it gives a cross-surface/event parity check rather than an abstract schema requirement.That keeps the core boundary explicit:
decision != lifecycle event != notification != executionand avoids treating “the enforcement worked” as proof that the denial was observable or diagnosable.
I’ll treat this as another concrete fixture case rather than proposing another Codex-specific event shape.
Adding a parity gap that the PreToolUse row's current wording ("coverage must be consistent across every tool handler") doesn't capture: the decision vocabulary differs from Claude Code, and
permissionDecision: "ask"is accepted by the wire but rejected at parse time.Verified against the source at tag
rust-v0.153.3:hooks/src/schema.rsPreToolUse output schema includes"ask"in thepermissionDecisionenum — so a Claude-Code-style hook config that emits it parses cleanly.hooks/src/engine/output_parser.rs(theaskarm) then rejects it as unsupported: the hook is marked Failed and the command proceeds (hooks fail open; see [Hooks] Add opt-in fail-closed handling for PreToolUse hook failures #41979).
For comparison, Claude Code's PreToolUse contract supports three decisions:
allow,deny, andask— whereaskdefers to the interactive approval surface. Codex's PreToolUse outcome model has no ask state at all (only Continue/Blocked), so there is no path from a PreToolUse hook to the interactive approval UI, even whenPermissionRequesthooks exist and can answer approvals Codex itself initiates (Session::request_approval). Underapproval_policy = never, no approval is ever initiated, so neither PermissionRequest hooks nor the approval UI can be reached from PreToolUse.Concrete external-hook consequence (from a PreToolUse policy hook on 0.153.3): a policy that wants "ask the human before this command runs" has only two expressible outcomes — allow (runs) or deny (blocked, with a reason). Neither matches Claude Code semantics; the Claude-compatible
askemission silently degrades to hook-failed (compounding with #41979's fail-open behavior).Suggested parity items for this tracker:
- PreToolUse decision vocabulary row (new): either honor
permissionDecision: "ask"by routing to the existing approval path (Session::request_approval), or rejectaskat config-parse time with a clear message — currently the schema admits it and the parser silently fails the hook. - Definition of DoD addition: "PreToolUse supports the full Claude Code decision vocabulary (allow / deny / ask), or documents the divergence explicitly in the hooks reference." The hooks reference currently documents neither the decision vocabulary nor the failure table ([Hooks] Add opt-in fail-closed handling for PreToolUse hook failures #41979, [Feature] Document hooks payload schema or expose codex session info --json for current model/reasoning effort #21990).
Related: #41979 (fail-open hook failures), #21990 (payload/schema documentation), #27833 (PreToolUse deny not enforced for apply_patch).
Full Claude Code Hook Parity (29+)
Umbrella tracker for bringing Codex hooks to full Claude Code-style parity, while keeping Codex-native event names and payloads where they make more sense.
The goal is not just more hook names. The goal is a complete automation surface:
29+leaves room for Codex-native hooks beyond Claude parity, especially skills, MCP, plan prompts, approval prompts, and local playbook promotion.Event Matrix
SessionStartSetupUserPromptSubmitUserPromptExpansionPreToolUsePermissionRequestPermissionDeniedPostToolUsePostToolUseFailurePostToolBatchNotificationSubagentStartSubagentStopTaskCreatedTaskCompletedStopStopFailureTeammateIdleInstructionsLoadedConfigChangeCwdChangedFileChangedWorktreeCreateWorktreeRemovePreCompactPostCompactElicitationElicitationResultSessionEndHandler Matrix
commandhttpmcp_toolpromptagentRuntime Matrix
Definition Of Done