Observed behavior
LLxprt 0.11.0 on macOS arm64 cannot preserve a saved Codex profile's behavior when its base URL is changed to a loopback reverse proxy. A named-profile headless run exits 1 with HTTP 400 {"detail":"Store must be set to false"}. The provider decides Codex mode from an upstream-host substring rather than the selected codex provider.
Reproduction
With an existing authenticated saved astra profile (provider: codex, model gpt-6-astra, original base URL https://chatgpt.com/backend-api/codex) and a transparent loopback reverse proxy forwarding /backend-api/codex to the original upstream:
llxprt --profile-load astra \
--baseurl http://127.0.0.1:18443/backend-api/codex \
--extensions none --approval-mode default --nobrowser \
--prompt 'Reply with exactly PRAXIS_OK. Do not use tools.' </dev/null
The smoke working directory's .llxprt/settings.json contains {"coreTools":[],"mcpServers":{},"telemetry":{"enabled":false},"hooks":{"enabled":false}}.
Actual: Non-interactive run failed: [API Error: Client error: Unknown error (Status: 400, body: {"detail":"Store must be set to false"})].
Expected: selecting codex should retain Codex OAuth/account-header and request semantics when using an explicitly configured reverse-proxy endpoint, independently of the endpoint hostname.
Source evidence
packages/providers/src/openai-responses/OpenAIResponsesProviderBase.ts: constructor and isCodexMode() use baseURL?.includes('chatgpt.com/backend-api/codex'). Installed JS lines 40, 46-51, 72-73 wire OAuth support/manager and mode detection through this condition. Current local TS counterparts are lines 57 and 101.
packages/providers/src/openai-responses/openAIResponsesExecutor.ts: applyCodexRequestSettings() returns early when that detection is false. The skipped behavior includes setting store = false and removing Codex-unsupported parameters. Installed JS lines 418-432; current local TS function starts at line 844.
OpenAIResponsesProviderCore also uses the same detection for Codex WebSocket behavior.
Named-profile loading matters: an earlier inline --profile reproduction instead failed with OpenAI API key is required, but #3448 already tracks inline-profile OAuth initialization. The named-profile failure above reproduces separately and does not justify claiming that every localhost override fails authentication.
Control and scope
Praxis AI v0.3.0/core 0.5.3 was the reverse proxy used here. A direct HTTP/SSE request through the same listener with the existing OAuth credential held only in memory, store:false, and Codex headers returned HTTP 200, response.completed, and the expected text. Four model controls passed in the initial setup; Astra was repeated after the named-profile failure. This report concerns LLxprt's endpoint-based mode selection, not a claim that Praxis caused it.
No LLxprt code was patched, no URL-substring workaround was used, and no tokens were embedded in profiles. Existing profiles and subagent assignments were preserved. Full tool, WebSocket, multimodal, and refresh-cycle verification remains out of scope for this reproduction.
Duplicate searches covered Codex proxy, localhost, base URL, and the exact hostname substring. #3448 is related but describes a different initialization path.
Recreated by request after the original llxprt-authored issue became unavailable due to account flagging. Content preserved verbatim from the original report.
Observed behavior
LLxprt 0.11.0 on macOS arm64 cannot preserve a saved Codex profile's behavior when its base URL is changed to a loopback reverse proxy. A named-profile headless run exits 1 with HTTP 400
{"detail":"Store must be set to false"}. The provider decides Codex mode from an upstream-host substring rather than the selectedcodexprovider.Reproduction
With an existing authenticated saved
astraprofile (provider: codex, modelgpt-6-astra, original base URLhttps://chatgpt.com/backend-api/codex) and a transparent loopback reverse proxy forwarding/backend-api/codexto the original upstream:The smoke working directory's
.llxprt/settings.jsoncontains{"coreTools":[],"mcpServers":{},"telemetry":{"enabled":false},"hooks":{"enabled":false}}.Actual:
Non-interactive run failed: [API Error: Client error: Unknown error (Status: 400, body: {"detail":"Store must be set to false"})].Expected: selecting
codexshould retain Codex OAuth/account-header and request semantics when using an explicitly configured reverse-proxy endpoint, independently of the endpoint hostname.Source evidence
packages/providers/src/openai-responses/OpenAIResponsesProviderBase.ts: constructor andisCodexMode()usebaseURL?.includes('chatgpt.com/backend-api/codex'). Installed JS lines 40, 46-51, 72-73 wire OAuth support/manager and mode detection through this condition. Current local TS counterparts are lines 57 and 101.packages/providers/src/openai-responses/openAIResponsesExecutor.ts:applyCodexRequestSettings()returns early when that detection is false. The skipped behavior includes settingstore = falseand removing Codex-unsupported parameters. Installed JS lines 418-432; current local TS function starts at line 844.OpenAIResponsesProviderCorealso uses the same detection for Codex WebSocket behavior.Named-profile loading matters: an earlier inline
--profilereproduction instead failed withOpenAI API key is required, but #3448 already tracks inline-profile OAuth initialization. The named-profile failure above reproduces separately and does not justify claiming that every localhost override fails authentication.Control and scope
Praxis AI v0.3.0/core 0.5.3 was the reverse proxy used here. A direct HTTP/SSE request through the same listener with the existing OAuth credential held only in memory,
store:false, and Codex headers returned HTTP 200,response.completed, and the expected text. Four model controls passed in the initial setup; Astra was repeated after the named-profile failure. This report concerns LLxprt's endpoint-based mode selection, not a claim that Praxis caused it.No LLxprt code was patched, no URL-substring workaround was used, and no tokens were embedded in profiles. Existing profiles and subagent assignments were preserved. Full tool, WebSocket, multimodal, and refresh-cycle verification remains out of scope for this reproduction.
Duplicate searches covered Codex proxy, localhost, base URL, and the exact hostname substring. #3448 is related but describes a different initialization path.
Recreated by request after the original
llxprt-authored issue became unavailable due to account flagging. Content preserved verbatim from the original report.