Repository navigation
Description
Area
Codex Desktop integration / authentication / Codex config injection
Goal
Provide an explicit opt-in mode that lets Codex Desktop use OpenCodex without requiring a ChatGPT OAuth login when the selected OpenCodex workflow does not need ChatGPT credentials.
This must remain an OpenCodex-scoped integration mode, not a global Codex authentication bypass.
Confirmed behavior
The original diagnostic established an important upstream fact:
model_provider = "opencodex"
[model_providers.opencodex]
name = "OpenCodex Proxy"
base_url = "http://127.0.0.1:10100/v1"
wire_api = "responses"
requires_openai_auth = falseWith OpenCodex stopped so it could not reconcile the file, Codex Desktop:
- skipped the ChatGPT OAuth login screen;
- entered the normal Desktop UI;
- routed a conversation through the local OpenCodex proxy.
So Codex Desktop does honor requires_openai_auth = false for a dedicated custom provider.
Current OpenCodex architecture
The implementation architecture changed after the original report.
Current dev uses Design B for normal loopback installs:
openai_base_url = "http://127.0.0.1:<port>/v1"
instead of permanently installing:
model_provider = "opencodex"
[model_providers.opencodex]
The reason is deliberate: loopback routing keeps Codex on its built-in openai provider and avoids provider retagging/history remapping.
During normal loopback reconciliation, OpenCodex removes the dedicated opencodex provider table and injects openai_base_url. This was observed directly in the full-flow test attached to this issue and is also documented in src/codex/inject.ts.
Non-loopback binds still need the dedicated provider-table path because the built-in provider cannot carry the OpenCodex admission header in the same way.
Therefore the original implementation prescription, "always write requires_openai_auth = false into the managed [model_providers.opencodex] table", is stale for the normal loopback path.
Remaining problem
There is still no supported OpenCodex setting for this workflow.
Users can prove authless Desktop behavior manually, but ocx start reconciles the configuration back to the normal openai_base_url shape. A manual edit is therefore not durable.
The feature now needs a solution that is compatible with the current injection architecture rather than reviving the old provider table unconditionally.
Required behavior
- Existing installs keep their current authenticated/default behavior unless the user explicitly opts in.
- The setting is durable across
ocx start, restart, sync, ensure, and normal config reconciliation. - The option affects only Codex Desktop/OpenCodex routing behavior. It must not disable authentication globally.
- Loopback OpenCodex admission remains safe. Authless Codex Desktop login must not be confused with exposing a non-loopback OpenCodex listener without admission authentication.
- CLI behavior remains unchanged unless explicitly designed otherwise.
- Disabling the option restores the normal supported OpenCodex injection path.
Implementation boundary
The implementation must first choose and prove a Codex-supported mechanism for the current loopback architecture.
Acceptable directions include:
A. Dedicated-provider mode only when authless Desktop is enabled
OpenCodex may intentionally switch the Codex config to a dedicated opencodex provider only for this opt-in mode, with:
requires_openai_auth = falseIf this direction is used, it must solve the additional behavior found in the full-flow test: the Desktop model selector was empty under the manually installed custom provider even though direct conversation routing worked.
The opt-in must therefore be a complete supported mode, not merely a login-screen bypass that leaves model selection degraded.
B. A verified Codex-supported authless control compatible with openai_base_url
If current Codex exposes a supported way to keep the built-in openai routing shape while declaring that Desktop login is unnecessary, OpenCodex may use that instead.
Do not invent or guess such a field. It must be verified against the current Codex configuration/app-server contract.
Non-loopback safety
Current non-loopback OpenCodex routing uses the dedicated provider table so Codex can send the OpenCodex admission credential.
Any authless Desktop option must preserve that data-plane admission boundary. It must never mean:
requires_openai_auth = false
=> disable OpenCodex network authentication
Those are separate authentication layers.
Suggested management surface
The exact public key can follow existing configuration conventions, for example conceptually:
{
"codex": {
"desktop": {
"authMode": "native"
}
}
}or:
{
"codex": {
"desktop": {
"requiresOpenAIAuth": false
}
}
}The public contract matters more than the exact field name:
default -> current behavior
authless opt-in -> supported Desktop routing mode without ChatGPT login
Acceptance criteria
- Codex Desktop is confirmed to honor
requires_openai_auth = falsefor a dedicated custom provider. - A conversation is confirmed to route through OpenCodex in that diagnostic mode.
- Current loopback OpenCodex injection is known to use
openai_base_urlrather than the old dedicated-provider table. - A first-class OpenCodex authless Desktop setting exists and defaults off.
- The implementation is compatible with the current loopback injection architecture.
-
ocx start, restart, sync, and reconciliation preserve the opt-in. - Desktop starts without the ChatGPT OAuth gate when the option is enabled.
- Model selection/catalog behavior remains usable in the supported authless mode.
- Requests continue to route through OpenCodex.
- Non-loopback OpenCodex admission authentication is not weakened.
- Disabling the option restores normal behavior.
- Existing CLI behavior remains unchanged.
- Tests cover default mode, authless loopback mode, reconciliation, disable/restore, and non-loopback safety.
Out of scope
- globally disabling Codex authentication;
- making non-loopback OpenCodex listeners unauthenticated;
- treating the empty custom-provider model selector as acceptable product behavior;
- unrelated Desktop model-default or catalog bugs unless they block the supported authless mode.
Activity
github-actions commentedon Aug 6, 2026
Automated translation bookkeeping — detected language: English.
Ingwannu commentedon Aug 6, 2026
There is a concrete OpenCodex-controlled boundary here, but I do not think a global auth bypass is safe to implement from the report alone.
Current
devdeliberately writesrequires_openai_auth = truein the managed[model_providers.opencodex]table (src/codex/inject.ts:195-215). Current Codex app-server/TUI source does honorrequires_openai_auth = falsefor a custom provider: it skips the login screen and reportsrequires_openai_auth: falsefrom account status. Therefore this is not inherently limited to the built-indeepseekprovider, and OpenCodex can influence the gate when it owns the dedicated-provider table.The important distinction is whether the failure is caused by OpenCodex rewriting the managed table back to
true, or by a separate Codex Desktop frontend restriction after app-server has already reported that auth is not required.Could you please test this exact diagnostic after stopping OpenCodex so it cannot rewrite the file during the test:
Then restart only Codex Desktop and report whether the login gate is skipped. Please also include the
hostnamevalue from the OpenCodex config (loopback vs0.0.0.0/LAN matters because OpenCodex uses different injection shapes).If that works, the maintainable scope is an explicit opt-in on the managed dedicated-provider injection while keeping the current default for users who depend on ChatGPT account-gated surfaces. If it still fails, the remaining gate is in the Desktop client and should be tracked upstream rather than worked around by guessing in the proxy. I am leaving this open for that result.
majia3592 commentedon Aug 7, 2026
Diagnostic test result
Tested the exact config you suggested. Login gate was skipped successfully.
Setup
Stopped OpenCodex, then manually edited
~/.codex/config.toml(without startingocx):Then restarted only Codex Desktop (no
ocx start).Result
model_provider = "opencodex"and the defaultrequires_openai_auth = true, the login gate always appearedHostname
OpenCodex config (
~/.opencodex/config.json) has no explicithostnamefield. Default is127.0.0.1(loopback).Implication
This confirms that
requires_openai_auth = falsein the managed[model_providers.opencodex]table is sufficient to bypass the Desktop OAuth gate. The maintainable path would be an explicit opt-in flag in OpenCodex injection — when the user sets a custom provider that does not need ChatGPT credentials, OpenCodex writesrequires_openai_auth = falseinstead of the currenttruedefault.majia3592 commentedon Aug 7, 2026
Full flow test — additional findings
Continued testing beyond the initial
requires_openai_auth = falsediagnostic.What we did
model_provider = "opencodex"+requires_openai_auth = falsein config.tomlmodel = "deepseek/deepseek-v4-flash"(proxy-compatible format)ocx start— models injected into catalog (13 models in models.json)What we observed
ocx startmodifies config.toml: removesmodel_provider, removesrequires_openai_auth, removes[model_providers.opencodex]section, injectsopenai_base_url. We had to re-addmodel_providerandrequires_openai_authafterocx start.ocx startmodifications do not affect an already-running Desktop instance.model_provider = "opencodex"— Desktop does not load models frommodel_catalog_jsonfor custom providers.modelin config.toml works — Desktop uses the specified model for conversations even though the selector is empty.Current state
Config restored to
model_provider = "deepseek"(original). Proxy stopped.majia3592 commentedon Aug 8, 2026
Follow-up: gpt-5.6-terra 404 on NEW conversations (Aug 8) — interception list gap
Current working setup on our side (pure China network, no chatgpt.com):
forced_login_method = "api"+preferred_auth_method = "apikey"+ dummy API key (key validation goes through the proxy, not OpenAI) — Desktop starts without the OAuth gate.config.toml:model = "opencode-go/deepseek-v4-flash",openai_base_url = "http://127.0.0.1:10100/v1"(auto-injected by ocx).Problem
When starting a new conversation in Desktop, the client requests the hard-coded default model gpt-5.6-terra (not the
modelline from config.toml). The proxy rejects it with:Existing conversations keep working (per-conversation model
opencode-go/deepseek-v4-flashis remembered), but every new conversation 404s in a loop. Meanwhile the proxy still returns 200 for the old conversation.Root cause (proxy side)
shadowCallInterceptonly matchesgpt-5.4-mini/gpt-5.6-lunaby default (DEFAULT_SHADOW_SOURCE_MODELSinsrc/lib/shadow-call.ts).gpt-5.6-terrais the main-conversation default model, not a helper call, so it is never rewritten — by design. But that means Desktop's hard-coded new-chat default has neither an interception path nor a canonical provider → 404.Suggestions
gpt-5.6-terra(or make the shadow-call source list prefix-configurable) so Desktop's new-chat default is rewritten instead of 404ing. Alternatively add a generic "unknown bare native slug → user-configured fallback model" rule in the router.forced_login_method=apiis set, it would help if Desktop respected themodelline for new conversations instead of falling back to its built-in default.ocx startstill strips themodelline (and previouslymodel_provider/requires_openai_auth) from config.toml on every proxy restart — a preserve-list for user-managed keys would eliminate the manual restore step.Environment: Windows 11, Codex Desktop (MSIX), opencodex v2.10.0, loopback 127.0.0.1:10100.
majia3592 commentedon Aug 8, 2026
Complete reproducible workflow: one-time login with internet, then stable China-network usage (our results)
Sharing the full working setup so other users in blocked networks can replicate it. This is the production configuration we have been running — every step below is tested on Windows 11 + Codex Desktop (MSIX) + opencodex v2.10.0.
Phase 1 — One-time preparation (with internet, ~10 min)
~/.opencodex/config.json:{ "port": 10100, "defaultProvider": "opencode-go", "providers": { "opencode-go": { "adapter": "openai-chat", "baseUrl": "https://opencode.ai/zen/go/v1", "authMode": "key", "liveModels": true }, "deepseek": { "adapter": "openai-responses", "baseUrl": "https://api.deepseek.com", "authMode": "key" }, "xiaomi": { "adapter": "anthropic", "baseUrl": "https://api.xiaomimimo.com/anthropic", "authMode": "key" } }, "shadowCallIntercept": { "enabled": true, "model": "opencode-go/mimo-v2.5", "sourceModels": ["gpt-5.4-mini", "gpt-5.6-luna", "gpt-5.6-terra"] } }setx NO_PROXY "127.0.0.1,localhost"Phase 2 — Switch to pure China network (daily driver)
ocx start, verifycurl -s --noproxy "*" http://127.0.0.1:10100/healthz.~/.codex/config.toml:model = "opencode-go/deepseek-v4-flash"preferred_auth_method = "apikey"+forced_login_method = "api"← bypasses the Desktop OAuth gateopenai_base_url = "http://127.0.0.1:10100/v1"(auto-injected)sk-test123) — validation goes through the proxy, which does not check it. No chatgpt.com involved.Result (verified)
gpt-5.6-terrais intercepted by thesourceModelslist → no more 404 loop.modelline + restart Desktop (model selector is empty in API-key mode; that is expected).ocx startstrips themodelline from config.toml — restore it (a preserve-list for user-managed keys would remove this manual step).Hints for the maintainer
The generic fix that would benefit all users: route unknown bare native slugs (like
gpt-5.6-terrawhen the catalog does not contain it) to a user-configured fallback model instead of failing withrequires the canonical openai provider404 — and/or includegpt-5.6-terrain the default shadow-call source list.Ingwannu commentedon Aug 9, 2026
The diagnostic result confirms the important boundary: OpenCodex can control the Desktop login gate through the managed provider table, and requires_openai_auth = false works when the proxy is not rewriting that table.\n\nThe safe implementation scope is therefore an explicit opt-in dedicated-provider mode that preserves the managed model_provider table and user-selected model while setting requires_openai_auth = false. I would not make unknown native slugs or gpt-5.6-terra silently route through shadowCallIntercept by default; helper-call interception and the main new-chat model are different semantics, and a global fallback can hide configuration errors.\n\nThe empty selector under a custom provider is still a Desktop/upstream limitation. Because this changes authentication and product behavior rather than fixing a narrow adapter bug, I am leaving the implementation decision to @lidge-jun. The reported manual configuration is useful as a diagnostic workaround, but we should not document dummy-key acceptance as the final supported flow.
[-]Skip OAuth check for custom providers in Desktop (China/corporate network support)[/-][+][Feature]: add opt-in authless Codex Desktop mode for OpenCodex provider[/+][-][Feature]: add opt-in authless Codex Desktop mode for OpenCodex provider[/-][+][Feature]: add opt-in authless Codex Desktop routing mode[/+]lidge-jun commentedon Aug 19, 2026
리뷰 · 우선순위 71 / 80
현재
dev의 루프백 주입은 Design B입니다.src/codex/inject.ts는 전용[model_providers.opencodex]를 상시 설치하지 않고, 내장openai프로바이더에openai_base_url = "http://127.0.0.1:<port>/v1"를 씁니다. 전용 테이블이 남을 때requires_openai_auth = true가 명시됩니다. 그래서 이슈의 예전 처방(“항상 전용 테이블에 false를 써라”)은 현재 아키텍처와 어긋납니다.이슈가 원하는 것은 ChatGPT OAuth가 필요 없는 워크플로를 위한 명시적 옵트인입니다. 수동으로
model_provider = "opencodex"와requires_openai_auth = false를 넣으면 Desktop이 로그인 게이트를 건너뛰는 것은 재현됐습니다. 그러나ocx start가 설정을 다시openai_base_url형태로 맞추면 그 편집은 사라집니다. 지속 가능한 OpenCodex 설정이 없습니다.네이티브 신뢰성이 점수 이유입니다. 전역 인증 우회는 안 됩니다. 루프백 기본 경로를 전용 테이블로 되돌리면 히스토리 리태깅/프로바이더 재매핑이 다시 생기고, 비루프백 바인딩은 입장 헤더 때문에 전용 테이블이 필요합니다. Windows + 차단된 chatgpt.com 환경의 실사용 코멘트가 이 공백을 보여 줍니다. 더미 API 키와
forced_login_method = "api"는 우회이지 제품 계약이 아닙니다.서비스/자동시작에서도 같은 조정자가 파일을 다시 씁니다. 옵트인 플래그가 조정 대상이 아니면
ocx start와 서비스 재기동이 로그인 게이트를 되돌립니다. 위생적으로는 OpenCodex 범위 모드여야 하고, 사용자 소유openai_base_url을 덮어쓰면 안 됩니다.해결방안은 기본 루프백 경로를 유지한 채, 옵트인일 때만 전용
opencodex프로바이더 테이블을 보존하고requires_openai_auth = false를 쓰며 사용자 선택 모델을 유지하는 것입니다. 기본값은 지금과 같아야 합니다. 패치는 추측하지 않으며, 현재 트리에 authless 설정 키는 없습니다.이 댓글은 grok-bot이 작성했습니다
docs(devlog): fold the A-phase audit blockers into the backlog plan
feat(codex): opt-in authless Codex Desktop routing mode (#1107) (#3207)
lidge-jun commentedon Sep 1, 2026
Landed on
devvia #3207 (squash4a382beed).What shipped:
codexDesktopAuthless: truein config.json, orocx system settings --desktop-authless on, or PUT/api/settings. Default off keeps today's loopback injection byte-for-byte.model_provider = "opencodex"plus[model_providers.opencodex]withrequires_openai_auth = falseand noenv_key, so Desktop opens without the ChatGPT login and routes through the proxy. The setting is reconciled byocx start, restart, sync, and ensure; the fallback profile mirrors the form.openai_base_urlform on the next sync;ocx restorestrips it like any injected routing.requires_openai_auth = trueand theenv_keyadmission credential are unchanged, so the data-plane admission boundary is untouched.Known limits, documented in the guide: ChatGPT-gated Desktop chrome (account, usage, Fast) stays dark in this mode, and Desktop releases that filter the picker against a native-only allowlist may show an empty or
Custompicker (upstream openai/codex#19694); requests still use the configured model andmodel = "<provider>/<id>"in config.toml is the workaround. OpenCodex has no hook into that renderer allowlist, so the empty picker is not something this repository can fix.feat(codex): opt-in authless Codex Desktop routing mode (lidge-jun#1107…
feat(codex): opt-in authless Codex Desktop routing mode (lidge-jun#1107…