OpenAI’s Codex CLI is a capable terminal coding agent, and like Claude Code it isn’t locked to its maker’s models. Codex talks to any provider that implements an OpenAI-compatible API, so you can point it at DeepSeek, Qwen, GLM, or Kimi and keep the same workflow at a fraction of the cost.
The catch is that it’s not just a URL swap — Codex needs a proper provider definition, and the wire protocol has to match. This guide shows the working config.toml, the gotcha that wastes everyone an hour, and how to keep several providers on hand. For the wider picture, see use cheap AI models with Claude Code; the same model economics apply to Codex.
How Codex picks a provider
Codex loads ~/.codex/config.toml at startup. Two keys decide which API it talks to:
model— the model identifier (e.g.deepseek-chat).model_provider— which provider definition to use.
Provider definitions live under [model_providers.<id>] in the same file, each with a base URL, auth method, and wire protocol. On Windows the file is at C:\Users\YourName\.codex\config.toml.
A working DeepSeek config
model = "deepseek-chat"
model_provider = "deepseek"
[model_providers.deepseek]
name = "DeepSeek"
base_url = "https://api.deepseek.com/v1"
env_key = "DEEPSEEK_API_KEY"
wire_api = "chat"
Then export the key and run Codex:
export DEEPSEEK_API_KEY="sk-your-key"
codex
That’s the whole setup. env_key tells Codex which environment variable holds the key, so the secret never sits in the config file.
The wire protocol matters
config.toml provider keys
| name | Display name for the provider |
|---|---|
| base_url | The API endpoint, usually ending in /v1 |
| env_key | Env var that holds the API key |
| wire_api | "chat" for most third parties; "responses" for OpenAI |
Nearly every cheap provider — DeepSeek, Qwen via DashScope, Kimi, GLM — exposes the chat completions format, so wire_api = "chat" is the right choice. Only OpenAI’s own newer endpoints use "responses".
Other providers
Same shape, different URL and model. Qwen through Alibaba’s OpenAI-compatible endpoint:
model = "qwen3-coder-plus"
model_provider = "dashscope"
[model_providers.dashscope]
name = "Qwen (DashScope)"
base_url = "https://dashscope-intl.aliyuncs.com/compatible-mode/v1"
env_key = "DASHSCOPE_API_KEY"
wire_api = "chat"
Kimi through Moonshot:
model = "kimi-k2-thinking"
model_provider = "moonshot"
[model_providers.moonshot]
name = "Moonshot Kimi"
base_url = "https://api.moonshot.ai/v1"
env_key = "MOONSHOT_API_KEY"
wire_api = "chat"
Confirm the exact model IDs and base URLs on each provider’s docs — they change with new releases. See the per-model guides for current details: DeepSeek with Codex CLI, Qwen3-Coder with Codex CLI, GLM-5 with Codex CLI, and Kimi K2 with Codex CLI.
Keep several providers and switch
Define multiple [model_providers.*] blocks and switch per session. A common pattern is the --provider flag (with a matching model) or config profiles:
[model_providers.deepseek]
name = "DeepSeek"
base_url = "https://api.deepseek.com/v1"
env_key = "DEEPSEEK_API_KEY"
wire_api = "chat"
[model_providers.dashscope]
name = "Qwen (DashScope)"
base_url = "https://dashscope-intl.aliyuncs.com/compatible-mode/v1"
env_key = "DASHSCOPE_API_KEY"
wire_api = "chat"
This keeps DeepSeek for cheap day-to-day work and Qwen for big-context tasks, ready to switch.
Troubleshooting
- Auth errors — the
env_keyvariable isn’t set in the current shell, or the key is wrong. Echo the variable to confirm. - “Model not found” — the
modelvalue doesn’t match the provider’s exact ID. Check the provider’s model list. - Streaming/format errors — almost always
wire_api. Set it to"chat". - Changes ignored — restart Codex; it reads
config.tomlonly at startup.
Codex custom provider checklist
- Add a [model_providers.
] block with base_url and env_key - Set wire_api = "chat" for third-party endpoints
- Point model and model_provider at it
- Export the API key in your shell
- Restart Codex after editing config.toml
Wrapping up
Codex CLI runs on cheap models once you give it a real provider definition: a [model_providers.<id>] block with the base URL, an env_key for the secret, and wire_api = "chat". Set model and model_provider to match, export the key, and restart. The single most common mistake is overriding only the base URL — define the provider properly and it just works.
For the model side of the decision, see cheapest AI coding API in 2026 and Codex CLI on Windows with WSL.