Skip to content

Codex has lifecycle hooks now — verify, then stop guessing at Codex turn state #1107

Description

@openwong2kim

The gap

For a Claude Code pane, wmux knows what happened because the hook bridge tells it: turn ended, permission prompt raised, subagent activity. For a Codex pane it does not. The only thing wmux installs into Codex is the notify bridge (registerCodexNotify, src/shared/configIO.ts), which is effectively a single completion ping. Everything else — turn boundaries, approval prompts, subagent starts — falls back to reading the screen: regex detection plus the byte-rate promotion from #935.

That fallback is why completion detection on Codex panes is a heuristic with tuned thresholds instead of a fact.

What changed upstream

codex-cli 0.149.1 ships lifecycle hooks that look structurally like Claude Code's. Observed event names in the binary:

PreToolUse · PostToolUse · Notification · UserPromptSubmit · SessionStart · SessionEnd · PreCompact · PostCompact · SubagentStart · SubagentStop · Stop

with matching UI copy for each ("Before a tool executes", "When permission is requested", "After a tool executes", "Before/After context compaction", "When a new session starts", "Right before a session ends", "When the user submits a prompt", "When a subagent is created", "Right before a subagent ends its turn", "Right before Codex ends its turn"). The payload field names match too — hook_event_name, stop_hook_active, permission_mode, tool_name, tool_input, agent_transcript_path, last_assistant_message.

There is also a trust model around them: [hooks] in config.toml, plugin_hooks, allow_managed_hooks, and a review UI ("New hook - review required" / "Modified since last trusted" / "Managed hooks are always on"). Sources are enumerated as Admin config, User config, Project config, Session flags, Cloud-managed config.

If those behave the way the names suggest, the Codex side of completion detection stops being a guess.

This is not verified yet

The above is binary string inspection, not a working hook. This repo has been wrong before by reading a competitor's surface and declaring a gap, so nothing here gets promoted to a track until someone actually installs a hook against a live Codex session and watches it fire. Blocking questions:

  • What is the on-disk shape of a [hooks] entry in ~/.codex/config.toml, and does it accept a command the way Claude's settings.json does?
  • What exactly arrives on stdin per event, and is Stop a real turn boundary or a session-level signal?
  • What does the trust flow demand of a programmatic installer? "New hook - review required" implies wmux writing a hook is not enough on its own — the operator may have to approve it, which changes the install UX and possibly rules out silent reconciliation.
  • Does any of it work on Windows, which is the platform wmux ships on?

Suggested order

  1. Spike: hand-write one Stop hook against a live Codex pane, confirm it fires and capture the payload. Nothing else until this lands.
  2. If it holds: extend lifecycleIntegrations to install a Codex hook bridge next to the notify bridge, keeping notify for older Codex versions.
  3. Fold Codex panes onto the same signal path Claude panes use, and let the screen heuristic become the fallback rather than the primary.

Note the version floor: hooks are in 0.149.1 and were not always there, so any install path needs a capability check rather than assuming the local Codex has them.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important — should fix sooncodexenhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions