Summary
Switching model_provider currently hides existing local sessions from multiple Codex surfaces, even though the rollout files and SQLite rows are still present.
Affected flows:
codex resume --last
codex fork --last
- TUI
/resume / fork picker
- Codex Desktop local history picker and latest-session lookup
This makes local history appear to "disappear" whenever users switch between the built-in OpenAI provider and a custom provider/profile.
Why this matters
A common setup is:
- use built-in OpenAI auth for normal
codex
- switch to a custom
model_provider for a proxy / Azure / gateway / custom backend
- switch back later
Today, the session data is still on disk, but discovery defaults to the active provider, so prior local sessions are no longer visible from normal resume/history flows.
That pushes users toward risky local workarounds such as rewriting model_provider in rollout files / SQLite just to make history visible again.
Root cause
The problem is in the caller-side discovery defaults, not in storage.
The core listing APIs already support optional provider filtering, but several callers force the current provider by default:
codex-rs/tui/src/lib.rs
codex-rs/exec/src/lib.rs
codex-rs/tui/src/resume_picker.rs
codex-rs/tui_app_server/src/lib.rs
codex-rs/tui_app_server/src/resume_picker.rs
codex-rs/app-server/src/codex_message_processor.rs
There is also an app-server semantic wrinkle:
model_providers: None is interpreted as "use the current provider"
- an explicit empty list can be treated as "all providers"
So even when the UI wants "show all local sessions", it can still accidentally fall back to the active provider.
Reproduction
- Start with built-in OpenAI auth and create a few local sessions.
- Switch
config.toml to a custom model_provider.
- Try any of the following:
codex resume --last
codex fork --last
/resume inside TUI
- open Codex Desktop and browse local history
- Observe that previously saved local sessions are missing from discovery/history, even though they still exist under
~/.codex/sessions and in state_5.sqlite.
- Switch the provider back and the sessions reappear.
Expected behavior
Local session discovery should default to "all local providers" unless the user explicitly asks to filter by provider.
Provider identity should still be preserved per thread for actual resume/fork execution. This issue is about history visibility and local discovery, not about erasing provider metadata.
Proposed fix
Change the default local discovery behavior to be cross-provider:
resume --last / fork --last should look across local providers
- local TUI and Desktop history pickers should list local CLI / VS Code sessions across providers
- app-server clients should use an explicit empty provider list to mean "all providers" rather than relying on
None
This seems materially safer and smaller than introducing a built-in sync/migration command that rewrites rollout metadata and SQLite state.
Why not a built-in sync command?
I initially considered proposing an official sync command that rewrites local model_provider metadata so history becomes visible again.
That approach seems much more invasive because it would need to handle:
- rollout file rewrites
- SQLite updates
- locked files
- backup / rollback semantics
- future schema / migration compatibility
The visibility problem appears solvable without mutating history at all: make discovery cross-provider by default.
Prepared implementation
I already prepared a patch on my fork that takes this approach:
It updates CLI, TUI, Desktop app lookup/picker paths, and adds a regression test for the empty-provider-filter behavior.
I have not opened a PR because docs/contributing.md says external PRs are invitation-only and uninvited PRs will be closed. If this direction aligns with the intended product behavior, I can open a PR immediately after a maintainer invitation.
Related
Related but distinct from:
That issue is about resuming a thread on the wrong provider. This one is about local history/session discovery being hidden by the active-provider default.
Summary
Switching
model_providercurrently hides existing local sessions from multiple Codex surfaces, even though the rollout files and SQLite rows are still present.Affected flows:
codex resume --lastcodex fork --last/resume/ fork pickerThis makes local history appear to "disappear" whenever users switch between the built-in OpenAI provider and a custom provider/profile.
Why this matters
A common setup is:
codexmodel_providerfor a proxy / Azure / gateway / custom backendToday, the session data is still on disk, but discovery defaults to the active provider, so prior local sessions are no longer visible from normal resume/history flows.
That pushes users toward risky local workarounds such as rewriting
model_providerin rollout files / SQLite just to make history visible again.Root cause
The problem is in the caller-side discovery defaults, not in storage.
The core listing APIs already support optional provider filtering, but several callers force the current provider by default:
codex-rs/tui/src/lib.rscodex-rs/exec/src/lib.rscodex-rs/tui/src/resume_picker.rscodex-rs/tui_app_server/src/lib.rscodex-rs/tui_app_server/src/resume_picker.rscodex-rs/app-server/src/codex_message_processor.rsThere is also an app-server semantic wrinkle:
model_providers: Noneis interpreted as "use the current provider"So even when the UI wants "show all local sessions", it can still accidentally fall back to the active provider.
Reproduction
config.tomlto a custommodel_provider.codex resume --lastcodex fork --last/resumeinside TUI~/.codex/sessionsand instate_5.sqlite.Expected behavior
Local session discovery should default to "all local providers" unless the user explicitly asks to filter by provider.
Provider identity should still be preserved per thread for actual resume/fork execution. This issue is about history visibility and local discovery, not about erasing provider metadata.
Proposed fix
Change the default local discovery behavior to be cross-provider:
resume --last/fork --lastshould look across local providersNoneThis seems materially safer and smaller than introducing a built-in sync/migration command that rewrites rollout metadata and SQLite state.
Why not a built-in sync command?
I initially considered proposing an official
synccommand that rewrites localmodel_providermetadata so history becomes visible again.That approach seems much more invasive because it would need to handle:
The visibility problem appears solvable without mutating history at all: make discovery cross-provider by default.
Prepared implementation
I already prepared a patch on my fork that takes this approach:
codex/cross-provider-session-discovery0592e899c6457207b18c4e2ebd14fc73f181ffd1It updates CLI, TUI, Desktop app lookup/picker paths, and adds a regression test for the empty-provider-filter behavior.
I have not opened a PR because
docs/contributing.mdsays external PRs are invitation-only and uninvited PRs will be closed. If this direction aligns with the intended product behavior, I can open a PR immediately after a maintainer invitation.Related
Related but distinct from:
That issue is about resuming a thread on the wrong provider. This one is about local history/session discovery being hidden by the active-provider default.