Docs · Codex
Run Codex on your company's accounts
One command instead of codex, and every argument passes through. Same keys,
same limits, same Usage and Logs as everything else. For how the pieces fit together,
start at the docs.
Get started
Before you start
Codex is a prerequisite. Selan launches it; it does not bundle it. Without it on your
PATH you get:
codex not found on PATH; install Codex CLI from https://developers.openai.com/codex
You also need the selan binary and a session. If you have neither yet, both
are two commands: see Install and
Sign in. Nothing about signing in is Codex-specific — one
session serves every client.
A ChatGPT subscription is not required to run Codex through Selan. It is required for one thing only: the model picker. Codex only asks for a model list while it is signed in to ChatGPT.
Run it
selan codex
That is the whole change: selan codex instead of codex. Every
argument passes through verbatim, so anything you ran before still runs — flags,
subcommands, codex exec, all of it.
Codex then talks to your company's gateway rather than your own ChatGPT account. Your requests spend against whatever provider keys an owner connected, show up as you in Usage, and appear in Logs with the model that served them.
What Selan writes to your config
The first time you run it, Selan adds a provider block to
~/.codex/config.toml and tells you it did:
note: wrote selan's provider block to /Users/you/.codex/config.toml
Said once, and only when something changed — not on every launch. This is what lands:
# >>> selan managed — do not edit, `selan codex` rewrites this block >>>
[model_providers.selan]
name = "Selan"
base_url = "https://cxgw.selan.ai/v1"
wire_api = "responses"
request_max_retries = 1
stream_max_retries = 2
env_http_headers = { "x-selan-model" = "SELAN_MODEL", "x-selan-repo" = "SELAN_REPO" }
env_key = "SELAN_CODEX_TOKEN"
env_key_instructions = "Run `selan codex` — it exports this for the session."
# <<< selan managed <<<
- Only the block between the markers is ours. The rest of your config is left alone: your own providers, profiles and settings stay exactly as you wrote them.
- Do not edit inside the markers.
selan codexrewrites the block whenever it changes — a new gateway URL, say — and your edit goes with it. - The credential is not in the file.
env_keynames a variable, andselan codexexports it for that launch and no longer. - A bare
codexfails closed. Run Codex by hand and the variable is not set, so it stops rather than quietly spending your company's account. That is deliberate, and it is why the block names a variable instead of a command.
On the dev channel the block is [model_providers.selan-dev] and sits beside the
production one. Both can live in the same file.
Choosing a model
Your company's models in the picker
Type /model in Codex and your company's own models are in the list, in place
of the built-in one. Pick one the way you pick any other, with no flag to pass.
| > | 1. | GPT-5.6 Sol |
| 2. | GPT-5.6 Terra | |
| 3. | Kimi K3 · From gateway | |
| 4. | DeepSeek V4 Flash · From gateway |
A pick means the model, not one provider's copy of it. If your company has the same model on more than one account, choosing it here leases them in the order an owner set, so a provider that is out of quota falls through to the next instead of failing the request.
While Codex is signed in to ChatGPT, selan codex also starts on the first model
in that list rather than leaving the choice to each request.
--model instead.
The picker itself is not a setting any more — but models are still switched on one at a
time, so a model an owner has not turned on is in neither list.
If a model you expected is not there
- Quit and relaunch first. The list is fetched at startup and cached for five minutes, so a model switched on while you were working shows up on the next start, not when you reopen
/model. - Check it can reach Codex at all. Some models your company has switched on cannot appear here, whatever anyone toggles. See which models can appear.
- Then ask an owner to switch it on. Models are off until someone turns them on, one at a time. Connecting a provider key does not put anything in anyone's picker by itself.
Want a model your company has not curated, or one the picker cannot carry? Name it directly — see naming a model.
Which models can appear
Codex speaks one protocol, the one named on the wire_api line
in the block above. A model reaches Codex only if the provider serving
it speaks that protocol too — so a model can be switched on, be perfectly usable in Claude
Code, and still never appear here.
| Provider | In Codex |
|---|---|
| OpenAI — subscription or API key | Yes. Shown unmarked, since these are Codex's own models. |
| OpenRouter | Yes, marked From gateway. |
| nexos.ai | Yes for most of its catalogue — but not its Claude models, which it serves on the other protocol. |
| Ollama | No. Everything it serves is on the other protocol. |
| Vertex AI | No, and not in Claude Code's picker either. A Vertex key still works on the paths that name no model. |
Every one of these but Vertex reaches Claude Code, which is why a list that looks short here is usually this rule rather than a missing switch. Nothing is silently degraded: a model that cannot serve Codex is left out of the list instead of being offered and then refused.
Naming a model directly
You do not need the picker to choose. Name a model on the command line and Codex starts on it:
selan codex --model openrouter:moonshotai/kimi-k3
The shape of the name decides how far Selan will go to serve it:
- With a provider in front —
openrouter:moonshotai/kimi-k3— it runs on that provider and no other. If that account is out of quota, the request fails rather than moving. - Without one —
gpt-5.6-sol— it means the model itself, and Selan leases your company's accounts for it in the order an owner set, falling through on failure. This is what a pick in the picker does.
Either way the model has to be one your company connected. This path skips the curated list, not the provider keys.
Going further
Running without approval prompts
seland is the same binary under a second name, and it launches Codex with its
approval prompts off after one enter to confirm:
seland codex
--dangerously-bypass-approvals-and-sandbox, which is its flag and its
consequences, not ours.
For the same thing in Claude Code, and for the cases where running unattended is the point
— CI, containers, cron — see seland and
Running unattended. The token and environment variables described
there work the same for Codex.
What differs from Claude Code
Most of the main docs applies to both. These are the parts that do not:
- No statusline. The spend and headroom line Selan installs is Claude Code's. Run
selan usagefor the same numbers. - No context limit, and no
--autocompact. The window your company sets is applied by Claude Code when it compacts a conversation. Codex manages its own context and Selan does not touch it. - No 1M-context variant. Claude Code's picker offers some models twice, at 200k and at 1M. Codex gets each model once, at the window its provider reports.
Everything else carries across: the same session, the same spend limits, the same secret scanning before a request leaves your machine, the same Logs, and repository attribution when you run inside a git checkout.
If it did not work
codex not found on PATH— Codex itself is not installed. Install it, then runselan codexagain.- The picker shows OpenAI's built-in list. Codex is not signed in to ChatGPT, so it never asked for one. See the note above — naming a model still works.
- A model is missing from the list. Relaunch first, then check it can reach Codex at all, then ask an owner to switch it on.
- Codex starts on the wrong model. While Codex is signed in to ChatGPT, an unnamed launch starts on the first row of the list. Name one with
--modelto override it for that session. - A bare
codexrefuses to start. That is the design — the credential only exists for the length of aselan codexlaunch. Run it through Selan. - Something else. The error messages are collected in Reference, and you can always ask us.