Skip to content
2026-05-30 · Kalmantic

TL;DR: Codex CLI's custom provider config in ~/.codex/config.toml accepts any OpenAI-compatible base URL, but only over the Responses API. wire_api = \"chat\" was removed, so most open-weights hosts can't back it yet without a translation layer.

Codex CLI custom providers: what works, what's tricky, and what's coming

What Codex CLI is

Codex CLI is OpenAI's open-source Rust-based coding agent, a terminal CLI that reads your repo, proposes edits, runs commands, and iterates. If you've used Claude Code, the mental model is the same: an autonomous agent loop driven by a frontier model. The default install signs into chat.openai.com via OAuth and routes everything through your OpenAI account.

Why "custom provider" matters for Codex

Out of the box, Codex CLI talks to OpenAI's hosted endpoints over an OAuth-bound session. That's fine if your OpenAI bill is fine. It's not fine if you want to point Codex at Ollama on your laptop, at a fine-tune host running an experimental Qwen variant, at a corporate inference endpoint that never leaves your VPC, or at a routing gateway like jusCode that picks the cheapest capable model per call.

The custom-provider config is what makes those substitutions possible. Anything that speaks the right OpenAI-compatible wire format can stand in for chat.openai.com.

The config file

Codex CLI reads ~/.codex/config.toml. TOML, not JSON, not YAML. A minimal custom-provider config looks like this:

model = "<model-id>"
model_provider = "myprovider"

[model_providers.myprovider]
name = "My Provider"
base_url = "https://api.example.com/v1"
env_key = "MY_PROVIDER_API_KEY"
wire_api = "responses"
requires_openai_auth = false

Field by field:

  • model: the model identifier Codex will send on every request. The provider has to recognize this string.
  • model_provider: references one of the [model_providers.*] blocks below. Default for every session unless overridden by a profile.
  • name: display label shown in Codex's UI; cosmetic.
  • base_url: the root of the OpenAI-compatible endpoint. Codex appends paths like /responses itself; do not include them here.
  • env_key: name of the environment variable Codex reads the API key from. You export MY_PROVIDER_API_KEY=... in your shell; Codex never persists the secret in the TOML file.
  • wire_api: see the next section. This is the field that determines whether your setup actually works.
  • requires_openai_auth: set to false for any non-OpenAI provider; setting it to true triggers Codex's OAuth flow against chat.openai.com, which a custom provider can't satisfy.

The one thing that trips everyone up: wire_api

Codex only speaks the OpenAI Responses API now. The older wire_api = "chat" value (which targeted the classic /v1/chat/completions shape) was removed from the Codex CLI. See the openai/codex repository and the config.toml reference in its docs. So your custom provider must expose POST /v1/responses, not /v1/chat/completions.

This is the single most common failure mode for first-time custom-provider configs. The provider validates the API key, accepts the connection, and then 404s on the first tool call because it doesn't have a /responses route. Codex prints a generic error, the agent hangs, and the user assumes the provider list is wrong. It isn't. The wire protocol is.

Which OpenAI-compatible providers natively expose /v1/responses today (May 2026):

  • OpenAI: the reference implementation.
  • DeepSeek v4 family: Responses API support shipped in their April 2026 endpoint rollout.
  • OpenRouter: added a Responses-compatible wrapper in Q1 2026 across its catalog.

Which providers do not speak Responses natively (and therefore cannot back Codex CLI directly without a translation shim):

  • Together: Chat Completions only.
  • Fireworks: Chat Completions only.
  • Cloudflare Workers AI: Chat Completions only.
  • Most self-hosted runtimes (vLLM, TGI, llama.cpp, Ollama): Chat Completions only out of the box.

Without a Responses route, tool calls silently drop and the agent appears to think but never to act. That's the trap.

Profiles vs. defaults

The top-level model_provider is the default for every Codex session. If you want to keep your OpenAI account as the default and only opt into a custom provider for specific work, use profiles:

model = "gpt-5"
model_provider = "openai"

[profiles.work]
model = "jusCode-auto"
model_provider = "juscode"

[model_providers.juscode]
name = "jusCode"
base_url = "https://api.juscode.co/v1"
env_key = "JUSCODE_API_KEY"
wire_api = "responses"
requires_openai_auth = false

Then:

codex --profile work

Profiles are the right tool when your default already works and you want the custom provider to be deliberate. Top-level defaults are the right tool when the custom provider is your one and only setup.

Reasoning effort

Codex sends a reasoning.effort field on every Responses request when the upstream model supports it. You can pin the default at the top level:

model_reasoning_effort = "high"

Valid values: none, minimal, low, medium, high, xhigh. Default is medium. This is only meaningful for reasoning-capable models (GPT-5, o-series, DeepSeek v4 reasoners, etc.); sending it to a non-reasoning model is a no-op rather than an error.

What you can't do with custom providers (yet)

A few sharp edges worth knowing before you spend an evening debugging:

  • No XDG fallback. Config has to live at ~/.codex/config.toml. The XDG-conventional ~/.config/codex/ path is not read. Symlink if you care about XDG hygiene.
  • No CODEX_PROVIDER environment variable. You cannot ad-hoc override the provider from the shell environment alone. The closest equivalent is the per-invocation flag: codex -c model_provider=name. Useful for one-off runs against a non-default provider.
  • Duplicate top-level keys break the TOML load. If a setup script appends model = "..." to a file that already has model = "..." higher up, Codex refuses to load the config and prints a parse error. You have to edit in place, not append. Setup automation that assumes append-safety will silently corrupt the file.

jusCode and Codex CLI

Honest status: we are shipping Codex CLI support soon. It is not shipping today.

The blocker is the Responses-vs-Chat translation layer. Our routing currently sends most coding-agent traffic to Chat-Completions-only upstreams (Together, Fireworks, Cloudflare Workers AI), and that is where the cost savings live, because those hosts are where the cheap-but-capable mid-tier models actually run. If we exposed a Responses endpoint today that fronts those upstreams without translating tool-call semantics correctly, Codex would silently drop tool calls on every routed request and quietly degrade on exactly the models that make routing worthwhile. That defeats the whole point.

So we are enhancing the gateway's Responses adapter to translate tool-call shape, streaming, and reasoning-effort fields bidirectionally: Responses on the Codex-facing side, Chat Completions on the upstream side, with full fidelity in both directions. When that's done, Codex CLI users will get the same one-line install as every other agent we support, and routing will work honestly across the catalog.

Until then, you have two choices, both described below.

If you want us to ping you when it lands, drop your email at /preregister/?tier=codex.

Practical workaround for now

Option 1: Point Codex CLI at OpenAI direct. This works today because OpenAI obviously speaks its own Responses API. You lose all of jusCode's routing benefits (every call goes to OpenAI at OpenAI's rates) but Codex CLI works end to end.

model = "gpt-5"
model_provider = "openai-direct"

[model_providers.openai-direct]
name = "OpenAI"
base_url = "https://api.openai.com/v1"
env_key = "OPENAI_API_KEY"
wire_api = "responses"
requires_openai_auth = false

Option 2: Use Claude Code with jusCode for everything else. Claude Code's wire protocol is the Anthropic Messages API, which our gateway speaks fully today. Set two environment variables and you're routed:

export ANTHROPIC_BASE_URL=https://api.juscode.co
export ANTHROPIC_AUTH_TOKEN=jcg_your_key_here

Full walkthrough: /docs/claude-code/.

The drop-in install script for Codex CLI lands when the routing is honest. We'd rather ship late than ship a setup that quietly costs you tool calls.


Raw markdown: /blog/codex-cli-custom-provider.md

codex-cliopenai-codexcustom-provideropenai-responses-apillm-routingbyo-provider