config.toml. Codex keeps speaking the OpenAI Responses API and you keep picking your model; the gateway maps whatever it sends to the target your routing resolves to. See Set up ValarCode for the shared setup and the client-id model.
Prerequisites
- The OpenAI Codex CLI installed, with a
~/.codexconfig directory. Run Codex once so the directory exists. - A Valar coding key (
vlrcode_…) and thevalarCLI (install).
Enable routing
Run once per machine:config.toml, with no env var, shell-rc edit, or new-terminal step. Then restart Codex (or the ChatGPT app, if that is where you run Codex) and start a new conversation. Check the state any time:
What gets written
valar codex on edits ~/.codex/config.toml. It sets the root provider to Valar and adds a provider block that points at the gateway and carries your credentials in request headers:
- Sets the root
model_providertovalarso Codex uses the Valar provider block. - Writes
base_urlwith the/v1surface. Codex speaks the OpenAI Responses API (wire_api = "responses") and appends/responses, so requests land onhttps://api.valarhq.ai/v1/responses. - Puts the coding key on
experimental_bearer_token, which Codex renders asAuthorization: Beareron the wire. It must not be anAuthorizationentry inhttp_headers. Codex treats that name as reserved and drops it (confirmed from codex-cli 0.145), which sends requests with no credential at all. - Adds the
X-Valar-Client-Id,X-Valar-HarnessandX-Valar-Cli-Versionrequest headers. The client-id header is omitted entirely when there is no client id, rather than written blank.
0600), since it now holds a bearer token, and the original config.toml is snapshotted under ~/.valar/codex/ before the first change so off restores it exactly.
The client id defaults to your OS username, so the header reads
X-Valar-Client-Id: jdoe. Use --user-id RANDOM for an opaque vc_… id instead. See per-engineer attribution.Route a single session
To try Valar without changing anything in your Codex setup, or to run one routed session beside it, open a single Valar-routed session instead of enabling globally:codex pinned to its own data dir (~/.valar/codex/session-home), routed through Valar. Your real ~/.codex config, and every other Codex session, stay untouched, and valar codex status stays off. Session history persists in that data dir across single-session runs.
Turn off routing
config.toml byte-for-byte. Restart Codex and start a new conversation.
Known limitations
Existing conversations require a fork between valar on and off
Moving a conversation across avalar codex on or off boundary is not supported. Start a new conversation, or /fork.
Conversations opened before valar codex on stay with OpenAI. Run /fork in one and the fork carries the context through Valar.
Running valar codex off under a conversation that is still open breaks that conversation. Routing reverts with the file, but the model stays the one you had selected, and OpenAI does not serve it:
codex resume reads whatever config.toml says at that moment and drops both the provider and the model the session recorded. The only hint is about the model:
off restores the file without the Valar block, a session recorded on Valar resumes straight against OpenAI on OpenAI’s default model. Forcing the provider back does not rescue it, since the block it needs is the thing off removed:
Voice is off while routing is on
Codex voice, realtime sessions and in-app dictation both, terminates at OpenAI. The audio leg runs against OpenAI’s Realtime API under your ChatGPT sign-in, andmodel_provider does not redirect it. Valar routing authenticates with your coding key instead, so the voice path is unavailable and Codex stays text-only. Turn routing off, or keep an unrouted Codex beside it, if you need voice.
Next steps
Model routing
How cohorts and the split decide which model serves each request.
Models
The open-weight targets and the frontier Claude tiers.