Support custom model providers in app
What version of the Codex App are you using (From “About Codex” dialog)?
260205.1301 (554)
What subscription do you have?
None
What issue are you seeing?
I'm using custom model provider for Codex CLI and App. In CLI, /model is available and switching models works as expected. However, in Codex App, this happens (notice the absence of model switcher):
<img width="2558" height="336" alt="Image" src="https://github.com/user-attachments/assets/c6181aaf-7681-4049-91ad-dd79d81f2dd2" />
What steps can reproduce the bug?
- set up custom model provider & profile
```toml
profile = "internal"
[features]
# remote_models = false
[profiles.internal]
# model = "gpt-5.2"
model_provider = "internal"
model_reasoning_effort = "medium"
[model_providers.internal]
name = "Interal LLM Gateway"
base_url = "http://llms.example.com/v1"
wire_api = "responses"
```
- launch Codex App
What is the expected behavior?
It should provider the same model switcher as in ChatGPT subscription mode:
<img width="2570" height="352" alt="Image" src="https://github.com/user-attachments/assets/291d0409-ab49-4eec-8f7b-0317ffc648f2" />
Additional information
_No response_
20 Comments
Ran into the same thing
I'm using a custom model provider behind an internal gateway and hit exactly this: CLI works great (
/modellets me switch), but the Desktop app (v26.217.1959, build 669, as of Feb 19 2026) just... doesn't show the model picker at all.Spent some time tracing through the Electron bundle to figure out what's going on. For anyone unfamiliar, the Codex Desktop app is an Electron app, and you can extract its bundled source from the asar archive at
Codex.app/Contents/Resources/app.asarusingnpx asar extract.Root cause: In the frontend JS (
index-X7Ur8m0p.jsinside the extracted asar), the composer footer component conditionally renders both the model picker and the reasoning effort picker only whenrequiresAuthis truthy:When you use a custom model provider without a ChatGPT or OpenAI API key login, the frontend sees
requiresAuth = falseand the entire picker block gets skipped. The backend side is actually fine — models pass filtering correctly and the frontend allowlist (mft) includes models likegpt-5.2-codexandgpt-5.2for non-ChatGPT auth. It's purely a UI gating issue.Also worth noting: the source on
mainas of Feb 21 2026 has amodel_catalog_jsonconfig key (incodex-rs/config/src/lib.rs) that looks like it was meant to help with this — letting you point to a local model catalog file. But it doesn't exist in the current shipped binary (v26.217.1959, build 669). Setting it inconfig.tomlis silently ignored.What I think the fix would look like:
The conditional should render the model picker regardless of auth mode when there are models available. Something like showing the picker when
requiresAuth || hasCustomProvider— the model filtering logic already handles scoping the list correctly per auth type.Would love to see this fixed since the Desktop app is otherwise really nice with custom providers.
Ran into the same/similar problem
We are using LiteLLM as a proxy to expose custom models via
/v1/models. The endpoint correctly returns our custom model IDs, for example:Problem:
The issue is not with LiteLLM or the endpoint itself.
The problem is that Codex CLI and Codex Desktop UI do not properly support or expose these custom models:
config.tomlExpected Behavior:
/v1/modelsWhy this matters:
Without this, using LiteLLM as a model gateway breaks the UX:
Quick question @iwinux @harshit97
Have any of you managed to get the gateway's /v1/models endpoint to properly populate the model list in the Codex CLI?
In our case, the endpoint returns the custom models correctly, but the CLI doesn’t seem to expose them as selectable options (we still need to manually set the model ID).
Just trying to understand if this is a general limitation or if someone has found a workaround.
Thanks!
Just add
under your provider.
then, restart the app. if the app asks you to login, choose api key, and enter any character then press enter
this is a workaround
it worked for me. thanks
Latest version on macOS (
Version 26.406.31014 (1395)) seems to have fixed the issue. Is there any changelog entry confirming this?It only allows one profile though...
Do you know if the model_catalog_json is working correctly? As of now I tried using it for a custom picker of models in our org, but it ignored all of them except the 5.3 codex slug, I assume because thats an existing openai model?
The same issue, configure a custom model, the custom model does not appear in the codex app, and it is also not possible to select the custom model (only official models are available)
Does anyone have an example with a workaround?
Any news on this?
any news on this issue?
+1
Please add a custom model selector
Codex is a good app and we dont want to migrate to other tools like Cline/Roo/Windsurf/Continue/etc
Currently for changing model from .toml file, should restart VSCode/Extension!!!
even more annoying is that threads are segregated by provider. So if I change provider and restart I lose all previous threads...
Adding another gateway-user data point here: the picker really shouldn’t be tied to the ChatGPT/OpenAI auth path.
A lot of teams are running Codex behind an OpenAI-compatible
/v1gateway for routing, fallback, usage limits, or centralized billing. In that setup the important thing is: if a custom provider hasbase_url+wire_api = "responses"and/v1/modelsreturns usable IDs, the app should expose those models just like the CLI does.For anyone testing external gateways, I’d treat this the same way as LiteLLM/OpenRouter-style providers: keep the model IDs exactly as the gateway returns them and point Codex at a Responses-compatible base URL. For example,
https://kiroforge.cloud/v1is OpenAI-compatible, so it falls into the same class of custom-provider UX issues being discussed here.The workaround with
requires_openai_auth = trueis useful, but long-term it would be much nicer if the Desktop app rendered the model picker whenever a custom provider has a discoverable model list, regardless of auth mode.@bakaburg1 Exactly
Blocking
ab.chatgpt.comand removingleveldbcan be temporary solution for not changing your provider, as it relates to service policies obtained online.On Windows you can add
127.0.0.1 ab.chatgpt.comtoC:\Windows\System32\drivers\etc\hostsand delete~\AppData\Local\Packages\OpenAI.Codex_<some hash>\LocalCache\Roaming\Codex\web\Codex\Default\Local Storage\leveldbHowever this would cause some other issue e.g. missing
Approve for mePretty sure that OpenAI has no plan to improve this, cause they want to ensure that their closed app can use their close models only.
I rechecked this against Codex CLI
0.144.5. The current source now has most ofthe transport needed for a custom provider to own its remote model catalog, but
not yet the provider-scoped authoritative semantics a gateway needs.
Current
0.144.5behavior:ModelProviderInfosupports command-backed bearer auth throughauth, andcommand-auth providers are eligible for remote model refresh.
{base_url}/models?client_version=...with the provider's auth,expects the Codex
{ "models": [ModelInfo...] }schema, captures the responseETag, and applies a five-second request deadline.OnlineIfUncachedusesmodels_cache.jsonwith a five-minute TTL; an ETagchange can trigger an online refresh.
custom command-auth provider, remote entries are merged into the bundled
OpenAI catalog.
that switching providers can reuse another provider's fresh cache entry.
model_catalog_jsonis global and startup-only. It is not a catalog contractattached to one
model_providers.<id>entry.Pinned source evidence:
ModelProviderInfoand command auth/modelstransport and five-second timeout{ models }decoding and ETag capture0.144.5generated config schemaCould custom providers opt into an explicit provider-scoped mode, for example:
Suggested semantics for
authoritative_remote:remote catalog replaces bundled models for that provider instead of merging
unrelated OpenAI presets.
mode, and Codex client version. It never includes or persists bearer tokens.
OnlineIfUncachedmay use only a fresh matching provider cache.On a cache miss, run command auth and fetch within the existing deadline. A
failure must not fall back to another provider's cache or bundled catalog;
retain the explicit configured model and surface the catalog error instead.
renews that cache's TTL; a changed ETag forces an online refresh.
If-None-Matchduring refresh.304retains the scoped snapshot andrenews its TTL; a valid
200atomically replaces models and ETag.model_catalog_json, or documentone deterministic precedence rule.
Useful acceptance tests:
CODEX_HOMEnever reuse each other'smodels or ETag;
provider;
304preserves the snapshot, while200replaces rather than merges it;This complements, but does not by itself close, #10867. Provider-scoped catalog
truth is the backend requirement; Desktop still needs to render and select the
models returned for a custom provider. If #10867 should remain focused on the
picker, this catalog-mode work could be tracked as a linked model-provider issue.
@zierocode do you say that there is good news on this feature request?