codex app-server harness. Every live Codex session runs through one path: a driver speaking the experimental codex app-server stdio JSON-RPC dialect feeds the shared ACP harness bridge, which writes into the session’s chat store. There is no PTY and no JSONL chat replay for Codex.
Requirements
Thecodex CLI must be installed and signed in (codex login). Continuum needs no separate token — the app-server authenticates from Codex’s own cached login. If the binary is missing or unusable you get a codex_not_found error with an “Install or repair Codex, then sign in with codex login” call to action; Settings → Providers → Codex can run npm install -g @openai/codex in an embedded terminal for you.
How a session runs
The daemon launchescodex with the app-server argument and handshakes over stdio JSON-RPC:
1
initialize
No ACP-style authenticate round-trip — Codex uses its cached login. The handshake advertises
experimentalApi so the v2 thread/turn dialect is available.2
thread/start
Creates a Codex thread. Continuum passes the per-session sandbox cwd, an approval policy, a sandbox mode, the model, and (when set) the reasoning-effort config override. The returned thread id becomes the session’s external id.
3
turn/start
Each prompt sends the thread id, the input, and the effort. The request resolves at turn acceptance; the turn’s end arrives later as a
turn/completed notification, so turn lifecycle is driven by the notification stream, not the request response.turn/interrupt. Mid-turn approval requests arrive as server-to-client approval calls that Continuum surfaces as permission prompts.
Sandbox and approvals
Codex permission posture is set atthread/start, not via a CLI flag, and it follows the composer’s two-state Plan ↔ Code pill:
Code sessions default to skip-approvals. Flipping the pill rebuilds the harness bridge with the new posture rather than restarting the CLI from scratch. When Codex is asking, its mid-turn approval requests render through the same permission-prompt card used across providers.
Plan approval
Codex has a real read-only Plan pole, and Continuum owns the “Approve & run” transition for it. Approving does the cheapest thing that works: if the agent is currently blocked on its own plan-exit request, Continuum answers that request with a code mode so it proceeds with edit access without tearing down the bridge — the turn keeps its momentum. Only when there’s no live pending approval (a plan captured before the bridge came up, or Codex’s synthetic plan seeded at spawn) does it fall back to a kill-and-respawn with edit access. Either way the session’s permission pill resolves to Code afterwards, on Mac and on iPhone.The
approve-plan endpoint returns 410 legacy_session_retired only for retired runtimes — legacy pane-backed sessions and the old chat-SDK path — not for Codex.Models and reasoning effort
The bundled catalog ships GPT-5.6 Sol, GPT-5.6 Terra, GPT-5.6 Luna, GPT-5.5, GPT-5.4, GPT-5.3 Codex Spark, GPT-5.3 Codex, and GPT-5.2 Codex. Sol is the default a fresh session resolves to. Codex has the widest effort ramp of any provider:minimal, low, medium, high, xhigh, and max are all accepted. There is no --reasoning-effort flag — Continuum sends the value as a model_reasoning_effort config override at thread/start and on each turn/start. The Claude-only Ultracode selection folds to xhigh for Codex at the spawn boundary, so an unsupported value never reaches the CLI.
Changing model or effort mid-session rebuilds the harness bridge; it is not a Claude-style respawn-and-resume.
Multi-account
A second Codex subscription is added in Settings → Providers → Add account…. Each non-primary account gets a deterministic config root, and the spawn environment setsCODEX_HOME to that root so the CLI’s auth, history, and settings resolve per account — config-directory isolation, not a HOME swap. Codex’s own codex login writes auth.json under that root. A session pinned to a removed account fails closed rather than silently billing the primary subscription.
Usage analytics and quota
Codex reports rate-limit state in two places, and Continuum reads both. The live gauge preferschatgpt.com/backend-api/wham/usage, the account-wide view Codex Desktop’s “Usage remaining” menu shows, and falls back to the rate_limits payload embedded in local session files when that call fails (offline, expired token, endpoint change). The two can diverge sharply: the local files carry the per-CLI bucket, while the account-wide window also counts your ChatGPT chat usage. Each bucket exposes a 5-hour rolling window and a 7-day weekly window.
Historical analytics are separate from both. Continuum parses ~/.codex/sessions/**/*.jsonl for token-count events, each carrying a cumulative usage snapshot. The parser subtracts the previous cumulative to produce per-turn deltas; a non-monotonic drop (a session reset mid-file) is treated as a fresh baseline rather than emitted as a negative delta. Deltas are priced with the embedded pricing snapshot.
Transcript resolution and respawn lineage
Live Codex chat doesn’t replay JSONL while streaming, but Continuum still maps each session to its on-disk Codex rollout for history and search hydration, file-citation scanning, and the cold-miss snapshot reparse. The resolver tracks respawn lineage so a session never strands on the wrong rollout: it returns the cached rollout if still valid, otherwise scans~/.codex/sessions/ for the newest rollout inside the session’s activity window, and an explicit spawn or invalidation can seed or force a rescan.
The scan is cwd-hardened: a candidate rollout’s own recorded working directory must match the session’s, so a sibling Codex rollout — a Spawn-mode tile, or any codex you launched in a terminal — can’t silently re-point a live session’s transcript at a different conversation. Legacy rollouts with no metadata line stay accepted for back-compat; a file still mid-creation is never selected, and is re-probed once its metadata line lands.
Chat rendering
Live Codex chat renders from the app-server event stream. The mapper normalizes the v2 thread/turn dialect into provider-neutral events:- assistant message deltas and whole messages, with commentary vs. final-answer phase metadata;
- reasoning deltas, rendered as collapsible “Thinking” rows rather than chat bubbles;
- tool and command runs with status, output, and exit code;
- proposed file edits with per-file unified diffs;
- plan and step checklists;
- approval requests, surfaced as permission prompts.
Broadcast
Codex can participate in the Chat surface’s multi-provider broadcast mode — one prompt to several providers, answers side by side.The Chat tab is hidden by default across every client while the product is focused on Code, so broadcast is not reachable from the default UI. See Chat.