summary
Codex Mobile / Remote Control does not currently provide reliable new-thread support when the connected desktop host uses a custom Codex Pooler model provider.
A thread created from mobile can be persisted and executed by the connected desktop host while being initialized with the built-in openai model provider instead of the host's configured custom provider. The model request can then bypass Codex Pooler and use the OpenAI/ChatGPT account path available to the host.
By contrast, a thread created on Codex Desktop with the Codex Pooler provider and later resumed from mobile generally retains its persisted provider when the client does not submit a model/provider override and the persisted thread metadata is available.
Status checked August 13, 2026: no fix for Remote new-thread provider inheritance is present in current upstream main or the checked public release tags and release branches. The desktop-first workaround below remains the only evidence-backed workaround.
upstream context
The direct upstream reports are:
- openai/codex#23659 documents the likely Android root condition: Remote sends
modelProvider=openai as a client default, and app-server treats it as an explicit override instead of letting the host configuration resolve the provider
- openai/codex#31370, updated August 10, reports Android Remote creating usable host-local threads with
model_provider=openai instead of the configured host provider; this remains the closest match to the Codex Pooler routing problem
- openai/codex#33054, opened after this issue and updated July 31, independently reports the same provider mismatch: the Remote picker can expose a custom-catalog model while a new mobile-created thread persists as
model_provider=openai and uses the ChatGPT account path
An upstream commit 43dfb545 implements the normalization proposed in #23659: Android Remote's default openai value is treated as no provider override, while deliberate non-default provider choices are preserved. The change also covers resume and fork. However, that commit belongs to a divergent, unmerged lineage. It is absent from current main and from the checked public releases through rust-v0.148.0-alpha.12, so it must not be treated as shipped.
Configuration and permission reports provide supporting context but are not provider-routing proof:
- openai/codex#25186 was closed by its reporter on August 4 with an unqualified
fixed comment, but has no linked maintainer confirmation, PR, commit, release note, or provider-routing verification
- openai/codex#24270 remains open and shows that mobile-selected permission settings can diverge from the effective host configuration; this concerns approval/sandbox state, not the model provider or Pooler credential
Related thread visibility reports must also remain causally separate:
- openai/codex#24780, openai/codex#24648, and openai/codex#35617 show a provider-filtered history failure: omitted or
null modelProviders defaults to the currently configured provider, while an empty list means all providers. A valid custom-provider thread can therefore disappear from a refreshed list without being deleted or rerouted
- openai/codex#22800, openai/codex#30123, and the canonical sidebar issue openai/codex#30895 cover additional mobile-created versus desktop-created thread lifecycle, restore, project-association, and sidebar synchronization differences. These remain relevant context, but do not establish the provider-routing cause
- openai/codex#31187 tracks host/account identity ambiguity. Official Remote documentation now describes pairing and switching between multiple hosts under the same account and workspace, but simultaneous multi-account operation and durable thread-to-host provenance remain unclear
A broader non-Remote report, openai/codex#37245, describes a custom model remaining selected while the reporter observed sampling traffic going to ChatGPT/OpenAI endpoints rather than the configured custom endpoint. This is reporter evidence from a desktop build, not a confirmed universal behavior, but it reinforces the verification rule for this issue: a model name or successful response is not routing proof.
current Codex behavior
Current app-server source explains the start/resume difference:
thread/start accepts client-provided model/provider values as configuration overrides. An explicit modelProvider takes precedence over the host's configured provider
- if
modelProvider is omitted, the configured host model_provider is used when present; built-in openai is the final fallback
thread/resume restores the provider persisted with a non-running thread when persisted metadata is available and the client does not submit a model/provider override
- explicit resume overrides, already-loaded threads, or missing persisted metadata can change those semantics, so resumption must still be verified rather than assumed
This means the failure is not that every Remote start always selects openai. The demonstrated Android failure is that the client can submit its default openai value as an authoritative override, preventing the host configuration from winning.
impact on Codex Pooler users
- A successful mobile response can create the false impression that the request used Codex Pooler
- Pool policy, upstream selection, quota accounting, and request logs are bypassed when the effective request never reaches Pooler
- Usage can be charged against the OpenAI/ChatGPT account path instead of a Pool-selected upstream
- A custom-catalog model can appear selectable but fail at runtime because the mobile-created thread uses built-in
openai
- Custom-provider threads can also be hidden by provider-filtered history or remain absent from normal Desktop/mobile project lists even when their local thread state is intact
current workaround
Create the thread on Codex Desktop while the Codex Pooler provider is active, then open or resume that existing thread from mobile.
This normally preserves the provider stored in the desktop-created thread when the mobile client does not submit a model/provider override. Creating a brand-new thread from mobile should not currently be documented as guaranteed to use Codex Pooler.
The workaround should be verified for the actual client build by checking the resumed thread's effective provider and a matching Codex Pooler request row. Thread visibility or a successful response alone is insufficient.
configuration constraints
The provider id alone is not routing proof. In current Codex, model_provider = "openai" is a valid selection of the built-in provider, and the top-level openai_base_url can redirect that provider. What Codex rejects is redefining the reserved built-in id through [model_providers.openai].
Current Codex Pooler documentation therefore uses distinct Codex provider ids such as codex-pooler-ws and codex-pooler-http, with name = "OpenAI" to preserve OpenAI-family client behavior. Other clients can legitimately use an openai provider id in their own configuration schema; that is a separate namespace and should not be generalized to Codex's reserved provider table.
openai_base_url changes the built-in openai provider's API endpoint, but it does not configure a Pool API-key credential for that provider. On a Remote host signed in with ChatGPT, built-in openai uses the first-party Codex authentication available to the client. Replacing that sign-in with API-key authentication changes the account mode and can remove account-dependent features required by Remote, so it is not an established Mobile workaround.
For a custom Codex Pooler provider, the recommended configuration remains env_key = "CODEX_POOLER_API_KEY". Codex resolves that provider-scoped key before falling back to global Codex/ChatGPT authentication. If the environment variable is missing or empty, provider authentication fails.
Codex also supports experimental_bearer_token = "<pool-api-key>" inside a custom provider block. This can be used as a short-lived diagnostic to distinguish an environment-propagation failure from a provider-selection failure, but it is discouraged for normal use because it stores the secret directly in config.toml.
Hardcoding the bearer only helps when the effective provider is still the custom Codex Pooler provider. If a mobile-created thread persists as model_provider=openai, the custom provider block, its env_key, and its hardcoded bearer are all bypassed. It therefore does not work around the primary Remote thread/start provider-inheritance defect documented here.
requires_openai_auth is independent of env_key:
true can preserve account-dependent Codex/Desktop features while env_key still supplies the bearer token sent to Codex Pooler
false provides a gateway-only, fail-closed configuration but may make account-dependent Desktop, app-server, or mobile features unavailable
Codex Pooler runtime routes require a Pool API-key bearer token before dispatch, routing, and accounting. A correct URL, provider name, model name, or successful response does not prove that Pooler handled the request.
This issue should not lead to proxying ChatGPT control-plane, account, identity, pairing, realtime, or app-server helper routes. Codex Pooler supports authenticated model-provider traffic through its explicit runtime routes; it is not a wildcard Remote Control proxy.
proposed repository scope
- Add a public Codex Mobile / Remote Control limitation section to the Codex CLI client documentation and docs site
- State explicitly that mobile-created new threads are not currently guaranteed to use Codex Pooler
- Distinguish Remote
thread/start from resuming a desktop-created thread
- Name
thread/start, thread/resume, pairing, account, identity, permission-profile, and realtime helpers as unsupported Pooler proxy surfaces; clarify that Remote communicates with the host app-server and only the resulting model-provider request may reach Pooler
- Explain that
requires_openai_auth controls local account-dependent client behavior and does not enable app-server or Remote helper proxying
- Document direct bearer configuration only as a diagnostic for environment propagation, not as a permanent credential recommendation or a fix for provider selection
- Keep the direct provider reports, the unmerged normalization commit, and the separate visibility/permission issue families linked so the limitation can be revisited without conflating their causes
- Add a metadata-only verification procedure that compares desktop-created/resumed and mobile-created/new threads
acceptance criteria
- Public documentation clearly distinguishes mobile
thread/start from resuming a desktop-created thread
- The documented workaround does not imply that every resumed or mobile-created turn is accounted by Codex Pooler
- Verification records the request-side provider override, the effective/persisted provider, the actual request destination, the credential class or safe fingerprint, and the corresponding Pooler request/accounting row
- Verification covers both a desktop-created thread resumed from mobile and a brand-new mobile-created thread
- Provider-filtered history, sidebar synchronization, permission inheritance, and host/account selection are tested or documented as separate boundaries rather than treated as proof of provider routing
- Any future configuration recommendation proves both routing and authentication through a Pool API key
- Verification distinguishes environment propagation from provider selection by testing the same custom provider with
env_key and, only in a disposable diagnostic configuration, a direct bearer token
- Any future implementation remains compatible with multi-node Codex Pooler deployments and preserves the current explicit model-provider-only proxy boundary unless that product scope is deliberately changed
summary
Codex Mobile / Remote Control does not currently provide reliable new-thread support when the connected desktop host uses a custom Codex Pooler model provider.
A thread created from mobile can be persisted and executed by the connected desktop host while being initialized with the built-in
openaimodel provider instead of the host's configured custom provider. The model request can then bypass Codex Pooler and use the OpenAI/ChatGPT account path available to the host.By contrast, a thread created on Codex Desktop with the Codex Pooler provider and later resumed from mobile generally retains its persisted provider when the client does not submit a model/provider override and the persisted thread metadata is available.
Status checked August 13, 2026: no fix for Remote new-thread provider inheritance is present in current upstream
mainor the checked public release tags and release branches. The desktop-first workaround below remains the only evidence-backed workaround.upstream context
The direct upstream reports are:
modelProvider=openaias a client default, and app-server treats it as an explicit override instead of letting the host configuration resolve the providermodel_provider=openaiinstead of the configured host provider; this remains the closest match to the Codex Pooler routing problemmodel_provider=openaiand uses the ChatGPT account pathAn upstream commit
43dfb545implements the normalization proposed in #23659: Android Remote's defaultopenaivalue is treated as no provider override, while deliberate non-default provider choices are preserved. The change also covers resume and fork. However, that commit belongs to a divergent, unmerged lineage. It is absent from currentmainand from the checked public releases throughrust-v0.148.0-alpha.12, so it must not be treated as shipped.Configuration and permission reports provide supporting context but are not provider-routing proof:
fixedcomment, but has no linked maintainer confirmation, PR, commit, release note, or provider-routing verificationRelated thread visibility reports must also remain causally separate:
nullmodelProvidersdefaults to the currently configured provider, while an empty list means all providers. A valid custom-provider thread can therefore disappear from a refreshed list without being deleted or reroutedA broader non-Remote report, openai/codex#37245, describes a custom model remaining selected while the reporter observed sampling traffic going to ChatGPT/OpenAI endpoints rather than the configured custom endpoint. This is reporter evidence from a desktop build, not a confirmed universal behavior, but it reinforces the verification rule for this issue: a model name or successful response is not routing proof.
current Codex behavior
Current app-server source explains the start/resume difference:
thread/startaccepts client-provided model/provider values as configuration overrides. An explicitmodelProvidertakes precedence over the host's configured providermodelProvideris omitted, the configured hostmodel_provideris used when present; built-inopenaiis the final fallbackthread/resumerestores the provider persisted with a non-running thread when persisted metadata is available and the client does not submit a model/provider overrideThis means the failure is not that every Remote start always selects
openai. The demonstrated Android failure is that the client can submit its defaultopenaivalue as an authoritative override, preventing the host configuration from winning.impact on Codex Pooler users
openaicurrent workaround
Create the thread on Codex Desktop while the Codex Pooler provider is active, then open or resume that existing thread from mobile.
This normally preserves the provider stored in the desktop-created thread when the mobile client does not submit a model/provider override. Creating a brand-new thread from mobile should not currently be documented as guaranteed to use Codex Pooler.
The workaround should be verified for the actual client build by checking the resumed thread's effective provider and a matching Codex Pooler request row. Thread visibility or a successful response alone is insufficient.
configuration constraints
The provider id alone is not routing proof. In current Codex,
model_provider = "openai"is a valid selection of the built-in provider, and the top-levelopenai_base_urlcan redirect that provider. What Codex rejects is redefining the reserved built-in id through[model_providers.openai].Current Codex Pooler documentation therefore uses distinct Codex provider ids such as
codex-pooler-wsandcodex-pooler-http, withname = "OpenAI"to preserve OpenAI-family client behavior. Other clients can legitimately use anopenaiprovider id in their own configuration schema; that is a separate namespace and should not be generalized to Codex's reserved provider table.openai_base_urlchanges the built-inopenaiprovider's API endpoint, but it does not configure a Pool API-key credential for that provider. On a Remote host signed in with ChatGPT, built-inopenaiuses the first-party Codex authentication available to the client. Replacing that sign-in with API-key authentication changes the account mode and can remove account-dependent features required by Remote, so it is not an established Mobile workaround.For a custom Codex Pooler provider, the recommended configuration remains
env_key = "CODEX_POOLER_API_KEY". Codex resolves that provider-scoped key before falling back to global Codex/ChatGPT authentication. If the environment variable is missing or empty, provider authentication fails.Codex also supports
experimental_bearer_token = "<pool-api-key>"inside a custom provider block. This can be used as a short-lived diagnostic to distinguish an environment-propagation failure from a provider-selection failure, but it is discouraged for normal use because it stores the secret directly inconfig.toml.Hardcoding the bearer only helps when the effective provider is still the custom Codex Pooler provider. If a mobile-created thread persists as
model_provider=openai, the custom provider block, itsenv_key, and its hardcoded bearer are all bypassed. It therefore does not work around the primary Remotethread/startprovider-inheritance defect documented here.requires_openai_authis independent ofenv_key:truecan preserve account-dependent Codex/Desktop features whileenv_keystill supplies the bearer token sent to Codex Poolerfalseprovides a gateway-only, fail-closed configuration but may make account-dependent Desktop, app-server, or mobile features unavailableCodex Pooler runtime routes require a Pool API-key bearer token before dispatch, routing, and accounting. A correct URL, provider name, model name, or successful response does not prove that Pooler handled the request.
This issue should not lead to proxying ChatGPT control-plane, account, identity, pairing, realtime, or app-server helper routes. Codex Pooler supports authenticated model-provider traffic through its explicit runtime routes; it is not a wildcard Remote Control proxy.
proposed repository scope
thread/startfrom resuming a desktop-created threadthread/start,thread/resume, pairing, account, identity, permission-profile, and realtime helpers as unsupported Pooler proxy surfaces; clarify that Remote communicates with the host app-server and only the resulting model-provider request may reach Poolerrequires_openai_authcontrols local account-dependent client behavior and does not enable app-server or Remote helper proxyingacceptance criteria
thread/startfrom resuming a desktop-created threadenv_keyand, only in a disposable diagnostic configuration, a direct bearer token