The ChatGPT desktop app bundles the real Codex CLI at /Applications/ChatGPT.app/Contents/Resources/codex and runs it in app-server mode against the same config home the terminal uses, ~/.codex — verified against the bundled binary and the live process environment on 13 August 2026. So ~/.codex/config.toml is read by desktop-launched Codex, and the app even links "Open config.toml" from its settings. What does not work is picking a custom model in the app: the picker is not provider-aware, so selecting one changes the model name without switching provider, and the session fails with a message about the model not being supported on a ChatGPT account. The setup that works is a Codex CLI profile in that shared home: define [model_providers.continuum] with base_url https://continuumcode.ai/v1 and wire_api "responses", define [profiles.continuum] that selects it, export CONTINUUM_API_KEY, and run codex --profile continuum from a terminal. The custom provider stays out of the default config, so the desktop GUI keeps working on your ChatGPT account.
- The desktop app bundles the real Codex CLI and shares one config home with your terminal Codex:
~/.codex. - The in-app model picker is not provider-aware. Choosing a custom model changes the name, not the provider, and the turn then fails.
- Provider is settable only when a thread is created. There is no mid-thread provider switch.
- The working route is a Codex profile in that same config home, launched with
codex --profile continuumfrom a terminal. - Do not set a global
model_providerif you want the desktop GUI to keep working on your ChatGPT account. wire_apimust be"responses"— the binary refuses"chat"outright. Continuum serves/v1/responses, so no translating gateway is needed.
What the ChatGPT desktop app actually runs
Codex inside the ChatGPT desktop app is not a reimplementation and not a hosted service with a local skin. The app ships the genuine CLI binary and drives it in app-server mode, so the thing answering your prompts in that window is the same program you would run from a terminal.
Read off this machine on 13 August 2026.
| Question | Answer |
|---|---|
| Where is the binary? | /Applications/ChatGPT.app/Contents/Resources/codex |
| What does it report? | codex-cli 0.147.0-alpha.6.5 |
| How is it driven? | App-server mode, with daemon state under ~/.codex/app-server-daemon/ |
| Which config home? | ~/.codex — no CODEX_HOME override in the live process environment |
That is a genuinely good starting position, and it is why this guide exists rather than saying "you cannot". It is also not the end of the story, because reading your configuration and letting you select what is in it are two different things.
Why the in-app route is a trap
Adding a custom provider and then picking its model from the app’s own model picker is the obvious move, and it does not work. The failure is not a permissions or credentials problem; it is that the picker does not carry provider identity, so the app changes which model name it asks for without changing who it asks.
Each of these is documented in the open issue openai/codex#29156, last active 5 August 2026, or in the configuration reference.
| The obstacle | What actually happens |
|---|---|
| The picker is not provider-aware | model/list returns no provider identity, so selecting a custom model changes the name only |
| Provider is creation-time only | ThreadStartParams.modelProvider sets it at thread creation; TurnStartParams can override the model but not the provider |
model_catalog_json replaces, it does not merge | Adding one custom model removes the entire built-in catalog for that process |
A global model_provider breaks the GUI | It stops the desktop app coexisting with your ChatGPT login |
A separate CODEX_HOME hides your history | Session state is tied to the active home, so your normal chat history disappears |
The reproduced symptom is worth knowing by sight, because it sends people to check their API key when the key is fine. On Codex Desktop 26.730.8199, selecting a custom model produces a "Model changed…" confirmation, immediately followed by a failure reading The "<model>" model is not supported when using Codex with a ChatGPT account. The app switched the label and kept the provider, so it asked the ChatGPT backend for a model that backend has never heard of.
The setup that works: a Codex profile
Profiles are Codex’s own mechanism for a named overlay on top of the default configuration. That is exactly the shape of this problem: you want Continuum available in the config home the desktop reads, without it being what the desktop picks up by default. Nothing here touches the app’s ChatGPT login.
One prerequisite before the steps: this needs Continuum Plus or higher. Inference keys do not mint on the Free tier, so the Create key button stays disabled until you subscribe, and the profile below is inert without a key.
Create a Continuum API key
In the Continuum web app at continuumcode.ai/app, open Settings, then Account, then Inference API. Create your key under Your keys. The same panel is on the Usage tab. Copy it at creation: it begins cont_sk_ and the full value is shown exactly once.
Keys mint on Plus and above, so on the Free tier Create key stays disabled until you subscribe.
Add a provider and a profile to ~/.codex/config.toml
Two tables, and deliberately no top-level model_provider line. That omission is the whole trick: the default configuration is unchanged, so the desktop app keeps behaving exactly as it did.
[model_providers.continuum]
name = "Continuum"
base_url = "https://continuumcode.ai/v1"
env_key = "CONTINUUM_API_KEY"
wire_api = "responses"
[profiles.continuum]
model_provider = "continuum"
model = "gpt-5.6-sol"
The provider id can be anything except the reserved ones — openai, ollama, and lmstudio cannot be reused. The profile name and the provider id do not have to match; they are the same word above only because that reads well on the command line.
Export the key and launch with the profile
env_key names a variable rather than holding a secret, so the key is exported in the shell you run Codex from.
export CONTINUUM_API_KEY="cont_sk_..."
codex --profile continuum
Without --profile, codex starts on your normal defaults and the Continuum tables sit inert. That is the intended behaviour: one config home, two ways to launch, no interference between them.
Confirm the desktop app is unaffected
Open the ChatGPT desktop app and start a Codex session as usual. It should behave exactly as before, on your ChatGPT account, because nothing it reads by default has changed. If it does not, you added a global model_provider line somewhere — remove it.
What this gets you, and what it does not
It is worth naming the result precisely rather than letting the guide’s title over-promise. As of 13 August 2026, "Continuum in the ChatGPT desktop app" resolves to Continuum in the bundled Codex CLI, launched from a terminal, while the desktop GUI stays on your ChatGPT account. The config home is shared, the binary is the same one; the window is not the surface that reaches Continuum.
| Surface | Runs on | Billed to |
|---|---|---|
codex --profile continuum, from a terminal | Continuum’s inference API | Your Continuum plan |
codex with no profile | Your normal Codex defaults | Whatever those are |
| The ChatGPT desktop app window | Unchanged, on your ChatGPT login | Your ChatGPT plan |
Three things not to do
- Do not use the
requires_openai_auth = truetrick. Making a third-party provider claim to be OpenAI-authenticated is a fake-auth hack, not a configuration, and it earns you a setup that breaks in ways nobody will help you debug. - Do not use
model_catalog_json. It is a full replacement rather than a merge, so adding one custom model deletes the entire built-in catalog for that process. - Do not use a separate
CODEX_HOME. It looks like clean isolation and costs you your chat history, because session state is tied to the active home.
Each of those is attractive precisely because it looks like it routes around the picker problem. None of them do; they trade a visible limitation for an invisible one.
When it does not work
Start every diagnosis in a terminal. The desktop app’s environment is the hardest part of this setup to reason about, so proving the profile works from a shell first removes the largest variable in one step.
| Symptom | Cause | Fix |
|---|---|---|
| "Model changed…" then "not supported when using Codex with a ChatGPT account" | The in-app picker changed the name, not the provider | Expected. Use codex --profile continuum from a terminal instead |
Error loading config.toml: `wire_api = "chat"` is no longer supported. | The old wire value | Set wire_api = "responses", which the error itself tells you |
| 401 from the terminal | The variable is not set in this shell | echo $CONTINUUM_API_KEY in the same terminal you launch from |
| Works in a terminal, fails when launched from the GUI | A GUI app does not inherit your shell profile | Not a config problem; the desktop route is not the supported one here |
| The desktop app stopped working after the edit | A global model_provider line | Remove it. The provider belongs to the profile, not the defaults |
| The profile is ignored | --profile was omitted | Profiles are opt-in by design; without the flag the tables are inert |
| Unknown or invalid model | The ID is not on your plan’s allowlist | Check it against GET /v1/models with your key |
| A long answer stops mid-sentence | The 8,192-token output cap | Ask for the work in parts; agent turns iterate and rarely hit it |
On wire_api, which is not negotiable
The configuration reference gives "responses" as the only supported value, and the binary enforces it rather than warning. The error is unusually helpful, so it is worth reproducing exactly:
Error loading config.toml: `wire_api = "chat"` is no longer supported.
How to fix: set `wire_api = "responses"` in your provider config.
More info: https://github.com/openai/codex/discussions/7782
in `model_providers.continuum.wire_api`
curl -s https://continuumcode.ai/v1/models \
-H "Authorization: Bearer cont_sk_..."
curl -s https://continuumcode.ai/v1/responses \
-H "Authorization: Bearer cont_sk_..." \
-H "Content-Type: application/json" \
-d '{"model":"gpt-5.6-sol","input":"say hi"}'
The paid lane serves claude-opus-5, claude-fable-5, claude-sonnet-5, gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna, grok-4.6, gemini-3.5-flash, deepseek-v4-flash, glm-5.3, and muse-spark-1.2, read from the live gateway on 17 August 2026, alongside a free lane. Personal API keys are a paid-plan feature: Plus at $25/mo, Max 100 at $100/mo, Max 200 at $200/mo, or Ultra at $500/mo. The full table, free lane included, is in the Codex CLI guide.
Questions people ask
Yes. It bundles the binary at /Applications/ChatGPT.app/Contents/Resources/codex, which reports codex-cli 0.147.0-alpha.6.5, and drives it in app-server mode. That was read off the application on 13 August 2026.
Yes. Both use ~/.codex, verified from the live process environment with no CODEX_HOME override, and app-server daemon state sits in ~/.codex/app-server-daemon/. The app also links "Open config.toml" from its own settings.
The model picker is not provider-aware: model/list returns no provider identity, so selecting a custom model changes the model name without switching provider. The turn then fails with a message about the model not being supported on a ChatGPT account.
No. Provider is settable only at thread creation, through ThreadStartParams.modelProvider. TurnStartParams can override the model but not the provider, so there is no mid-thread switch.
Not if you follow the setup here. The provider lives inside a profile and there is no global model_provider line, so the app’s defaults are unchanged. Setting a global model_provider is what breaks coexistence with the ChatGPT login.
Because it is a full replacement rather than a merge. Adding one custom model removes the entire built-in catalog for that process, which is a much larger change than it looks.
Session state is tied to the active home, so a separate one hides your normal chat history. The profile approach keeps everything in the shared home and stays opt-in per launch.
It is the only supported value, and the binary refuses "chat" with an error that names the fix. Continuum serves POST /v1/responses natively, so unlike a Chat-Completions-only endpoint it needs no translating proxy in front of it.
A GUI-launched Mac app does not inherit your shell profile, so a variable exported in ~/.zshrc may not reach the app-server. This is the expected first failure of any desktop-launched attempt, and the reason this guide routes through a terminal launch instead.
It would need a provider-aware model picker, which is what openai/codex#29156 asks for; that issue was open with activity on 5 August 2026. If it ships, the configuration above already defines the provider in the file the app reads, so nothing here would need to change.
Sources
Every figure above was read from these pages on August 2026. Vendors reprice without notice; if you find a stale number, tell us.
- OpenAI Codex: configuration model_providers, profiles, the reserved provider ids, and wire_api "responses" as the only supported value
- openai/codex#29156 the request for a provider-aware picker, plus the creation-time-only provider, the catalog replacement, and the desktop symptoms; open with activity on 5 August 2026
- openai/codex discussion 7782 the removal of wire_api = "chat", linked by the binary’s own error message
- Continuum pricing plan names, prices, and which tiers include personal API keys
- Continuum hosted inference the model lanes and the gateway surfaces, read 13 August 2026; the live /v1/models endpoint itself needs a cont_sk_ bearer