[Windows App][Remote SSH] Ultra chat selection silently downgrades the remote config.toml default
What version of the Codex App are you using (From “About Codex” dialog)?
Windows Codex Desktop client 26.721.41059 (captured in the remote app-server logs as app_server.client_name="Codex Desktop").
Remote-side components observed during the incident:
- global
codex-cli 0.145.0 - long-lived app-server reported as
0.144.1 - bundled remote binary
codex-cli 0.146.0-alpha.3.1
What subscription do you have?
ChatGPT-authenticated account. The exact tier is not exposed in the redacted remote-side diagnostics.
What platform is your computer?
Windows Codex Desktop connecting over Remote SSH to:
Linux 6.8.0-124-generic x86_64 x86_64
What issue are you seeing?
I intentionally keep the remote Linux user default pinned in ~/.codex/config.toml:
model = "gpt-5.6-sol"
model_reasoning_effort = "ultra"
plan_mode_reasoning_effort = "ultra"
service_tier = "default"
After using the Windows Codex App with an SSH project, the remote model_reasoning_effort has intermittently been changed to low, so later local CLI threads on the Linux host start below the explicit durable default. I have to edit it back to ultra manually.
The most concerning behavior is the scope mismatch: Ultra is presented as applying “for this conversation”, but the implementation computes a non-Ultra fallback for future threads and persists that fallback to the user-level config. On an SSH project, the config belongs to the remote Linux user, so a desktop chat can silently change defaults used later by unrelated local CLI sessions.
Local forensic timeline on 2026-07-25 (AEST, UTC+10):
17:30:22: an SSH-launchedcodex app-server proxystarted.17:30:23: the remoteconfig.tomlinode was created/replaced, consistent with an atomic config rewrite.- The file was later observed with the lower effort and manually repaired to
ultraat18:35:19. 18:44:32: another SSH/app-server proxy started.18:44:47:config.tomlwas automatically written again. The retained diff for this second write only changedmarketplaces.openai-bundled.last_updated, which confirms that the connection lifecycle can mutate the remote config, although it did not reproduce the effort downgrade on that pass.
Important evidence boundary: the pre-repair file containing low was not retained, so the exact RPC payload for that specific downgrade is not available. The recurring ultra -> low observation is user-reported; the connection-correlated remote config rewrites and the source behavior below are confirmed.
I also ruled out the normal override layers on the remote host: there was no project .codex/config.toml, no profile config, no /etc/codex/config.toml or managed config, and no active agent-role TOML overriding the effort.
What steps can reproduce the bug?
The issue is intermittent in the Windows frontend, but the suspected path is:
- On a Linux SSH host, set the user-level config to
gpt-5.6-solwithmodel_reasoning_effort = "ultra"and record its hash/mtime. - From Windows Codex Desktop, connect to that host through Settings > Connections > SSH and open a remote project.
- Start or restore a remote chat and use/retain Ultra for the current conversation. Do not manually edit the Linux config during the test.
- Start a new chat, reconnect the SSH project, or later launch the Linux CLI locally.
- Re-read the remote
~/.codex/config.tomland inspect the new thread’s effort. - The current remote chat may remain Ultra while the durable remote default has been replaced with a lower non-Ultra catalog fallback (observed as
low).
A useful control is to leave the Windows App disconnected and start only local Linux CLI threads; the durable value should remain unchanged.
What is the expected behavior?
Selecting Ultra “for this conversation” should not silently lower an explicitly configured user-level default, especially on another host.
Any of these would be acceptable:
- keep the conversation-only Ultra state separate and preserve the explicit remote durable default;
- store a future-thread fallback in session/client state rather than overwriting
model_reasoning_effort; - or clearly prompt that this action will modify the remote host’s user-level default and show the exact fallback value.
Remote connection housekeeping should also avoid touching unrelated model/reasoning keys.
Additional information
The current open-source implementation closely matches the symptom:
- Ultra takes the separate
ApplyAdvancedReasoningpath: https://github.com/openai/codex/blob/4c43465133428898aa84f0bfc02c306ed65fb66a/codex-rs/tui/src/chatwidget/model_popups.rs#L235-L262 - the active conversation is set to Ultra, while a non-Ultra compatible default is computed and assigned for future sessions: https://github.com/openai/codex/blob/4c43465133428898aa84f0bfc02c306ed65fb66a/codex-rs/tui/src/app/config_persistence.rs#L800-L846
- that fallback is persisted, immediately before the UI says the model changed “for this conversation”: https://github.com/openai/codex/blob/4c43465133428898aa84f0bfc02c306ed65fb66a/codex-rs/tui/src/app/event_dispatch.rs#L1117-L1147
- the regression test explicitly expects configured Ultra to become a non-Ultra default for new threads while the current chat stays Ultra: https://github.com/openai/codex/blob/4c43465133428898aa84f0bfc02c306ed65fb66a/codex-rs/tui/src/app/config_persistence.rs#L1206-L1239
- app-server
config/batchWritewrites the user config on the host where the app-server runs: https://github.com/openai/codex/blob/4c43465133428898aa84f0bfc02c306ed65fb66a/codex-rs/app-server/README.md#L251-L253 - the official SSH flow starts the Codex app-server on the remote host: https://learn.chatgpt.com/docs/remote-connections#connect-to-an-ssh-host
This is related to #26472, where general model/reasoning selection persistence was described as intentional. This report is narrower: the UI says “for this conversation”, transforms Ultra into a different lower durable value, and writes that value across the SSH host boundary, affecting future local CLI threads.
There was also version skew on the remote host, and the long-lived app-server repeatedly logged failed to load models cache: missing field supports_reasoning_summaries. That may amplify the fallback behavior, but I am not claiming it as the root cause.
1 Comment
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action