Full Claude Code Hook Parity (29+)

Open 💬 28 comments Opened May 8, 2026 by oxysoft
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

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.

View original on GitHub ↗

28 Comments

oxysoft · 2 months ago

Indexed hook tickets (canonical hooks label, state as of May 8, 2026):

  • [CLOSED/COMPLETED] #2109 - Event Hooks

https://github.com/openai/codex/issues/2109

  • [OPEN] #8929 - Notify not getting triggered

https://github.com/openai/codex/issues/8929

  • [OPEN] #11912 - Please give us a hook for custom compaction

https://github.com/openai/codex/issues/11912

  • [CLOSED/NOT_PLANNED] #12341 - Better notification for multi-agent

https://github.com/openai/codex/issues/12341

  • [CLOSED/COMPLETED] #14754 - Add PreToolUse and PostToolUse hook events for code quality enforcement

https://github.com/openai/codex/issues/14754

  • [CLOSED/NOT_PLANNED] #14814 - Add a native pre-turn dynamic context hook for time-sensitive metadata

https://github.com/openai/codex/issues/14814

  • [CLOSED/DUPLICATE] #14882 - Proposal: add PreToolUse/PostToolUse lifecycle hooks to Codex hooks engine

https://github.com/openai/codex/issues/14882

  • [CLOSED/COMPLETED] #15266 - UserPromptSubmit and SessionStart hooks fire simultaneously on first prompt

https://github.com/openai/codex/issues/15266

  • [CLOSED/DUPLICATE] #15269 - SessionStart not firing on session start instead it fires on first user prompt submission

https://github.com/openai/codex/issues/15269

  • [CLOSED/COMPLETED] #15311 - Add blocking PermissionRequest hook for external approval UIs

https://github.com/openai/codex/issues/15311

  • [CLOSED/NOT_PLANNED] #15486 - Expose CollabAgentSpawn{Begin,End} as hook events

https://github.com/openai/codex/issues/15486

  • [CLOSED/DUPLICATE] #15490 - Expose AfterToolUse in hooks.json and support codex_hooks on Windows

https://github.com/openai/codex/issues/15490

  • [CLOSED/COMPLETED] #15497 - Support suppressing hook status messages in TUI (suppressOutput is a no-op)

https://github.com/openai/codex/issues/15497

  • [CLOSED/DUPLICATE] #16098 - Add pre_compact and post_compact hooks for context compaction

https://github.com/openai/codex/issues/16098

  • [OPEN] #16226 - Hooks: distinguish subagent events from main agent

https://github.com/openai/codex/issues/16226

  • [CLOSED/COMPLETED] #16246 - Hooks: PostToolUse is missing for tools that complete via exec session / polling path

https://github.com/openai/codex/issues/16246

  • [CLOSED/COMPLETED] #16301 - hooks: add permission request event for parity with claude code's auto-approve flow

https://github.com/openai/codex/issues/16301

  • [OPEN] #16466 - Hooks should support stable bundle/plugin context for reusable hook scripts

https://github.com/openai/codex/issues/16466

  • [OPEN] #16484 - Feature request: official machine-readable event surface for approvals and turn lifecycle

https://github.com/openai/codex/issues/16484

  • [OPEN] #16486 - Render UserPromptSubmit.additionalContext as multiline hook context in the TUI

https://github.com/openai/codex/issues/16486

  • [CLOSED/COMPLETED] #16732 - ApplyPatchHandler doesn't emit PreToolUse/PostToolUse hook event. Hooks only fire for Bash tool.

https://github.com/openai/codex/issues/16732

  • [CLOSED/DUPLICATE] #16743 - Hooks log output is very noisy

https://github.com/openai/codex/issues/16743

  • [OPEN] #16933 - Codex CLI renders hook additionalContext as visible developer message

https://github.com/openai/codex/issues/16933

  • [CLOSED/DUPLICATE] #16993 - tui: suppress hook notifications when there is nothing to display

https://github.com/openai/codex/issues/16993

  • [CLOSED/DUPLICATE] #17105 - Add hook_report_level config to suppress routine hook chatter

https://github.com/openai/codex/issues/17105

  • [OPEN] #17132 - Add PreSkillUse and PostSkillUse hooks for explicit and implicit skill usage

https://github.com/openai/codex/issues/17132

  • [OPEN] #17148 - Pre and PostCompact hooks

https://github.com/openai/codex/issues/17148

  • [CLOSED/DUPLICATE] #17321 - Hook execution audit logs clutter session terminal output

https://github.com/openai/codex/issues/17321

  • [CLOSED/COMPLETED] #17331 - Plugin manifests define hooks, but plugin hooks are not loaded into the Codex hooks runtime

https://github.com/openai/codex/issues/17331

  • [OPEN] #17333 - Feature Request: Add TaskCompleted Hook Event

https://github.com/openai/codex/issues/17333

  • [OPEN] #17341 - Feature request: expose native composer suggestion hooks/API for local plugins

https://github.com/openai/codex/issues/17341

  • [CLOSED/DUPLICATE] #17421 - Add SessionEnd hook

https://github.com/openai/codex/issues/17421

  • [OPEN] #17422 - Force hook usage approval with config

https://github.com/openai/codex/issues/17422

  • [CLOSED/COMPLETED] #17478 - Enable hooks on Windows

https://github.com/openai/codex/issues/17478

  • [CLOSED/DUPLICATE] #17479 - Codex Desktop shows background hook transcript noise, while the TUI does not

https://github.com/openai/codex/issues/17479

  • [OPEN] #17518 - Greeting message hook

https://github.com/openai/codex/issues/17518

  • [OPEN] #17532 - codex_hooks do not fire in interactive sessions when configured via repo-local .codex/config.toml

https://github.com/openai/codex/issues/17532

  • [OPEN] #17636 - Hot-reload hook configuration during a live session

https://github.com/openai/codex/issues/17636

  • [CLOSED/DUPLICATE] #17794 - File write operations do not fire PreToolUse/PostToolUse hooks

https://github.com/openai/codex/issues/17794

  • [CLOSED/COMPLETED] #17930 - Add hook support for IDE extension and Codex app

https://github.com/openai/codex/issues/17930

  • [OPEN] #18051 - MCP hook

https://github.com/openai/codex/issues/18051

  • [OPEN] #18067 - 【BUG】Codex CLI hooks fail silently on Linux/Windows when editing large files

https://github.com/openai/codex/issues/18067

  • [CLOSED/COMPLETED] #18090 - Hook support not working in IDE extension and Codex app

https://github.com/openai/codex/issues/18090

  • [CLOSED/COMPLETED] #18295 - Support "Edit|Write" matcher in PostToolUse and PreToolUse

https://github.com/openai/codex/issues/18295

  • [OPEN] #18491 - [Feature request] Extend PreToolUse hooks beyond Bash + implement updatedInput rewrite

https://github.com/openai/codex/issues/18491

  • [OPEN] #18541 - Ambients Suggestions feature uses UserPromptSubmit hook without Stop hook afterwards

https://github.com/openai/codex/issues/18541

  • [CLOSED/NOT_PLANNED] #18607 - Codex exec does not fire Stop / SessionStop / PostToolUse hooks (only UserPromptSubmit fires)

https://github.com/openai/codex/issues/18607

  • [OPEN] #18887 - Stop hook invalid JSON error is too opaque for unsupported fields

https://github.com/openai/codex/issues/18887

  • [CLOSED/COMPLETED] #19061 - Add a post-compaction hook for deterministic memory reinjection

https://github.com/openai/codex/issues/19061

  • [CLOSED/COMPLETED] #19199 - codex-cli 0.124.0 fails to start when hook config is present and codex_hooks is enabled

https://github.com/openai/codex/issues/19199

  • [OPEN] #19328 - Expose TUI question prompts ("Implement this plan?", reasoning scope, etc.) to the external hook system

https://github.com/openai/codex/issues/19328

  • [CLOSED/DUPLICATE] #19364 - Error starting chat - invalid configuration

https://github.com/openai/codex/issues/19364

  • [OPEN] #19383 - Allow Codex hooks to run silently without rendering completed hook entries

https://github.com/openai/codex/issues/19383

  • [OPEN] #19385 - Support additionalContext in PreToolUse hooks or clarify Claude-style hook parity

https://github.com/openai/codex/issues/19385

  • [OPEN] #19666 - Docs: SessionStart source field omits clear value

https://github.com/openai/codex/issues/19666

  • [CLOSED/NOT_PLANNED] #19780 - Hooks do not fire in interactive sessions (v0.125.0)

https://github.com/openai/codex/issues/19780

  • [OPEN] #19921 - Expose plan-mode-prompt and approval-requested through top-level notify

https://github.com/openai/codex/issues/19921

  • [OPEN] #20204 - Inconsistent PreToolUse hook coverage across tool handlers (most tools never emit hook events)

https://github.com/openai/codex/issues/20204

  • [CLOSED/NOT_PLANNED] #20374 - Add SessionEnd hook event for session/thread shutdown

https://github.com/openai/codex/issues/20374

  • [CLOSED/COMPLETED] #20603 - Expose hook capabilities and a session-exit hook for integrations

https://github.com/openai/codex/issues/20603

  • [OPEN] #20616 - Built-in image generation does not appear to emit PreToolUse hooks

https://github.com/openai/codex/issues/20616

  • [OPEN] #20675 - Expose root/subagent metadata in hook payloads

https://github.com/openai/codex/issues/20675

  • [OPEN] #20766 - Add an option to collapse hook-injected context in the CLI transcript

https://github.com/openai/codex/issues/20766

  • [OPEN] #20783 - Blocking stop hook continuation can fail with invalid local message id

https://github.com/openai/codex/issues/20783

  • [CLOSED/COMPLETED] #20862 - SessionStart hook on resume can report hook timed out after 60s even when the hook exits 0 in ~4s

https://github.com/openai/codex/issues/20862

  • [OPEN] #20879 - Native apply_patch lacks per-call workdir context for Hooks in multi-worktree repositories

https://github.com/openai/codex/issues/20879

  • [CLOSED/COMPLETED] #20985 - Proposal: repo-scoped experience compiler hooks for memory, evals, briefs, and skills

https://github.com/openai/codex/issues/20985

  • [CLOSED/NOT_PLANNED] #21148 - Deprecation notice links to malformed hooks docs URL (/codex/hooks. returns 404)

https://github.com/openai/codex/issues/21148

  • [OPEN] #21160 - Hooks stop firing after rate-limit stops or live hooks.json edits

https://github.com/openai/codex/issues/21160

  • [OPEN] #21615 - Provide a supported way for local IDE/wrapper installers to request trust for installed hooks

https://github.com/openai/codex/issues/21615

  • [OPEN] #21639 - Hooks no longer run after Codex Desktop update

https://github.com/openai/codex/issues/21639

  • [OPEN] #21675 - Codex Rules: per-session cache for additionalContext (Claude Code InstructionsLoaded parity)

https://github.com/openai/codex/issues/21675

  • [OPEN] #21696 - Allow hook additionalContext to be model-visible but hidden from TUI

https://github.com/openai/codex/issues/21696

  • [OPEN] #21723 - Running hooks (Start, Stop, any other) hooks do not show up nor run in actual since today (8th May)

https://github.com/openai/codex/issues/21723

  • [OPEN] #21748 - Enable Codex to promote recurring fixes into reusable approved local playbooks

https://github.com/openai/codex/issues/21748

github-actions[bot] contributor · 2 months ago

Potential duplicates detected. Please review them and close your issue if it is a duplicate.

  • #20204
  • #21675
  • #20675
  • #20603
  • #20374

Powered by Codex Action

pmatos · 2 months ago

Missing the SessionEnd hook atm.

Morriz · 2 months ago

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 · 2 months ago

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 opens
  • task.acknowledge: work was accepted and processing started
  • task.complete: a unit of work finished successfully
  • task.error: work failed
  • input.required: the agent is blocked on user input or approval
  • resource.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 notify integrations 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 to task.acknowledge, while PermissionRequest maps to input.required, Stop / successful turn completion maps to task.complete, and tool or turn failures map to task.error.

A useful minimum for audio and accessibility tools would be:

| Codex hook/event | Suggested CESP mapping | Why it matters |
|---|---|---|
| SessionStart | session.start | Signal a workspace/session is ready |
| UserPromptSubmit | task.acknowledge | Play a confirmation sound immediately after the user sends a prompt |
| PermissionRequest | input.required | Alert the user that Codex is blocked |
| PostToolUse success | task.progress or tool-specific progress | Indicate long work is advancing |
| explicit tool/turn failure | task.error | Distinguish failures from normal completion |
| Stop successful turn | task.complete | End-of-turn completion sound |
| session/thread close | session.end | Cleanup/disconnect signal |
| rate/context/quota events | resource.limit | Notify 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, and Stop, 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 notify remain a simple compatibility path while richer integrations use lifecycle hooks directly.

Keesan12 · 2 months ago

One cross-runtime seam worth preserving is event identity versus policy meaning.

If Codex chases Claude Code parity by name alone, wrappers still end up branching on runtime-specific semantics because PermissionRequest, Stop, and Notification do not all carry the same authority. A small shared contract on every hook event such as blocking=true|false, authority=advisory|authoritative, terminal_for=child|root|none, and resume_capable=true|false would make migration much easier than one-to-one event-count parity.

That would let Codex stay native while still being a credible target for Claude Code-oriented automation stacks.

SaravananJaichandar · 1 month ago

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 defer enforcement tier in world-model-mcp is concrete field evidence for this.

I shipped defer as a third PreToolUse decision (between allow and deny) precisely because the binary deny/allow/ask space did not survive contact with headless agents. A constraint with severity = warning and violation_count >= 3 is too soft for deny (the agent is doing real work and the warning was advisory the first two times) and too hard for ask (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 existing permissionDecision enum 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 |
|---|---|
| blocking | Whether the hook can halt the transition |
| authority | Advisory versus authoritative, distinguishes a soft warning from a hard policy |
| terminal_for | Whether a stop applies to the child, the root, or neither |
| resume_capable | Whether 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 same deny can mean four different things depending on which layer asserted it.

Two specific matrix observations from the v0.7.5 Codex adapter integration:

  1. The PostToolUseFailure gap (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 typed failure_kind enum (validation_error, runtime_error, user_correction, model_correction) would let memory layers attribute corrections honestly. world-model-mcp currently flags the synthesized confidence tier for any fact that was never explicitly corroborated, but the failure-attribution path is still inference-driven.
  1. The InstructionsLoaded gap (Missing) blocks deterministic memory reinjection parity. Today, world-model-mcp's PostCompact hook can inject curated state as additionalContext, 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 a source_of_truth field 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 anthropics/claude-code#47023.

Adapter (Codex): https://github.com/SaravananJaichandar/world-model-mcp/tree/main/adapters/codex

andyp-wq · 1 month ago

Focused repro: UserPromptSubmit block/warning reasons are not visible in Codex Desktop

I hit a concrete UserPromptSubmit visibility 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 UserPromptSubmit hook blocks or stops a prompt, Codex Desktop should show the user-facing reason somewhere visible in the app, similar to how PreToolUse block reasons surface as messages such as Command blocked by PreToolUse hook: ....

Likewise, when a UserPromptSubmit hook returns a warning/system message without blocking, the warning should be visible to the user if the docs describe it as a systemMessage/warning surface.

Actual behavior

The prompt can be blocked, but Codex Desktop only shows a generic Not Sent marker. The hook-provided reason/message is not visible in the app.

A non-blocking systemMessage was 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.

  1. 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.

  1. 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.

  1. 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.

  1. 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.

  1. Plain text stdout with exit 2:
ZENITY_STDOUT2_PROBE: blocked via raw stdout text

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.

  1. Stderr with exit 2:

Result: did not produce a useful visible message in Desktop.

Notes

PreToolUse blocking did surface its message correctly during the same testing, so the visible-message gap appears specific to UserPromptSubmit in Desktop.

A likely relevant source path is codex-rs/core/src/hook_runtime.rs: the impl From<UserPromptSubmitOutcome> for ContextInjectingHookOutcome currently destructures stop_reason: _, so the stopReason is discarded before the runtime outcome is returned. There may also be a Desktop UI gap for rendering HookCompletedEvent feedback/system messages for stopped user prompts.

Temporary workaround: launch an out-of-band Windows MessageBox from the hook for blocked UserPromptSubmit events, 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 · 1 month ago

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:

  • 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 UserPromptSubmit reason 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.
SaravananJaichandar · 1 month ago

@rpelevin — agreed on the framing. Visibility-durability-actionability at the right boundary is the same axis Keesan12 named earlier in the thread (event identity versus policy meaning), and your payload sketch composes cleanly with the four fields proposed above (blocking, authority, terminal_for, resume_capable).

Your acceptance tests are the right ones, and @andyp-wq's Desktop repro just above is concrete evidence for why the visibility leg of the contract has to be enforced, not assumed. A blocking UserPromptSubmit that surfaces only "Not Sent" is exactly the operational failure mode the acceptance tests would catch.

One substantive disagreement on the decision enum: allow | warn | block is sufficient for prompt admission, but my v0.7.0 shipping experience on the PreToolUse side argues for a fourth state when the loop is headless. I shipped defer precisely because warn is too soft (the agent ignores the warning the next time the constraint fires) and block is too hard (no human is in the loop to unblock). For UserPromptSubmit specifically the three-value enum probably holds, since prompt submission is a user-initiated event by definition. But the moment the same contract is generalized across other hook events that fire mid-turn or in headless runs, the fourth state earns its keep.

The cleanest reconciliation: decision carries the three-value enum at the event boundary, and authority (from the Keesan12 fields) carries advisory-versus-authoritative independently. A decision: warn plus authority: authoritative is the defer case; decision: warn plus authority: advisory is the soft warning. That keeps your enum clean while preserving the runtime semantic the headless case needs.

rpelevin · 1 month ago

That reconciliation makes sense to me.

I would keep decision small and event-local, then let authority carry the runtime force of that decision.

For UserPromptSubmit, the decision can stay:

  1. allow
  2. warn
  3. block

because the event is user-initiated and the terminal boundary is the prompt attempt.

For mid-turn/headless events, I would avoid adding a fourth decision value if authority can express the defer case cleanly:

  1. decision: warn + authority: advisory = visible warning, run may continue
  2. decision: warn + authority: authoritative = defer / needs-human, run must not proceed until an authorized actor resolves it
  3. decision: block + authority: authoritative = terminal denial for that boundary

The acceptance test I would add is the headless one:

  1. PreToolUse fires in a headless/non-interactive run.
  2. Hook returns decision: warn, authority: authoritative, terminal_for: tool_call, resume_capable: true.
  3. Runtime does not execute the tool.
  4. Event log preserves the reason and pending/deferred state.
  5. A later approved resume can continue only the same pending tool call; changed tool/input/resource becomes stale.

That preserves the simple prompt-admission enum while still giving headless runs a real non-execution state that is stronger than a soft warning and less final than a block.

Necmttn · 29 days ago

Hook parity needs a typed event matrix backed by replay fixtures.

For each hook, keep event name, payload schema version, decision authority, blocking/warn behavior, resume/compaction behavior, and sample real payloads. Compatibility tests can then replay Claude-style fixtures and Codex-native fixtures so parity means stable semantics, not only matching names.

---

_Generated with ax._

SaravananJaichandar · 26 days ago

Empirical update relevant to the hook parity question. v0.9 of world-model-mcp shipped today with a pre-registered SWE-bench Verified benchmark on the Claude Code side of the parity gap. Lifecycle-hook-based persistent memory reduced repeated coding-agent failures by +10.2 pts combined paired delta across 49 instances. Within-domain +15.0 pts, cross-domain +6.9 pts with zero cross-domain regressions.

The methodologically clean piece for this thread: the same contract elements that need parity on Codex (typed events, decision/authority semantics, blocking PreCompact, payload schema versioning) are exactly what the Claude Code lifecycle hooks delivered to make this measurable. The +6.9 pts cross-domain transfer was achieved without any per-instance harness changes, only via the constraint extraction and re-injection layer the contract enables.

If the Codex side ships event-name parity without contract parity (the @rpelevin authority leg, the @Necmttn payload schema versioning), a memory layer cannot run this test on Codex. The empirical case for parity at the contract level, not just the event-name level, is what this benchmark establishes.

Full result: https://github.com/SaravananJaichandar/world-model-mcp/blob/main/benchmarks/repeat-mistake/RESULTS.md

safal207 · 26 days ago

This umbrella issue maps closely to the vendor-neutral Trusted Runtime contracts we are developing in LS.

One useful design principle may be:

hook event
≠ model-visible notification
≠ authorization
≠ execution

A canonical hook schema should make those boundaries explicit rather than relying on handler-specific conventions.

A possible versioned event envelope:

{
"schema_version": "agent-hook-event/v0.1",
"event_id": "evt-001",
"event_type": "PreToolUse",
"trajectory_id": "project-task-trajectory",
"continuation_id": "current-thread-continuation",
"actor": {
"session_id": "thread-123",
"agent_id": "agent-456",
"role": "implementer",
"parent_agent_id": "agent-root"
},
"subject": {
"tool_family": "file_mutation",
"tool_name": "internal_patch",
"target_refs": ["src/example.py"]
},
"context_refs": [
"constraint:no-production-write",
"decision:approved-scope"
],
"decision": {
"status": "HOLD",
"reason_code": "ACTIVE_CONSTRAINT_CONFLICT",
"model_visible": true,
"execution_authorized": false
},
"audit": {
"durable": true,
"transcript_visible": false
}
}

This would help unify several requirements already listed in the issue:

  • stable typed payloads;
  • blocking interception points;
  • root/subagent identity and lineage;
  • resume and compaction semantics;
  • durable audit logs;
  • consistent behavior across CLI, Desktop, IDE, plugins, and worktrees.

A few invariants may be useful:

«Every side-effecting operation must emit a matchable event, including internal tools that are not exposed under user-facing names.»

«Hook output may inform the model, but model visibility must not imply authorization.»

«A blocking decision must be durable and replayable, not only displayed in the TUI.»

«Resume and compaction should preserve the same trajectory while creating a new continuation identity.»

«Subagent events should include runtime identity, parent lineage, and terminal status so claimed work can be matched to actual execution.»

The same envelope could support:

PreCompact
→ preserve active constraints and operational tail

PostCompact
→ validate recovered state before injection

SubagentStart / SubagentStop
→ bind delegation to runtime execution receipts

PermissionRequest
→ produce an explicit approval record

PreToolUse
→ ALLOW / HOLD / BLOCK before effect

PostToolUse
→ typed observed outcome and evidence refs

A small conformance suite could test:

  1. internal patch tool still triggers "PreToolUse";
  2. blocking decision prevents mutation and appears in the audit log;
  3. compaction preserves trajectory identity and active constraints;
  4. resumed work receives a new continuation ID;
  5. subagent result cannot be reported without matching start/stop events;
  6. permission approval is bound to the exact requested action;
  7. asynchronous advisory hooks cannot accidentally grant execution authority.

Related LS work:

  • recovered-evidence continuation envelope:

https://github.com/safal207/LS/pull/651

  • causal audit:

https://github.com/safal207/LS/issues/594

  • evidence gates:

https://github.com/safal207/LS/issues/595

  • commit-before-effect:

https://github.com/safal207/LS/issues/596

  • deterministic replay:

https://github.com/safal207/LS/issues/597

Would a small vendor-neutral "AgentHookEvent" conformance fixture be useful for testing parity across Codex surfaces without prescribing the internal hook implementation?

rpelevin · 26 days ago

A small vendor-neutral conformance fixture would be useful if it tests the contract boundaries rather than only the event names.

The key split I would preserve is:

hook event is not the same thing as model-visible notification;
model-visible notification is not the same thing as authorization;
authorization is not the same thing as execution;
execution is not the same thing as audit durability.

For a fixture, I would make each event carry three independent axes:

  1. Observation: what happened, with event id, event type, trajectory id, continuation id, actor identity, parent lineage, tool or prompt subject, and target refs.
  2. Authority: whether the runtime is allowed to continue, hold, block, or resume, with a machine-readable reason and exact action binding.
  3. Visibility and durability: whether the model sees the message, whether the user sees it, whether it is persisted to audit, and whether it survives resume or compaction.

The acceptance tests I would pin first:

  1. An internal write or patch path emits the same pre-effect event class as a visible shell tool.
  2. A blocking pre-effect decision prevents mutation and leaves a durable audit record.
  3. A model-visible warning does not grant execution authority.
  4. A permission approval binds to the exact tool, args digest, target refs, actor, and continuation id.
  5. A disabled or checks-off runtime state cannot reuse stale enabled policy state to keep blocking or advising on later actions.
  6. Resume preserves trajectory identity but creates a new continuation id.
  7. Compaction preserves active constraints before reinjection and validates recovered state after reinjection.
  8. A subagent result is not accepted unless matching start, stop, parent lineage, and terminal status events exist.
  9. A post-effect event records the observed outcome and evidence refs without becoming retroactive authorization.

That keeps the fixture vendor-neutral while making parity testable across CLI, Desktop, IDE, plugins, and worktrees. The fixture does not need to prescribe the internal hook implementation; it only needs to define the externally observable contract a runtime must satisfy.

Boundary: architecture and test feedback only; no claim about using this project or running its code.

safal207 · 26 days ago

@rpelevin This separation is exactly right. I would make the first fixture encode the three axes independently rather than infer one from another:

  • "observation": event identity, type, trajectory/continuation, actor, parent lineage, subject, and target refs;
  • "authority": "ALLOW | HOLD | BLOCK | RESUME", exact action binding, decision ID, reason, and validity;
  • "visibility_durability": model-visible, user-visible, audit-persisted, survives-resume, and survives-compaction.

The mandatory invariant would be:

«Observation or visibility never implies authority, and a post-effect record never becomes retroactive authorization.»

A minimal first vector could be "blocked_internal_patch":

  1. an internal patch emits the same pre-effect class as a shell write;
  2. authority returns "BLOCK", bound to the exact tool, args digest, target refs, actor, and continuation;
  3. no mutation occurs;
  4. the block remains durably auditable after resume;
  5. resume preserves "trajectory_id" but creates a new "continuation_id";
  6. a model-visible warning alone cannot change the verdict.

This composes cleanly with the RAMR ↔ LS boundary we recently froze: reliability determines what state is recovered, while conformance determines whether this exact action may execute.

RAMR canonical fixture:

https://github.com/DanceNitra/ramr/blob/main/fixtures/ramr_ls/duplicate_successful_outcome.json

LS pinned verifier:

https://github.com/safal207/LS/blob/main/tools/run_ramr_ls_shared_evidence_fixture.py

The next concrete artifact can be a small vendor-neutral JSON Schema with three or four deterministic fixtures, without prescribing Codex’s internal hook implementation.

Boundary: architecture and test feedback only; no claim about using this project or running its code.

rpelevin · 26 days ago

That first vector is the right one. I would make the fixture fail unless all three axes are independently present and independently checked.

For blocked_internal_patch, the expected record shape should be explicit:

  1. Observation says a pre-effect action was proposed, with event identity, event type, trajectory id, continuation id, actor identity, parent lineage, subject, and target refs.
  2. Authority says BLOCK, with decision id, exact action binding, args digest, target refs, actor, continuation id, reason, and validity window.
  3. Visibility and durability say whether the model saw it, whether the user saw it, whether audit persisted it, whether it survives resume, and whether it survives compaction.

The verifier should reject if:

  1. any mutation occurs;
  2. a model-visible warning is treated as authorization;
  3. a post-effect or audit record appears without a matching pre-effect authority decision;
  4. resume reuses the same continuation id instead of creating a new continuation under the same trajectory;
  5. compaction drops active block state or reinjects stale enabled policy after the runtime is disabled or checks are off;
  6. a later approval changes any binding input without a new decision id.

I would keep recovered-state and orientation references out of the core fixture except as optional evidence provenance. The portable contract should stand alone: recovered state can explain what is known, but it cannot authorize the next action.

Boundary: architecture and test feedback only; no claim about using this project or running its code.

safal207 · 26 days ago

Thanks — agreed. The fixture should fail unless observation, authority, and visibility/durability are independently present and independently verified.

I’ll keep recovered-state and orientation references outside the portable core, as optional provenance only.

For "blocked_internal_patch", I’ll bind the pre-effect observation and BLOCK decision to the same actor, continuation, target refs, action digest, and decision identity, then add explicit rejection cases for:

  • mutation despite BLOCK;
  • warning treated as authority;
  • post-effect evidence without matching pre-effect decision;
  • stale continuation reuse after resume;
  • block state lost during compaction;
  • changed binding inputs under the same decision id.

The invariant stays narrow:

recovered knowledge may explain state
!= recovered knowledge authorizes action

That gives the fixture a cleaner vendor-neutral boundary.

safal207 · 25 days ago

The discussion now has a concrete implementation target:

  • observation, authority, and visibility_durability are independent and independently verified;
  • the first fixture is blocked_internal_patch;
  • recovered state is optional provenance and never execution authority;
  • changed action bindings require a new decision identity;
  • resume preserves trajectory identity but creates a new continuation identity.

The next useful contribution is a concrete vendor-neutral JSON Schema and deterministic fixtures rather than further abstract discussion.

Boundary: architecture and test feedback only; no claim about Codex adoption or implementation.

rpelevin · 25 days ago

For the first AgentHookEvent artifact, I would make the schema validate three independent blocks and make the verifier reject if one block is inferred from another.

Minimal shape:

{
"schema_version": "agent-hook-event/v0.1",
"fixture_id": "blocked_internal_patch",
"observation": {
"event_id": "evt-001",
"event_type": "PreToolUse",
"trajectory_id": "traj-001",
"continuation_id": "cont-001",
"actor_id": "agent-root",
"parent_actor_id": null,
"subject": {
"tool_family": "file_mutation",
"tool_name": "internal_patch",
"target_refs": ["src/example.py"],
"args_digest": "sha256:..."
}
},
"authority": {
"decision_id": "dec-001",
"status": "BLOCK",
"reason_code": "ACTIVE_CONSTRAINT_CONFLICT",
"binding": {
"actor_id": "agent-root",
"continuation_id": "cont-001",
"target_refs": ["src/example.py"],
"args_digest": "sha256:..."
},
"validity": {
"issued_at": "2026-06-25T00:00:00Z",
"expires_at": null
},
"execution_authorized": false
},
"visibility_durability": {
"model_visible": true,
"user_visible": true,
"audit_persisted": true,
"survives_resume": true,
"survives_compaction": true,
"transcript_visible": false
}
}

I would pin the first fixture set around that object:

  1. accept: blocked_internal_patch records observation, BLOCK authority, no mutation, and durable audit state;
  2. reject: model-visible warning is treated as execution authority;
  3. reject: post-effect or audit evidence appears without matching pre-effect authority;
  4. reject: resume reuses the same continuation id instead of preserving trajectory and creating a new continuation;
  5. reject: compaction drops active block state or reinjects stale enabled-policy state after checks are off;
  6. reject: later approval changes tool, args digest, target refs, actor, continuation id, or validity under the same decision id.

The verifier rule is simple: observation says what was proposed; authority says whether that exact action may proceed; visibility_durability says who sees it and what persists. Passing one block never satisfies another, and recovered context remains provenance only, never execution authority.

Boundary: architecture and test feedback only; no claim about Codex adoption, implementation, or running code.

safal207 · 25 days ago

@rpelevin Agreed — this is the right first artifact boundary.

I would make AgentHookEvent/v0.1 a conformance object with the three blocks required independently:

  • observation: what action/event was proposed, including event id/type, trajectory id, continuation id, actor, parent lineage, subject, target refs, tool/action, and args digest;
  • authority: whether that exact proposed action may proceed, including ALLOW | HOLD | BLOCK | RESUME, decision id, reason, exact binding fields, validity window, and policy refs;
  • visibility_durability: who saw the decision and what survives, including model-visible, user-visible, audit-persisted, survives-resume, survives-compaction, and evidence refs.

The verifier should reject whenever one axis is inferred from another rather than explicitly present. In particular:

  1. observation without authority never authorizes execution;
  2. authority without matching observation is not actionable;
  3. visibility without audit durability is not enough for resume/compaction safety;
  4. a later approval that changes tool, args digest, target refs, actor, continuation id, or validity under the same decision id is stale and must fail closed;
  5. recovered/orientation state can be evidence provenance only, never execution authority.

I can prepare a small vendor-neutral fixture pack around this shape: one valid blocked_internal_patch vector plus negative vectors for missing authority, inferred visibility, changed binding on resume, stale recovered policy after compaction, and post-effect audit being treated as retroactive authorization.

That keeps the first artifact testable across CLI/Desktop/IDE/plugin runtimes without requiring any claim about Codex internals or adoption.

Boundary: architecture and test feedback only; no claim about using this project or running its code.

rpelevin · 25 days ago

Yes. I would keep the first fixture pack small and make it prove axis independence rather than try to model every hook surface.

For AgentHookEvent/v0.1, the conformance rule I would want is:

  1. observation is required and only says what was proposed;
  2. authority is required and only says whether that exact proposal may proceed;
  3. visibility_durability is required and only says who saw it and what persists;
  4. no verifier may satisfy one block by inferring it from another block.

That gives the fixture pack a useful shape:

  1. accept blocked_internal_patch with a pre-effect observation, BLOCK authority, durable visibility, and no mutation;
  2. reject observation without authority;
  3. reject authority whose binding does not match the observed tool, args digest, target refs, actor, continuation, or validity;
  4. reject visibility without durable audit state when resume or compaction is involved;
  5. reject post-effect audit evidence treated as retroactive authorization;
  6. reject recovered or orientation state used as execution authority.

The important part is that the valid case should be boring and the negative cases should be impossible to hand-wave. A runtime can then implement hooks however it wants, but the portable artifact still proves the same invariant: proposed, authorized, visible, and durable are separate checks.

Boundary: architecture and test feedback only; no claim about Codex adoption, implementation, or running code.

safal207 · 25 days ago

@rpelevin Agreed. Keeping v0.1 small and making it prove axis independence is the right first boundary.

I also think the next useful extension point is temporal phase rather than more hook-surface breadth. The same observation / authority / visibility-durability fields should not be treated as timeless booleans: their force changes across the lifecycle of a trajectory.

So for the first fixture pack I would keep your shape exactly as-is, but leave room for a later phase-aware profile on top of it:

  • observation can remain durable after it stops being execution-actionable;
  • authority can be valid, resumed, stale, or expired while the underlying observation still remains auditable;
  • visibility may persist longer than authority;
  • recovered/orientation state may remain useful provenance after execution authority has ended.

Concretely, I would keep AgentHookEvent/v0.1 limited to the axis-independence vectors you outlined, then add a later temporal-phase fixture pack around the same contract surface: fresh authority, resumed authority, stale authority, expired-but-auditable authority, and revalidated authority.

That keeps v0.1 boring in the good way, while still giving the contract a clean path to model continuity over time instead of flattening everything into static booleans.

Boundary: architecture and test feedback only; no claim about Codex internals or adoption.

SaravananJaichandar · 20 days ago

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 · 19 days ago

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_helper and inject_helper Python 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.executable and 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.0

hoganfan · 7 days ago

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 · 8 hours ago

I’d like to propose a focused implementation of the missing PermissionDenied lifecycle 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 PermissionDenied as a first-class hook event.
  • Offer it only after an approval result is final and normalized.
  • Emit it for Denied, TimedOut, and Abort, plus non-allow network-policy amendment results.
  • Emit the generic event for every decision source and use decision_source as the matcher input:
  • auto_review
  • user
  • hook
  • 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 PermissionRequest contract.

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 doctor reports 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 PermissionDenied notification.
  • A full local just test run 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:

  1. Should the generic event be emitted for every final denial source, with source-specific behavior handled entirely by matchers?
  2. Are auto_review, user, and hook the desired external source labels?
  3. Should non-allow network amendments normalize to decision = "denied"?
  4. Should the first PR include the app-server/TUI/schema surfaces, or would you prefer a narrower staged landing?
  5. 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.

SaravananJaichandar · 47 minutes ago

world-model-mcp (OSS memory MCP) already ships a Codex adapter. The hook events it hard-depends on today are PostToolUse and UserPromptSubmit. 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. The content_type: rule | fact | procedure routing 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, and session_id is 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.