Coding agents expose no cross-vendor way to observe their state from outside the process, so a tmux status line has to consume each agent’s own hook system. ACP defines a session/request_permission method, but it is only visible to the editor that spawned the agent over stdio, which is the wrong layer for an outside observer. What converged instead was Claude Code’s hook event vocabulary, copied by imitation rather than specification: Codex 0.145.0 ships preToolUse, permissionRequest, postToolUse, sessionStart, sessionEnd, userPromptSubmit, and stop in ~/.codex/hooks.json, the same set under a camelCase skin.
The reusable structure underneath is that waiting is two states, not one. Blocked means a decision is required right now: Claude Code’s permission_prompt, elicitation_dialog, and agent_needs_input, or Codex’s permissionRequest. Idle means the turn ended and the agent is merely available: Claude’s idle_prompt (which fires only after 60 seconds), Codex’s stop, pi’s agent_settled. A picker should sort blocked panes first, since only those are costing wall-clock.
The convergence is partial, and how far an agent falls short is the thing to check first. Antigravity CLI 1.1.8 has only five events (docs): PreToolUse, PostToolUse, PreInvocation, PostInvocation, Stop. No permission event, so it can never report blocked, and no session-start event, so a launched-but-unprompted pane publishes nothing at all and has to be found by process name instead. pi has the opposite shape: no permission event either, but a real session_start.
Two traps. Turn-end is not settlement: pi documents that agent_end may be followed by auto-retry, auto-compaction, or queued follow-ups, and directs status integrations to agent_settled instead, while Claude’s Stop hook can exit 2 and force the turn onward. And Claude’s Notification event covers eight types, of which auth_success, elicitation_complete, and agent_completed are not waits at all, so matching bare Notification over-reports. Discriminate with matchers, not with the bell. See Claude Code Terminal Notification System and Antigravity Hooks Take the Event as a Key.
Blocked also needs an edge that retires it, and no agent supplies one. Answering a permission prompt fires no event of its own, and Claude Code documents that Stop does not run when a turn ends in a user interrupt, so a blocked tag outlives the block it describes: for the rest of the turn in the first case, indefinitely in the second. Two of the three exits from a block are silent. Nothing purely edge-triggered can recover from that, so the consumer needs a level-triggered signal to reconcile against. The nearest thing that works is screen presence, since a pane you are looking at is not waiting on you whatever it last published. PostToolUse covers the first case from the hook side, but only for agents that expose it.