-
-
Notifications
You must be signed in to change notification settings - Fork 3
Providers
A custom API provider is a saved third-party endpoint that codex-switch launch can hand to Codex CLI for one session. Typical case: OpenRouter, or another gateway that speaks Codex's Responses protocol.
Unlike a ChatGPT account profile, a provider has no auth.json and no quota dashboard. It stores a model-provider definition plus a bearer API key under $CODEX_SWITCH_HOME, then at launch injects that definition as codex -c … overrides. Nothing is written to ~/.codex.
Never put an API key on the command line.
provider addreads it from a hidden prompt, or from stdin with--api-key-stdin. The key is stored mode0600and never printed, listed, or placed in argv.
codex-switch provider add openrouter \
--base-url https://openrouter.ai/api/v1 \
--model openai/gpt-5.3-codexThe command then prompts for the API key without echoing it. For scripts, pass the key on stdin instead:
printf '%s' "$OPENROUTER_API_KEY" | codex-switch provider add openrouter \
--base-url https://openrouter.ai/api/v1 \
--model openai/gpt-5.3-codex \
--api-key-stdinOptional flags:
| Flag | Default | Purpose |
|---|---|---|
--name |
the alias | Human-readable name Codex shows |
--env-key |
CODEX_SWITCH_<ALIAS>_KEY |
Environment variable Codex reads the key from at launch |
--wire-api |
responses |
Codex wire protocol; current Codex only accepts responses
|
--reasoning EFFORT |
none | Save model_reasoning_effort=EFFORT for thinking models (see below) |
--no-web-search |
off | Save web_search=disabled for models that reject the built-in tool |
--set KEY=VALUE |
none | Extra codex -c override saved with the provider and applied at launch (repeatable) |
--api-key-stdin |
off | Read the key from stdin instead of a hidden prompt |
These save codex -c KEY=VALUE overrides with the provider, so a model-specific Codex setting is applied on every launch without retyping it after -- (see Model-specific request settings). --reasoning and --no-web-search are convenience shortcuts for the two most common settings; --set (repeatable) covers any other override. Values are passed to Codex verbatim — Codex, not codex-switch, decides which keys and values are valid — so only the KEY=VALUE shape is checked. An explicit --set wins over a convenience flag for the same key.
The alias follows the same rules as a ChatGPT profile (ASCII letters, digits, _, -, .; at most 64 characters) and must not collide with an existing profile, an existing provider, or Codex's reserved ids openai, ollama, and lmstudio.
Inspect and remove:
codex-switch provider list
codex-switch provider show openrouter
codex-switch provider remove openroutershow prints a redacted key (… plus the last four characters). Removal deletes the stored key immediately; unlike ChatGPT profile deletion, it is not archived under deleted-profiles/. Non-interactive and --json runs require --yes.
--json is supported on provider add, list, show, and remove. JSON never includes the raw key.
Name the provider alias. Auto-select (launch with no alias) stays ChatGPT-only.
codex-switch launch openrouter
codex-switch launch openrouter -- --full-autolaunch does not replace $CODEX_HOME/auth.json. It starts codex with -c overrides that define and select the provider, and injects the API key into the child process environment under env_key. Extra arguments after -- are appended as Codex CLI flags.
Some models need extra Codex request settings (disabling web_search, or setting a reasoning effort for thinking models) — see Model-specific request settings.
Because -c layers on top of $CODEX_HOME/config.toml, MCP servers, skills, and other Codex settings in that file stay in effect for the session.
codex-switch use does not accept a provider alias. A provider is applied only for the launched Codex process; a later bare codex invocation is unchanged.
OpenRouter is the intended first provider: its /api/v1 base URL plus a full model slug (including the vendor prefix) is what Codex expects.
Codex currently speaks only wire_api = "responses". DeepSeek's official API is Chat Completions, so pointing --base-url at DeepSeek directly will not work. Route DeepSeek (or any other Chat Completions-only vendor) through OpenRouter or another Responses-capable gateway, and set --model to that gateway's slug:
codex-switch provider add deepseek \
--base-url https://openrouter.ai/api/v1 \
--model deepseek/deepseek-chat \
--name "DeepSeek via OpenRouter"Pick the slug from the gateway's catalog. If Codex rejects the model, the usual cause is a Chat Completions-only endpoint rather than a missing key.
Codex always sends the same Responses request shape (including its built-in web_search server tool). Whether a given model accepts it depends on the model, not on luck — the behavior is consistent per model, not intermittent.
Codex enables its built-in web_search server tool by default. Some models accept or ignore it (verified: deepseek/deepseek-v3.2, moonshotai/kimi-k2, minimax/minimax-m3:free all return HTTP 200), while others reject it (verified: openai/gpt-oss-20b returns HTTP 400 Server tool request failed). If a model rejects it, turn it off at the top level of $CODEX_HOME/config.toml:
web_search = "disabled"per launch, since launch passes everything after -- to Codex:
codex-switch launch openrouter -- -c web_search=disabledor saved once with the provider so every launch applies it:
codex-switch provider add openrouter \
--base-url https://openrouter.ai/api/v1 \
--model openai/gpt-oss-20b \
--no-web-search(--no-web-search is shorthand for --set web_search=disabled.)
Codex defaults an unknown model to reasoning effort: none, which reads as reasoning disabled. Thinking models reject that with HTTP 400 Reasoning is mandatory for this endpoint. Give Codex a reasoning effort (verified with deepseek/deepseek-r1-0528 and moonshotai/kimi-k2-thinking):
codex-switch launch openrouter -- -c model_reasoning_effort=mediumor save it with the provider so it is always applied:
codex-switch provider add r1 \
--base-url https://openrouter.ai/api/v1 \
--model deepseek/deepseek-r1-0528 \
--reasoning medium(--reasoning medium is shorthand for --set model_reasoning_effort=medium.)
Effort values (none, minimal, low, medium, high, xhigh, max; Codex also accepts ultra) come from the Codex version in use, so codex-switch does not restrict them — pass any value with --reasoning (or --set) and Codex reports if it is invalid. Plain chat models (deepseek/deepseek-v3.2, moonshotai/kimi-k2, openai/gpt-4o-mini) need no reasoning flag. Combine --reasoning and --no-web-search (or repeat --set) when a model needs both.
codex-switch tui has two tabs: Accounts (ChatGPT OAuth, quota, scoring) and Providers (alias, name, model, base URL). Switch with Tab / Shift+Tab.
On the Providers tab:
| Key | Action |
|---|---|
j / k or ↑ / ↓
|
Navigate |
a |
Add a provider (alias → base URL → model → reasoning → web_search → API key) |
d |
Remove the selected provider (confirmation required) |
Tab |
Return to Accounts |
h |
Help |
q |
Quit |
The reasoning step is a single choice (←/→, default (skip) saves nothing); the web_search step is a toggle (Space, default leaves it enabled). Both are saved into the provider's codex_config. The API-key step is masked (*). The stored key is never rendered in the table. The wizard does not set --name, --env-key, or --wire-api; those keep the CLI defaults (name = alias, derived env_key, responses). Use the CLI (--set) for any override other than reasoning and web_search.
Launching a provider is CLI-only; the Providers tab does not start Codex.
| Location | Purpose |
|---|---|
$CODEX_SWITCH_HOME/providers/<alias>/provider.toml |
Provider definition and API key (directory 0700, file 0600) |
Defaults to ~/.codex-switch/providers/. Relocate the whole tree with CODEX_SWITCH_HOME; this still does not change where Codex reads auth.json.
Security contract:
- The key is never a CLI argument, so it does not appear in the process table as argv.
- At launch it exists only in the Codex child environment, under a codex-switch-owned variable (
CODEX_SWITCH_<ALIAS>_KEYby default) rather than a vendor's conventional name, so a pre-exportedOPENAI_API_KEYorOPENROUTER_API_KEYis not reused by accident. -
list,show, JSON output, and the TUI print a redacted form only. - Launch writes nothing under
$CODEX_HOME. ChatGPTuse/launchlocking andauth.jsonbackup/restore do not apply.
Do not commit provider.toml, paste keys into issues, or share unredacted --debug output.
- Persist a provider for a subsequent bare
codexrun (useremains ChatGPT-only). - Auto-select among providers, score them, or show quota / credits.
- Talk Chat Completions, or wrap a local proxy.
- Share an alias with a ChatGPT profile.
- Command flags and JSON shapes: Command reference.
- ChatGPT account, quota, and
useworkflows: Feature guide. - Paths and
CODEX_SWITCH_HOME: Configuration. - Module and storage layout: Architecture overview.