Client · CLI
Connect a third-party API to Codex without ChatGPT sign-in
Start with visual setup in CC Switch. When manual setup is needed, this page covers API keys, Base URLs, Client and CLI, plus 401, 404, and stale-route checks.
Independent setup notes, not affiliated with OpenAI. Field meanings follow public config conventions; verify against your local Codex version.
Choose your situation first — do not mix all three paths
Many 401 and no-effect reports come from mixed auth methods. Follow only the path that matches what you have.
You have a ChatGPT plan and want plan allowance
Sign in with ChatGPT
Browser authorization, with no third-party Base URL.
You have an official OpenAI API key
Log in with --with-api-key
Usage-based API billing; let CLI write the shared credential.
You have a third-party or CodexFree-compatible API
Write a user-level model_provider
Set Base URL, model, and Responses protocol together.
First: ChatGPT login vs API key
Only one credential is active at a time. CLI and Client share it; logging out of one clears both.
| Compare | ChatGPT login | API key |
|---|---|---|
| How you sign in | codex login (browser) | printenv … | codex login --with-api-key |
| Billing | Codex allowance on your ChatGPT plan | API / gateway usage (separate from plan credits) |
| Best for | Subscription allowance, no custom gateway | CI, custom base_url, compatible gateways, this site |
| Is export alone enough? | N/A | No — export does not auto-login; use explicit login or a provider |
Check the active credential with codex login status. Clear with codex logout.
Three ways to attach a key
Platform keys or compatible gateway keys both work. Custom routes need a Responses-capable endpoint (since Feb 2026, wire_api only supports responses).
CLI: pipe into login (most common)
Feed the key on stdin. It lands in the credential store and later sessions bill as API usage. Avoid echoing secrets into shell history when you can.
export OPENAI_API_KEY="sk-..."
printenv OPENAI_API_KEY | codex login --with-api-key
codex login statusauth.json / OS keyring
file mode writes ~/.codex/auth.json; keyring uses the OS store. CLI and Client share the cache. Treat it like a password.
{
"OPENAI_API_KEY": "sk-your-key"
}Custom model_providers in config.toml
Third-party / self-hosted / this site’s gateway: define base_url + env_key (or requires_openai_auth) in user-level config. Never put the raw secret in TOML.
CLI: login through verification
Suggested order: export → pipe login → status → start codex. In CI, pipe from secrets — never print the key.
export OPENAI_API_KEY="sk-..."
printenv OPENAI_API_KEY | codex login --with-api-key
codex login status
codexSetting OPENAI_API_KEY alone is not a login. For the built-in openai route, explicit --with-api-key (or a custom provider with env_key) is the reliable path.
Where credentials live: file / keyring / auto
Control with cli_auth_credentials_store in user-level ~/.codex/config.toml. Check this when login “worked” but nothing reads it.
file
Writes $CODEX_HOME/auth.json (default CODEX_HOME=~/.codex). Easy to inspect — also easy to leak into git.
keyring
OS credential store. Safer; can be awkward over SSH or headless sessions.
auto
Prefer keyring; fall back to auth.json.
cli_auth_credentials_store = "file"auth.json is sensitive. Keep permissions tight; don’t sync it as plain text to shared drives.
Client: same login cache as the CLI
Desktop/app Clients read the same user-level cache. Logging out of one clears the other. Fully quit and reopen after config changes — closing a window is often not enough.
- 1
Confirm the user-level directory
Default ~/.codex. CODEX_HOME relocates it — CLI and Client must agree on the path.
- 2
Log in via CLI or finish the provider block
Clients rarely need a separate pipe-login; they reuse what the CLI already wrote.
- 3
Fully quit the Client, then reopen
Forces a reload of auth.json and config.toml. If it still looks old, check user vs project scope next.
User-level vs project-level: providers belong in user config
One of the most common “I edited config and nothing changed” failures. Project .codex/config.toml can load when trusted, but provider-related keys are ignored.
User-level ~/.codex/config.toml
Put model_provider, model_providers, openai_base_url, and credential-related keys here.
Project-level .codex/config.toml
Fine for workflow prefs — but model_providers / model_provider / openai_base_url are ignored (often with a startup warning). Gateway edits in the project folder do nothing.
Use profiles for multiple routes
Keep profile-name.config.toml under the user home and launch with --profile profile-name instead of rewriting the default file.
config.toml: custom compatible gateway
Custom providers cannot reuse reserved ids: openai, ollama, lmstudio. model_provider must match the [model_providers.xxx] table name.
- 1
Edit only the user-level file
Path: ~/.codex/config.toml (or $CODEX_HOME/config.toml).
- 2
env_key is a variable name, not the secret
Example: env_key = "OPENAI_API_KEY", then export the real value in your shell.
- 3
Write base_url the way your gateway documents it
Many compatible hosts end with /v1 and no trailing slash. Azure shapes differ (/openai vs /openai/v1) — follow what you were given.
- 4
Restart the session to verify
New terminal for CLI; fully quit the Client. Or let CC Switch write the files, then restart the same way.
model_provider = "codexfree"
model = "gpt-5"
[model_providers.codexfree]
name = "CodexFree"
base_url = "https://YOUR-GATEWAY-HOST/v1"
wire_api = "responses"
env_key = "OPENAI_API_KEY"
env_key_instructions = "export OPENAI_API_KEY before starting Codex"
requires_openai_auth = false
request_max_retries = 4
stream_max_retries = 5
stream_idle_timeout_ms = 300000Field cheat sheet
| Field | Meaning |
|---|---|
| model_provider | Active provider id — must match the table name. |
| model | Default model; on Azure this is often the deployment name. |
| name | Display name in UI / logs. |
| base_url | API root. Compatible gateways often end with /v1. |
| wire_api | Protocol. After 2026-02 only responses; chat fails at startup. |
| env_key | Name of the env var that holds the key — not the key string. |
| requires_openai_auth | When true, uses OpenAI login cache and ignores env_key. |
| query_params | Extra query params (e.g. some Azure api-version values). |
| http_headers / env_http_headers | Static or env-injected request headers. |
| request_max_retries / stream_* | Retries and SSE idle timeout. |
Older guides saying wire_api = "chat" are outdated. Chat Completions support was removed; only Responses remains. If a gateway only speaks /chat/completions, it needs Responses on the host — or a local route that translates (see the toolkit).
Lighter option: openai_base_url only
To point the built-in openai provider at a proxy/router, set openai_base_url in user-level config. For multiple vendors, different keys, or full provider fields, use model_providers.
openai_base_url = "https://YOUR-PROXY-HOST/v1"Pitfall matrix
Symptom → check this first.
Edited project config — no effect
Provider keys are ignored at project scope. Edit ~/.codex/config.toml.
401 / auth failures
Is env_key only a variable name? Is that var present in the same shell that starts Codex? Did requires_openai_auth ignore env_key?
404 / Unsupported endpoint
base_url path (/v1, trailing slash) and whether the gateway actually exposes Responses.
Exported a key but still looks logged out
Pipe into login for the built-in route, or use a custom provider + env_key.
Switched gateways but still on the old route
New terminal; fully quit Client; confirm model_provider matches the table; cat ~/.codex/config.toml.
CLI works, Client does not
CODEX_HOME mismatch, Client not fully quit, or file vs keyring pointing at different stores.
Do not trust the save button: verify the route in four steps
A saved file is not proof. Identity, config location, process state, and provider logs must all agree.
codex login status
printenv CODEX_HOME
cat ${CODEX_HOME:-$HOME/.codex}/config.toml
codexCheck 1
Confirm the active identity
login status must match the ChatGPT or API-key path you chose. If not, logout and repeat only one path.
Check 2
Confirm the file being read
Inspect CODEX_HOME. Provider settings belong in user config.toml, not project .codex.
Check 3
Fully restart both surfaces
Open a new terminal for CLI and fully quit the Client before reopening it. Closing a window may leave the process alive.
Check 4
Send a short task and inspect upstream
Check provider logs or balance. 401 means key, 404 means Base URL / Responses, and no record means a stale process or wrong model_provider.
Need a key first?
Request our upcoming compatible capacity, then finish wiring here — or use CC Switch in the toolkit to reduce hand-edits.
- Leave an email on Access
- CLI: pipe login, confirm login status
- Custom gateway: user-level config.toml + wire_api = responses
- Client: share ~/.codex, fully quit and reopen
FAQ
Do Client and CLI use different configs?
No. They share ~/.codex auth and config by default. Logout clears both.
Why doesn’t project-level provider config work?
For host/security boundaries, project configs ignore model_providers and related keys. Gateways belong in user-level config.
Can wire_api still be chat?
No. After February 2026 only responses is valid.
Can I put sk-… in env_key?
No. env_key is the variable name; export the secret separately.
openai_base_url vs model_providers?
Use openai_base_url to redirect the built-in openai provider; use model_providers for full multi-vendor setups.
How does this fit the free access on this site?
After you receive a key and base_url, follow the custom provider example — or Enable it in CC Switch and restart.