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
- Spike: hand-write one
Stop hook against a live Codex pane, confirm it fires and capture the payload. Nothing else until this lands.
- If it holds: extend
lifecycleIntegrations to install a Codex hook bridge next to the notify bridge, keeping notify for older Codex versions.
- 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
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
notifybridge (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·Stopwith 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:
[hooks]entry in~/.codex/config.toml, and does it accept a command the way Claude'ssettings.jsondoes?Stopa real turn boundary or a session-level signal?Suggested order
Stophook against a live Codex pane, confirm it fires and capture the payload. Nothing else until this lands.lifecycleIntegrationsto install a Codex hook bridge next to the notify bridge, keeping notify for older Codex versions.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