How to Set Up Codex config.toml: Custom API, Proxy, and Common Errors

AIHubMix7 min read
How to Set Up Codex config.toml: Custom API, Proxy, and Common Errors

Codex keeps its settings in one file, config.toml: which model to use, which API to call, and how much the agent may do without asking. The format changed several times in 2026, and many guides from earlier in the year show settings that now stop Codex from starting.

This guide gives you a working config first, then the parts most people change: profiles, project settings, the sandbox, and a proxy. At the end is a list of the errors you're likely to see, with what each one means. Checked against OpenAI's docs and run on Codex CLI 0.162.1 on October 19, 2026. The examples use AIHubMix as the provider; any gateway that supports the OpenAI Responses API works the same way.

The short version

  • The file is ~/.codex/config.toml, or C:\Users\<you>\.codex\config.toml on Windows.
  • A custom provider needs base_url, wire_api = "responses" and env_key. The API key goes in an environment variable.
  • Profiles are now separate files, ~/.codex/<name>.config.toml, chosen with --profile <name>.
  • A repo's .codex/config.toml works only in trusted projects and can't change the provider.
  • Restart Codex after every edit; it reads the file only at startup.

Where config.toml lives

Your main settings are in ~/.codex/config.toml. The CLI and the IDE extension both read it. If the file doesn't exist yet, create it.

Two other places can add settings on top:

  • Profile files, ~/.codex/<name>.config.toml, used only when you start Codex with --profile <name>.
  • Project files, .codex/config.toml inside a repo, for settings a team wants to share.

If you run Codex inside WSL2 on Windows, it reads the Linux home (/home/<you>/.codex/config.toml), not the Windows one. If CODEX_HOME is set, Codex uses that folder instead of ~/.codex.

A minimal working config

This complete ~/.codex/config.toml sends Codex's requests to AIHubMix:

model = "gpt-6-sol"
model_provider = "aihubmix"
model_reasoning_effort = "high"

[model_providers.aihubmix]
name = "AIHubMix"
base_url = "https://aihubmix.com/v1"
wire_api = "responses"
env_key = "AIHUBMIX_API_KEY"
  • model is the model ID to call, and model_reasoning_effort its default reasoning level.
  • model_provider must match the name in [model_providers.<name>]. Don't use openai, ollama or lmstudio; those names are taken by Codex's built-in providers.
  • base_url is the provider's API address. wire_api = "responses" is the only value Codex accepts now.
  • env_key is the name of an environment variable, not the key itself.

Then set that variable, with a key from the AIHubMix console:

# macOS / Linux: add this line to ~/.zshrc or ~/.bashrc, then open a new terminal
export AIHUBMIX_API_KEY=sk-...
# Windows PowerShell: takes effect in new terminals
setx AIHUBMIX_API_KEY "sk-..."

Start codex from a new terminal and ask it anything. If it answers, the provider works. Being logged in to Codex doesn't matter here: the key from codex login is never sent to a custom provider.

Profiles: one file per setup

A profile holds only the settings that differ from your main config, such as deeper reasoning and a read-only sandbox for code review. Each profile is its own file next to config.toml, with the keys written at the top level:

# ~/.codex/review.config.toml
model_reasoning_effort = "xhigh"
sandbox_mode = "read-only"
codex --profile review

This changed in Codex 0.134.0. Older guides put profiles inside config.toml as [profiles.review] tables and pick one with profile = "review". Codex now refuses to start with that selector. A leftover [profiles.review] table on its own is ignored without any message, so its settings quietly stop working. To migrate, move each table's keys into ~/.codex/<name>.config.toml, then delete the table and the profile = ... line. More detail is in OpenAI's advanced configuration guide.

Project config: .codex/config.toml

A .codex/config.toml in a repo lets a team share a default model, reasoning level or sandbox mode. Codex reads it only in projects marked as trusted in your own ~/.codex/config.toml:

[projects."/Users/you/code/my-app"]
trust_level = "trusted"

A project file can't change where requests go. Codex ignores model_provider, model_providers, openai_base_url, profile, notify and a few other keys there, and prints a warning when it does. Keep your provider in ~/.codex/config.toml. A project can still pick the model; the request goes to your own provider.

Which setting wins

When the same key is set in more than one place, OpenAI's Config basics gives this order, highest first:

  1. Command-line flags, including -c overrides
  2. The project's .codex/config.toml
  3. The profile chosen with --profile
  4. Your ~/.codex/config.toml
  5. The system config, /etc/codex/config.toml
  6. Codex's built-in defaults

Note that a project file beats a profile. If a profile setting seems to do nothing, check whether the repo's .codex/config.toml sets the same key.

To change a setting for one run only, use -c:

codex -c model_reasoning_effort=high

Sandbox and approvals

Two keys control what Codex does on its own. sandbox_mode sets what its commands can touch, and approval_policy sets when it stops to ask you.

sandbox_mode What commands can do
read-only Read files; anything more needs approval
workspace-write Write in the project folder and temp folders
danger-full-access Anything, with no sandbox
approval_policy When Codex asks
on-request When it needs to go past the sandbox
never Never; blocked commands just fail
sandbox_mode = "workspace-write"
approval_policy = "on-request"

[sandbox_workspace_write]
network_access = true   # off by default

The two are independent: never stops the questions but doesn't loosen the sandbox. In workspace-write, commands can't reach the network until you set network_access = true.

Behind a proxy

Codex has no proxy setting in config.toml. It uses the standard environment variables:

export HTTPS_PROXY=http://127.0.0.1:7890   # your proxy address
export NO_PROXY=localhost,127.0.0.1

OpenAI's docs don't mention these, so they were tested on Codex 0.162.1: requests, including those to a custom provider, went through HTTPS_PROXY (or ALL_PROXY), and hosts in NO_PROXY were reached directly. PAC files aren't supported, so enter the proxy address itself. If your company's proxy uses its own root certificate, point CODEX_CA_CERTIFICATE at it, as described in the environment variable reference.

More models in /model

The /model picker lists only OpenAI's models. To choose GLM, Claude, Gemini or DeepSeek models from it, add a model catalog: a JSON file named by a top-level model_catalog_json key. Put that key above the first [table] line, or TOML counts it as part of that table and Codex ignores it.

The catalog replaces the built-in list, and every entry needs a long set of fields, so it's best generated rather than written by hand. The AIHubMix Codex CLI guide has a script that builds one from the top 30 models on AIHubMix. The desktop app may still hide custom models from its picker (openai/codex#19694), so switch models in the terminal.

Common errors and what they mean

These are the messages Codex 0.162.1 printed for each mistake.

legacy profile = "..." config is no longer supported
Your config.toml still has the old profile = "..." line. Move the profile into its own file as described above. Running --profile x while an old [profiles.x] table exists gives a similar error, --profile x cannot be used while ... contains legacy ... config.

wire_api = "chat" is no longer supported
Codex no longer supports the Chat Completions API. Change it to wire_api = "responses". A provider that only offers Chat Completions won't work without a translating proxy.

model_providers contains reserved built-in provider IDs
You named your provider openai, ollama or lmstudio. Rename the table and model_provider to something else.

approval_policy = "untrusted" is no longer supported
Remove the line or use on-request.

Missing environment variable: AIHUBMIX_API_KEY
The variable named in env_key isn't set in the terminal that started Codex. Open a new terminal, or run source ~/.zshrc, and start Codex again.

401 Unauthorized after a few "Reconnecting..." lines
The request went out without a key. Check that the provider table has env_key. The login stored in auth.json doesn't count for custom providers.

Model metadata for ... not found. Defaulting to fallback metadata
Codex has no built-in settings for that model, which is normal for non-OpenAI models. Requests still work. Add a model catalog if you want proper settings and the model in /model.

Ignored unsupported project-local config keys
A repo's .codex/config.toml sets a key that only works in your own config, usually model_provider. Move it to ~/.codex/config.toml.

missing field base_instructions
An entry in your model catalog is missing a required field, so Codex rejects the whole file. Regenerate the catalog with the script instead of editing it by hand.

When a setting doesn't take effect

  • Restart Codex after editing.
  • Make sure top-level keys come before the first [table] line.
  • Check the repo's .codex/config.toml; it overrides your profile.
  • Look for a leftover [profiles.x] table.
  • Run codex doctor, which checks your install, config and login.

If you want to use OpenAI, Anthropic, Google, Zhipu, DeepSeek and other models in Codex with one key, AIHubMix serves them through the Responses API at https://aihubmix.com/v1. Start with the minimal config above, and add a model catalog when you want to switch models from /model.

FAQ

Where is the Codex config.toml file?
In ~/.codex/config.toml on macOS and Linux, and C:\Users<you>.codex\config.toml on Windows. If CODEX_HOME is set, it's in that folder instead.

Do I need to restart Codex after changing config.toml?
Yes. Codex reads the file when it starts, so quit and reopen the terminal session or the app.

Why does Codex say "legacy profile config is no longer supported"?
Codex 0.134.0 dropped profiles defined inside config.toml. Move each profile into ~/.codex/name.config.toml, delete the old lines, and start Codex with --profile name.

Can I still use wire_api = "chat"?
No. Codex accepts only wire_api = "responses". A provider that supports only Chat Completions needs a proxy that translates to the Responses API.

Why does my custom provider return 401 when I'm logged in to Codex?
The login key in auth.json isn't sent to custom providers. Add env_key to the provider table and set that variable in your terminal.

Does Codex use HTTPS_PROXY?
Yes. In a test on Codex 0.162.1, requests went through HTTPS_PROXY and skipped hosts listed in NO_PROXY. PAC files aren't supported.

Why is model_provider ignored in my project's .codex/config.toml?
Project files can't change where requests go, so a repo can't redirect your traffic. Put the provider in ~/.codex/config.toml; the project file can still set the model.

Sources