Repository navigation
Full Claude Code Hook Parity (29+) #21753
Copy link
Copy link
Open
Labels
enhancementNew feature or requestNew feature or requesthooksIssues related to event hooksIssues related to event hooks
Description
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:
- every major lifecycle transition is observable
- every high-risk action has a blocking interception point
- every hook payload is stable, typed, and documented
- every handler mode can participate in the same event surface
- hooks work consistently across CLI, TUI, Desktop, IDE, plugins, subagents, worktrees, resumes, compaction, and session shutdown
29+ leaves room for Codex-native hooks beyond Claude parity, especially skills, MCP, plan prompts, approval prompts, and local playbook promotion.
Event Matrix
| Event | Parity state | Codex notes |
|---|---|---|
SessionStart |
Shipped | Needs stable source metadata and resume semantics. |
Setup |
Missing | Early environment/project setup hook. |
UserPromptSubmit |
Shipped | Needs clean visible/hidden context behavior. |
UserPromptExpansion |
Missing | Prompt expansion/suggestion interception. |
PreToolUse |
Partial | Coverage must be consistent across every tool handler, not only selected paths. |
PermissionRequest |
Shipped | Blocking approval bridge exists; needs complete payload contract. |
PermissionDenied |
Missing | Denial should be observable as its own transition. |
PostToolUse |
Partial | Needs complete coverage, including long-running/polled sessions and all write paths. |
PostToolUseFailure |
Missing | Failures should not be inferred from generic post-tool payloads. |
PostToolBatch |
Missing | Needed for grouped edits/tool batches. |
Notification |
Partial | Notify behavior exists, but event semantics need parity clarity. |
SubagentStart |
Missing | Needs root/subagent identity and lineage. |
SubagentStop |
Missing | Needs root/subagent identity and terminal state. |
TaskCreated |
Missing | Task lifecycle should be observable. |
TaskCompleted |
Missing | Task lifecycle should be observable. |
Stop |
Shipped | Needs reliable continuation and better validation errors. |
StopFailure |
Missing | Stop hook failure should be first-class. |
TeammateIdle |
Missing | Useful for multi-agent/wrapper orchestration. |
InstructionsLoaded |
Missing | Needed for deterministic memory/rule/cache injection parity. |
ConfigChange |
Missing | Needed for hot reload and plugin/runtime config drift. |
CwdChanged |
Missing | Needed for multi-worktree and repo-local config correctness. |
FileChanged |
Missing | Needed for external editor and generated-file awareness. |
WorktreeCreate |
Missing | Needed for parallel-agent workspace orchestration. |
WorktreeRemove |
Missing | Needed for cleanup and watcher state. |
PreCompact |
Partial | Requested separately; should pair with post-compaction. |
PostCompact |
Partial | Exists in some form; needs final contract and parity docs. |
Elicitation |
Missing | Needed for interactive prompt/question surfaces. |
ElicitationResult |
Missing | Needed for answers/results from interactive prompt/question surfaces. |
SessionEnd |
Partial | Needs reliable shutdown/thread-close semantics across surfaces. |
Handler Matrix
| Handler type | Parity state | Notes |
|---|---|---|
command |
Shipped | Baseline executable hook handler. |
http |
Missing | Needed for local daemons and wrapper services. |
mcp_tool |
Missing | Needed for hook-to-MCP orchestration. |
prompt |
Missing | Needed for model-visible context injection without shell glue. |
agent |
Missing | Needed for delegated analysis/repair hooks. |
Runtime Matrix
| Capability | Target state |
|---|---|
| Blocking hooks | Supported for all relevant interception points. |
| Async hooks | Supported where transition does not need to block. |
| Payload schema | Machine-readable, versioned, and documented. |
| Matcher schema | Consistent across tools, files, MCP, skills, agents, and prompts. |
| Suppression controls | Hook output can be hidden, collapsed, or made model-visible without TUI noise. |
| Audit logs | Durable and searchable without polluting normal transcripts. |
| Hot reload | Hook config changes take effect predictably or report why they cannot. |
| Plugin scope | Plugin-defined hooks load into the same runtime with stable bundle context. |
| Trust flow | Local installers/wrappers can request hook trust through a supported path. |
| Cross-surface support | CLI, TUI, Desktop, IDE, and app surfaces behave consistently. |
Definition Of Done
- Codex publishes a single canonical hook event/handler schema.
- Existing hook bugs and feature requests can be mapped onto that schema.
- Claude Code parity gaps are explicit rather than rediscovered issue by issue.
- Codex-native extensions are admitted as first-class hooks instead of one-off surfaces.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or requesthooksIssues related to event hooksIssues related to event hooks
Activity
oxysoft commentedon May 8, 2026
Indexed hook tickets (canonical
hookslabel, state as of May 8, 2026):Event Hooks #2109
Notify not getting triggered #8929
Please give us a hook for custom compaction #11912
Better notification for multi-agent #12341
Add PreToolUse and PostToolUse hook events for code quality enforcement #14754
Add a native pre-turn dynamic context hook for time-sensitive metadata #14814
Proposal: add PreToolUse/PostToolUse lifecycle hooks to Codex hooks engine #14882
UserPromptSubmit and SessionStart hooks fire simultaneously on first prompt #15266
SessionStart not firing on session start instead it fires on first user prompt submission #15269
Add blocking PermissionRequest hook for external approval UIs #15311
Expose CollabAgentSpawn{Begin,End} as hook events #15486
Expose AfterToolUse in hooks.json and support codex_hooks on Windows #15490
Support suppressing hook status messages in TUI (suppressOutput is a no-op) #15497
Add pre_compact and post_compact hooks for context compaction #16098
Hooks: distinguish subagent events from main agent #16226
Hooks: PostToolUse is missing for tools that complete via exec session / polling path #16246
hooks: add permission request event for parity with claude code's auto-approve flow #16301
Hooks should support stable bundle/plugin context for reusable hook scripts #16466
Feature request: official machine-readable event surface for approvals and turn lifecycle #16484
UserPromptSubmit.additionalContextas multiline hook context in the TUI #16486 - RenderUserPromptSubmit.additionalContextas multiline hook context in the TUIRender
UserPromptSubmit.additionalContextas multiline hook context in the TUI #16486ApplyPatchHandler doesn't emit PreToolUse/PostToolUse hook event. Hooks only fire for Bash tool. #16732
Hooks log output is very noisy #16743
Codex CLI renders hook additionalContext as visible developer message #16933
tui: suppress hook notifications when there is nothing to display #16993
Add hook_report_level config to suppress routine hook chatter #17105
Add PreSkillUse and PostSkillUse hooks for explicit and implicit skill usage #17132
Pre and PostCompact hooks #17148
Hook execution audit logs clutter session terminal output #17321
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 runtimePlugin manifests define
hooks, but plugin hooks are not loaded into the Codex hooks runtime #17331Feature Request: Add TaskCompleted Hook Event #17333
Feature request: expose native composer suggestion hooks/API for local plugins #17341
Add SessionEnd hook #17421
Force hook usage approval with config #17422
Enable hooks on Windows #17478
Codex Desktop shows background hook transcript noise, while the TUI does not #17479
Greeting message hook #17518
codex_hooks do not fire in interactive sessions when configured via repo-local .codex/config.toml #17532
Hot-reload hook configuration during a live session #17636
File write operations do not fire PreToolUse/PostToolUse hooks #17794
Add hook support for IDE extension and Codex app #17930
MCP hook #18051
【BUG】Codex CLI hooks fail silently on Linux/Windows when editing large files #18067
Hook support not working in IDE extension and Codex app #18090
Support "Edit|Write" matcher in PostToolUse and PreToolUse #18295
[Feature request] Extend PreToolUse hooks beyond Bash + implement updatedInput rewrite #18491
UserPromptSubmithook withoutStophook afterwards #18541 - Ambients Suggestions feature usesUserPromptSubmithook withoutStophook afterwardsAmbients Suggestions feature uses
UserPromptSubmithook withoutStophook afterwards #18541Codex exec does not fire Stop / SessionStop / PostToolUse hooks (only UserPromptSubmit fires) #18607
Stop hook invalid JSON error is too opaque for unsupported fields #18887
Add a post-compaction hook for deterministic memory reinjection #19061
codex-cli 0.124.0 fails to start when hook config is present and codex_hooks is enabled #19199
Expose TUI question prompts ("Implement this plan?", reasoning scope, etc.) to the external hook system #19328
Error starting chat - invalid configuration #19364
Allow Codex hooks to run silently without rendering completed hook entries #19383
Support additionalContext in PreToolUse hooks or clarify Claude-style hook parity #19385
Docs: SessionStart source field omits clear value #19666
Hooks do not fire in interactive sessions (v0.125.0) #19780
Expose plan-mode-prompt and approval-requested through top-level notify #19921
Inconsistent PreToolUse hook coverage across tool handlers (most tools never emit hook events) #20204
SessionEndhook event for session/thread shutdown #20374 - AddSessionEndhook event for session/thread shutdownAdd
SessionEndhook event for session/thread shutdown #20374Expose hook capabilities and a session-exit hook for integrations #20603
Built-in image generation does not appear to emit PreToolUse hooks #20616
Expose root/subagent metadata in hook payloads #20675
Add an option to collapse hook-injected context in the CLI transcript #20766
Blocking stop hook continuation can fail with invalid local message id #20783
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 ~4sSessionStart hook on resume can report
hook timed out after 60seven when the hook exits 0 in ~4s #20862Native apply_patch lacks per-call workdir context for Hooks in multi-worktree repositories #20879
Proposal: repo-scoped experience compiler hooks for memory, evals, briefs, and skills #20985
/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) #21148Hooks stop firing after rate-limit stops or live hooks.json edits #21160
Provide a supported way for local IDE/wrapper installers to request trust for installed hooks #21615
Hooks no longer run after Codex Desktop update #21639
Codex Rules: per-session cache for additionalContext (Claude Code InstructionsLoaded parity) #21675
Allow hook additionalContext to be model-visible but hidden from TUI #21696
Running hooks (Start, Stop, any other) hooks do not show up nor run in actual since today (8th May) #21723
Enable Codex to promote recurring fixes into reusable approved local playbooks #21748
github-actions commentedon May 8, 2026
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
SessionEndhook event for session/thread shutdown #20374Powered by Codex Action
pmatos commentedon May 11, 2026
Missing the SessionEnd hook atm.
Add Codex CLI plugin (#142)
hooks: declaratively scope validate-mthds to .mthds files
Morriz commentedon May 14, 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?
zenvor commentedon May 20, 2026
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 limituser.spam,session.end,task.progressSpec 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:
SessionStartsession.startUserPromptSubmittask.acknowledgePermissionRequestinput.requiredPostToolUsesuccesstask.progressor tool-specific progresstask.errorStopsuccessful turntask.completesession.endresource.limitThe 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 commentedon May 20, 2026
SaravananJaichandar commentedon Jun 6, 2026
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:
blockingauthorityterminal_forresume_capableA 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
docs(expo): correct Codex hook status + mark the enablement path
feat(expo): make skill_invoked resolver payload-tolerant (Codex-ready)
andyp-wq commentedon Jun 8, 2026
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-cli 0.131.0-alpha.9C:\ProgramData\OpenAI\Codex\requirements.tomlUserPromptSubmit,PreToolUse,PostToolUseExpected 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.
{"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.{"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.
{"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.
{"systemMessage":"ZENITY_SYSTEM_MESSAGE_ONLY_PROBE: visible warning test"}Result: prompt went through; no visible warning/message appeared in the app.
Result: 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.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.rpelevin commentedon Jun 8, 2026
The 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:
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:
UserPromptSubmitreason is shown in Desktop and CLI;14 remaining items
SaravananJaichandar commentedon Jun 30, 2026
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
SaravananJaichandar commentedon Jul 1, 2026
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.0hoganfan commentedon Jul 13, 2026
I 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.
ifoster01 commentedon Jul 20, 2026
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
PermissionDeniedas a first-class hook event.Denied,TimedOut, andAbort, plus non-allow network-policy amendment results.decision_sourceas the matcher input:auto_reviewuserhook^auto_review$without hard-coding source suppression into the runtime.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
codex doctorreports 17 checks OK with no warnings or failures outside the harness sandbox.PermissionDeniednotification.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:
auto_review,user, andhookthe desired external source labels?decision = "denied"?I’m happy to adapt the prototype to the maintainers’ preferred payload, naming, staging, and test requirements.
SaravananJaichandar commentedon Jul 21, 2026
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.
docs(adapters): SubagentStart probe — Codex 0.145.0 custom-role lifec…
docs(P078d2b): declare Codex in-subagent role-envelope enforcement MI…
fix(P078e): close Codex approval-transition deadlock + block worker s…
fix(P078h): Codex actor-check advance-block (gap #3) + patch-path nor…
trevi00 commentedon Jul 27, 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:
notifyargv;ElicitationRequest;type,server-name, andrequest-mode(form,openai/form, orurl);Focused validation:
codex-hooks: 129/129 tests passed, including payload privacy and legacy wire-shape coverage;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.
pickypg commentedon Aug 22, 2026
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.
safal207 commentedon Aug 22, 2026
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.
AdiedX commentedon Aug 22, 2026
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:
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 commentedon Aug 25, 2026
@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;I would add a deterministic
UserPromptSubmitfixture with two independent assertions: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.
chrysent commentedon Sep 17, 2026
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:
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.Related: #41979 (fail-open hook failures), #21990 (payload/schema documentation), #27833 (PreToolUse deny not enforced for apply_patch).