Codex provider (OpenAI CLI-backed sessions)
Codex is OpenAI's own CLI coding agent, and Omniscio can run sessions on it instead of Claude. This page covers what a Codex session looks like, how to switch Codex on, how to sign in with a ChatGPT plan or an API key, and how Codex sessions behave alongside Claude ones.
What it is
Codex is OpenAI's CLI agent — a coding agent in the same shape as Claude Code, but driven by OpenAI models and shipped as the codex binary. Omniscio supports spawning Claude-Code-style sessions backed by Codex as one of several alternative providers, alongside claude (the default) and the other registry providers (Gemini, Antigravity, DeepSeek, Kimi, Cursor, Hermes, Pi, …). From the user's perspective a Codex session looks identical to a Claude session: same sidebar, same streaming bubbles, same Ctrl+Enter to send, same archive / pause / snooze. The only visible signal that it's NOT Claude is the small Codex icon (the OpenAI "flower" logo, no text label) next to the session title in the header — the mark tells you which engine is running, and every started session shows its engine mark (Claude included, in brand orange), so a Codex session's mark is the OpenAI flower. The per-launch provider dropdown shows the same logo next to each provider's row. Unlike the other providers' marks — which render in their brand colors (Claude orange, Gemini's blue→purple→pink gradient, Anti-Gravity blue) — the OpenAI flower stays adaptive monochrome: OpenAI's logo has no official color version, so it inherits the surrounding text color (dark on light backgrounds, light on dark).
Codex is opt-in and off by default. Two readiness gates must be green before the Codex row is offered (see How to enable): the Allow Codex sessions toggle and the Codex CLI binary. An OpenAI API key is NOT a gate — it's optional (Codex authenticates via your own codex login when no key is set; see below). When a readiness gate is red, the per-launch ChangeProviderButton (on a fresh session header) and the per-project Default-provider radios (Edit Project dialog) show the Codex row as aria-disabled with a "Set up…" / "Install…" suffix; clicking the row deep-links you to the right Settings panel instead of trying to spawn.
Where to find it
Crossing over to Codex is not a separate app to install and learn: it is a choice of engine, made in the same places you already choose one. Its Settings → Accounts → Codex panel is where the sign-in and the optional API key live, and the account pill at the lower-left of the window mirrors the same Codex logins in a lighter form. Once it is switched on, a Codex session is an ordinary row in the left sidebar — the same transcript, the same statuses, the same Ctrl+Enter — and the only visible difference is a small OpenAI flower next to the session title in the header.
The choice of which engine a session uses is offered in three places: on a brand-new session, where a provider picker sits above the message box; in a project's Edit dialog, where a project can be given a default engine for every session it starts; and, for anything created programmatically, wherever a session is created with Codex named. If Codex is not ready when you ask for it — the toggle is off or the program is not installed — the picker row is greyed out and clicking it takes you straight to the settings panel that fixes it.
How it behaves
How to enable
Master toggle required first. Codex and Gemini are alternative providers — by default Omniscio ships as a Claude-only product, and the entire Codex setup section below is hidden in Settings → Accounts. Flip Settings → Accounts → Show alternative AI providers to ON and the Codex panel appears. With the master off, the per-project "Default provider" radio collapses to a single Claude row and the session header's provider switcher (ChangeProviderButton) is hidden — Codex effectively does not exist in the UI even if every gate below is configured. Your saved API key, "Allow Codex sessions" toggle, and per-project defaults are preserved across master-toggle flips.
You need these in place:
- Codex CLI binary — must be present on PATH or installable from the same Settings panel. Click the Install Codex CLI button to run
npm install -g @openai/codex(or your platform equivalent); the panel polls for version and shows a green "Installed (vX.Y)" status when ready. - Settings → Account → Allow Codex sessions toggle — off by default. A small extra step so Codex isn't spawnable until you opt in.
- Auth — sign in to Codex, OR (optionally) paste a key. Omniscio no longer requires an OpenAI API key. If you've run
codex login(Sign in with ChatGPT), Omniscio uses that login automatically — no key needed, and Codex usage counts against your ChatGPT plan. You don't have to find a terminal yourself: once the Codex CLI is installed, Settings → Accounts → Codex shows a one-click Sign in with ChatGPT button that runs a NON-terminal, in-app browser sign-in: Omniscio opens your default browser to OpenAI, catches the redirect on a local loopback, and writes the Codex login file (~/.codex/auth.json) itself, flipping to "Signed in to Codex" the moment it completes — no terminal window. Prefer the old flow (or you're on Linux, where the browser sign-in isn't offered)? A "Use the terminal login instead" link beneath it opens a real terminal and runscodex loginin it — complete the sign-in there, then return (that terminal path can't flip to "signed in" the instant you finish, so re-open Settings to confirm). Alternatively, paste ansk-...key in Settings → Account → Codex → API key (stored encrypted viasafeStorage, sent to the CLI as an env var, never to the renderer); a pasted key is OPTIONAL and, when present, overrides the CLI login (billing then goes to that API account). Omniscio also strips any strayOPENAI_API_KEYfrom your shell so it can't silently bill an API account. With neither a key nor acodex login, starting a Codex session shows a plain "runcodex login, or add a key" message rather than spawning a wedged session. See cli-login-auth-contract.md. You can also start this sign-in during first-run onboarding: if you pick Codex on the Setup v2 "Which AI agent do you use most?" step, an optional "Sign in with Codex" button runs the same in-app browser sign-in right there (installing the Codex CLI first if needed), with a "use the terminal login instead" fallback link, so you can connect your ChatGPT account during setup instead of finding Settings later.
Once the binary + toggle are green (and you're signed in or have a key), you can launch a Codex session in three ways:
- Per-launch override — on a fresh (zero-message) session, the ChangeProviderButton in the new session's main panel (the launch-config pickers on a fresh session) lets you pick a one-off provider before sending the first message. Non-ready providers appear
aria-disabledwith a "Set up…" / "Install…" / "Add key…" suffix and deep-link to Settings. - Per-project default — Edit Project dialog (three-dot menu → Edit) has a "Default provider" section with one radio per
pickableregistry provider (Claude / Codex / Gemini / Antigravity / DeepSeek and the rest of the pickable set — 20 today, inpickerOrder; the set grows automatically as new providers ship). Pick Codex and the project's sidebar "+ New Session" button spawns Codex automatically. - Programmatically — anything that creates a session with
provider: 'codex'(recipes, agent-driven sessions, the API). Same readiness gates apply on the backend.
How sessions look different
- Codex icon in the header — the Codex mark next to the session title (no text label; OpenAI's mark is monochrome, so it adapts to light/dark). Every started session shows its engine mark now (Claude included). Hovering reveals "Codex."
- Omniscio behavior conventions ride as standing developer instructions (2026-08-14) — on Codex CLI versions that support
developerInstructions, Omniscio sends the shared engine prompt bundle through Codex's real standing instruction channel instead of only burying it in the first user message. That bundle now includes the standard/custom response-format block, the QuestionWidget/asking rules, the Plain Speak/final marker reminders, and the portable Dev Pipeline workflow when the pipeline is active. Clean Room still strips the response-format and QuestionWidget guidance. - Resumes by context-replay, not native rehydration (2026-06-10) — Codex sessions run via a child process per session; if Omniscio quits (or the child dies), the process is gone and Codex has no on-disk transcript to
claude --resumefrom. Instead, sending a new message to a stopped Codex session re-spawns Codex, opens a fresh thread, and replays Omniscio's stored conversation as context on that first message, so you continue where you left off — the same seamless resume OpenClaw and Pi use. (Multi-turn during a live session is native — the same process handles every turn, no replay needed.) Earlier this was a dead end ("the old context is gone"); now it isn't. - A stalled Codex session shows "Continue" and resumes (2026-06-10) — the orange "stopped responding" alert now offers Continue like Claude; clicking it re-spawns Codex and replays your conversation (above), so you pick up where you left off. (Earlier it showed a [ Start a new session ] dead-end, because Codex couldn't resume.) The honest "This Codex session is no longer running. Start a new session to continue." error now fires ONLY when the re-spawn itself genuinely fails (e.g. the binary or key is gone) — not merely because the child died. Codex sessions are also never swept by Anthropic rate-limit recovery (they don't run on your Anthropic account). See stalled-session.md and the codex-rate-limit-rebalance-wedge contract.
- Full execution access + real approval prompts (Claude parity, 2026-06-06) — Codex runs unsandboxed (
sandbox_mode=danger-full-access) at every level except the project-sandbox one below, so the agent has the same freedom a Claude agent does: it can run git, create its own worktree, and edit files wherever Claude could. Before this it ran in Codex's defaultworkspace-writesandbox, which silently blocked every.git/write — the agent could edit files but couldn't run a single git command. It now also asks before non-trusted commands (approval_policy=untrusted): a shell-command or file-change request pauses the session, marks it Needs You, and shows an Allow / Deny prompt in the SAME permission pane Claude uses; your decision is sent back over the protocol, and anything that goes wrong fails closed (denies). Since 2026-09-23 the level follows your Agent Permission Level by default — Read-only/Guarded → ask before every command, Autonomous → the project sandbox with internet access, Full trust → never ask — so choosing Autonomous no longer leaves Codex prompting on every command. Settings → Accounts → Codex permission level defaults to Follow Agent Permission Level; an upgrade moves an install still on the old default (Ask before every command) to it once and keeps any other level picked on purpose. The other three options override the level for Codex only: Ask before every command = full machine access + ask every time, exactly like Claude; Ask only when it reaches outside the project runs Codex restricted to the project folder (sandboxworkspace-write) and prompts only when it needs to escalate — including any command that needs the internet, since that sandbox has no network (npm install,git push); Allow all lets Codex run everything with full access and never asks. (Codex'son-failurepolicy is deliberately NOT offered — its sandbox isn't enforced on Windows, so it would never prompt: a dead option.) (A 2026-06-07 fix made these prompts work at all: Codex numbers its JSON-RPC approval requests and Omniscio had been dropping the numeric-id ones, which silently hung the whole turn — see codex-approval-numeric-id-routing postmortem.) Both knobs also have env kill switches (AMC_CODEX_SANDBOX_MODE,AMC_CODEX_APPROVAL_POLICY). Contract: provider-registry-contract.md. - Per-session cost / token counters — the Codex app-server protocol reports usage events; Omniscio translates them into the same
cost_usd/tokens_in/tokens_outcolumns it uses for Claude, so the Stats virtual project rolls them up the same way. - Plan usage + token totals in the account pill (2026-06-11) — the lower-left account popover's "Codex usage" section (on its Codex tab since 2026-06-26 — previously the Claude view) shows your ChatGPT-plan remaining usage (% used + reset for the ~5-hour and weekly windows, the same
MiniUsageBarClaude's account rows use) plus tokens used over 24h / 7d / 30d. The plan bars ride in free on Codex'saccount/rateLimits/updatedpush as sessions run (no extra request, no token cost) and are absent under an OpenAI API key (no plan window); tokens are shown but never a$(no OpenAI pricing table). See account-indicator.md § Codex usage section and provider-registry-contract.md. - Tool activity folds like Claude's — when a Codex turn runs shell commands, edits files, calls MCP tools, or searches the web, each action surfaces as the same collapsed
▸ call/← resultactivity marker Claude uses (e.g.▸ Shell: npm test→← exit 0;▸ Edit: src/foo.ts→← 1 file changed). Because those markers exist, the real-conversation layout folds the turn's pre-final narration into a compact "N actions" activity summary exactly the way it folds Claude's: only the turn's final answer renders as full prose, and the intermediate "Let me check…" / "Now I'll…" narration collapses into the expandable activity block. Before this, a multi-step Codex turn rendered as one long blob — every narration paragraph plus the answer, with no fold. (Reasoning and plan items are deliberately NOT turned into markers — they're prose, not actions. Context-compaction is not a marker either, but it is not noise: it gets its own divider — see Compaction below.) - Compactions are visible, like Claude's (2026-09-10) — when a long Codex session fills its context window, Codex rewrites the whole history into a summary. That rewrite can take a full minute, and it used to leave no trace at all in the transcript: the turn simply went quiet and older context silently stopped existing. Now it shows the same two things a Claude compaction shows — a pulsing “Compacting conversation…” pill while the rewrite runs, then a settled “Conversation compacted” divider (with the pre-compaction token count when Codex reported one) at the point in the feed where it happened. The one difference: the divider has no “Show summary” button. That button reads the summary back out of the Claude CLI's on-disk transcript, and Codex keeps no such file — so rather than offer a button whose only possible answer is “unavailable”, the divider hides it. See compaction-summary.md.
- A helper agent's words are labelled as the helper's, not the session's (2026-09-03) — Codex can spawn its own helper agents for a task and runs them all over one connection. Omniscio used to drop the tag saying which agent a message came from, so a helper's write-up appeared as the session's own reply — and, worse, a helper finishing its answer could suppress the session's real one. One session's whole visible turn was a helper signing off with "I sent both findings to the parent agent", which reads as that session having messaged another session; nothing had been sent anywhere, and its own reply was missing. Now a helper's write-up lands as its own labelled sub-agent row, a helper finishing no longer ends your turn, and the helper's tool activity still shows in the main activity fold (it is activity, not speech). The delegation marker also names what was handed off instead of repeating an opaque
Agent: wait— one real session showed thirteen identical ones and nothing else. Contract: codex-robustness-contract.md (sub-agent-prose-is-not-the-session-voice). - Image & document attachments (2026-06-07) — attach images and documents to a Codex message just like Claude. Images go to Codex as native image input — each is saved into the project workdir and passed by file path (
localImage), not as inline bytes over the protocol pipe. Documents (PDF / Word / Excel / PowerPoint / plain-text) are saved into the project and their paths are injected into the prompt so Codex opens them with its file tools (Office files are auto-extracted to text first). Caveat vs Claude: Codex reads text-based PDFs, but cannot "see" scanned / image-only PDF pages the way Claude's vision can. Nothing is silently dropped — every attachment shows as a chip in the transcript, and a file that can't be read surfaces an in-chat warning instead of vanishing. Contract: provider-registry-contract.md §7.
Everything else — archive, snooze, pause, send-later, search, the inbox, auto-generated session titles, plain view, plain speak overlay, question widgets — works the same as a Claude session. Title generation in particular is provider-agnostic: the first operator message in any Codex session triggers the same titleOrchestrator.maybeGenerate() call that runs for Claude / Gemini / OpenClaw, so the "Session 2,702" placeholder gets rewritten to a real title within a few seconds regardless of which provider answered.
Error states and fixes
The same readiness probe powers the ChangeProviderButton row, the per-project Default-provider radios, the project-row "!" badge, and the backend spawn guard. Readiness no longer includes an API-key gate (the key is optional — see How to enable), so there are two gap codes:
| Gap | What it means | Click-to-fix lands you at… |
|---|---|---|
toggle-off |
"Allow Codex sessions" is OFF in Settings | Settings → Account → Allow Codex sessions toggle |
binary-missing |
codex CLI not on PATH |
Settings → Account → Codex CLI binary panel |
Auth (a codex login session or a pasted key) is NOT a readiness gate — it's checked when the session actually starts. With neither, the session surfaces a plain "run codex login, or add a key" message instead of a key-missing picker suffix — and says the conversation is saved, so after signing in you just send a message in the same chat.
Detection survives a slow cold-start. binary-missing confirms the CLI via a --version probe (5 s budget); under heavy app load that probe can be killed before it answers, so detection falls back to the CLI's presence on disk at a known install dir (npm-global / well-known paths). An installed-but-slow Codex CLI therefore never false-flags as missing, and a successful detection is cached so the check stops re-probing. See provider-registry-contract.md (a-cold-start-probe-does-not-report-a-present-binary-missing).
If a Codex spawn fails after the gates were green (network blip, stale key, model rejected the prompt), the session lands in error status with the failure message in the header — same UX as a failing Claude session. There is no auto-retry; sending a new message re-spawns Codex and replays your conversation (so an errored-but-recoverable session resumes), or you can archive and start fresh.
Outdated Codex CLI → one-click update. If a turn fails because your chosen model needs a newer Codex than the one you have installed (e.g. "The 'gpt-5.6-luna' model requires a newer version of Codex. Please upgrade…"), the paused chat row now carries an Update Codex CLI button. It deep-links to Settings → Account → Codex CLI binary, whose button now doubles as an updater when Codex is already installed — one click re-runs the idempotent npm install -g @openai/codex to pull the latest, then you re-send. That replaces the old dead-end where the message just told you to "re-send to try again" against a CLI that would keep rejecting the model. (This does NOT auto-switch your model — you picked it deliberately, so the fix is to update the CLI.) Locked by codex-robustness-contract.md (outdated-cli-offers-update).
Archive cleanly when the child is mid-turn. Archiving (or pausing) a Codex session that's still running terminates the JSON-RPC child via codexSessionManager.terminate() before the archive UPDATE lands in the database — there is no race where the child fires a "needs you" status push after the row is archived and resurrects the session in the sidebar. There is also a defense-in-depth guard inside codex-session-manager.updateStatus: any incoming status change is dropped if the database row already reads archived or paused, so orchestration-engine / action-dispatcher / direct-DB archive paths that bypass terminate() are still safe. Symptom of the original bug, since fixed: "It won't let me archive this session — it stays permanently there till something happens that immediately comes back." If you ever see this on Codex again, the regression is one of those two layers.
Robustness under stress (2026-06-15). Several failure modes that used to wedge a Codex session are now handled cleanly: a turn the model rejects (usage limit, server error) shows as a red error with any partial reply kept — it no longer looks like a silent empty answer and it doesn't count toward your usage; a turn that runs away (loops past a size/time cap) stops on its own with the partial kept and a clear note, instead of only an app-close stopping it; Restart now resumes the session with its full conversation context (it used to come back looking brand-new); and if Codex asks for two approvals at once, both are queued and shown one at a time instead of the second silently replacing — and stranding — the first. A long pause while Codex waits on your approval no longer trips the stall watchdog, and non-English / emoji output is no longer occasionally garbled by a split stream frame. And if your chosen model isn't available on your account type — e.g. a code-tuned Codex model (gpt-5.3-codex / gpt-5-codex) that needs API-key billing while you're signed in with a ChatGPT plan (which can't run ANY *-codex model — OpenAI 400s them) — Omniscio automatically switches the session to a compatible general model (GPT-5.5), tells you in a chat note, and re-runs your message once, instead of dead-ending with a cryptic "turn ended without completing" (loop-guarded, so it never switches in circles). New ChatGPT-plan sessions also start on GPT-5.6 by default, so they don't hit this at all. And when OpenAI answers "Selected model is at capacity" (its servers are busy — nothing to do with your quota), the session no longer goes red and waits for you to re-send: it shows the ember waiting state with a note naming the busy servers, re-sends on its own about five minutes later, and keeps retrying for roughly two hours before it gives up and asks you (2026-09-30). Full invariants + the tests that lock them: codex-robustness-contract.md.
- A wedged-but-running turn auto-restarts instead of dead-ending (2026-08-06). When the stall / turn-cap watchdog force-recover fires on a Codex session that is still
running(e.g. one turn ran past the 4-hour cap because its commands kept timing out under load), Omniscio now tears down the stuck app-server and re-runs your last message on a fresh one — you see "Codex appeared stuck — restarting…" instead of the terminal "Codex stopped responding and couldn't recover. Start a new session to continue." It retries up to 2 times by default (AMC_CODEX_STALL_RECOVERY_MAX); only if the turn is genuinely stuck does the honest terminal error still run. Full invariants + the tests that lock them: codex-robustness-contract.md.
Your Codex accounts survive a data-folder move. Each managed Codex account keeps its sign-in in its own private folder inside Omniscio's app data. If that app-data folder is ever renamed or moved, Omniscio re-points each account to its new location the next time it starts, so an account does not silently read as signed-out and can still be removed. Before this, an account stranded that way refused to be removed at all and behaved as though it had never been signed in. Implementation detail and the safety rules that constrain it live in provider-registry-engines-core-codex-persistent-external-contract.md (CX-32).
Related
Codex is one of several alternative engines Omniscio can run sessions on: Gemini uses the same launcher, readiness check and per-project default with a different binary and credential, and OpenClaw is the remote-gateway alternative. Claude itself needs no toggle at all — its setup is on the Claude accounts page — and what happens when a session stops responding is on the stalled session page.
This page is split across three parts: part 2 covers the managed Codex accounts, the per-project default and the model and reasoning-effort chips, and part 3 covers what actually runs when a Codex session starts, and the files involved.
- codex-robustness-contract.md — turn-lifecycle robustness invariants (failed-turn honesty, runaway cap, frame/decoder safety, approval-hang + concurrent-approval queue, busy-guard, restart-resume, account integrity) + the tests that lock them
- gemini-provider.md — same launcher / readiness / per-project-default model, different binary + credential
- openclaw-provider.md — separate "alternative provider" model (remote WebSocket gateway, not a local CLI)
- add-a-claude-account.md — Claude account setup (the default provider; no toggle needed)
Last verified 2026-10-06