Prompt-bearing interactive TUI launches take the shadow home and stall ~55s rebuilding the thread index
Summary
codex [OPTIONS] [PROMPT] — the interactive TUI with its optional initial prompt — is classified by the wrapper as a noninteractive command named after the prompt text, so with runtime rotation enabled it is routed onto the disposable runtime shadow CODEX_HOME instead of the canonical-home app-helper path that a bare TUI and resume/fork already use.
The shadow mirror deliberately omits Codex's runtime SQLite files (state_5.sqlite etc. — isRuntimeRotationShadowHomeOmittedEntry), while the linked sessions/archived_sessions trees remain visible. Native Codex therefore starts, sees no thread index, and rebuilds it from every rollout file before it will submit the prompt it already has in argv. Startup stalls scale with session history: on a store with 936 rollouts the prompt sat unsubmitted for ~52 seconds.
Reproduction
With runtime rotation enabled (the default) and a non-trivial session history:
codex-multi-auth-codex --model gpt-5.6-sol -c 'model_reasoning_effort="high"' 'Reply with exactly READY, then stop.'
Observed on 2.8.5 (and the 2.8.6 tarball carries the same classifier):
- Native Codex starts immediately with the full prompt in argv.
- A disposable home appears under
~/.codex/multi-auth/runtime-shadow-homes/…; its config.toml is created instantly, and a new state_5.sqlite is created and keeps changing for ~52s — exactly the window during which the session is not created.
- The rebuilt shadow database ends with the same
threads row count as the canonical database (936 = 843 active + 93 archived rollouts), i.e. Codex spent the gap re-indexing the full history.
- Stock Codex with the identical prompt/model/effort/cwd starts instantly, as does the wrapper's bare TUI (no prompt).
Root cause
Official Codex's root grammar is:
codex [OPTIONS] [PROMPT]
codex [OPTIONS] <COMMAND> [ARGS]
findForwardedCommand(rawArgs) in scripts/codex.js skips options and returns the first positional token as { command, index }. That is not sufficient for this grammar: the first positional can be the optional root [PROMPT], not a subcommand. It also treats the token after -- as a command, although -- is precisely how a positional prompt is forced — codex -- exec launches the TUI with the prompt exec (verified against codex-cli 0.148.0), it does not run exec.
isCodexInteractiveTuiCommand returns true only when findForwardedCommand is null, so a prompt-bearing launch falls through createRuntimeRotationProxyContextIfEnabled past the canonical-home app-helper branch (useCanonicalHome: true) into createRuntimeRotationProxyCodexHome(...) — the same failure shape as #647 (resume/fork) and #659 (app-server), this time for the root TUI itself.
A related argv hazard sits next to it: the wrapper appends its -c overrides (model_provider, cli_auth_credentials_store) after the user argv. After a --, appended options bind to the [PROMPT] positional, so a ---forced prompt would swallow them as prompt text.
Expected
Prompt-bearing interactive TUI launches keep runtime rotation but use the canonical Codex home immediately, exactly like the bare TUI and interactive resume/fork; true noninteractive request commands (exec, review) stay on the isolated shadow home; the original Codex argv reaches native Codex unchanged, with wrapper-injected options on the option side of the prompt.
I have a fix ready and will open a PR shortly.
Prompt-bearing interactive TUI launches take the shadow home and stall ~55s rebuilding the thread index
Summary
codex [OPTIONS] [PROMPT]— the interactive TUI with its optional initial prompt — is classified by the wrapper as a noninteractive command named after the prompt text, so with runtime rotation enabled it is routed onto the disposable runtime shadowCODEX_HOMEinstead of the canonical-home app-helper path that a bare TUI andresume/forkalready use.The shadow mirror deliberately omits Codex's runtime SQLite files (
state_5.sqliteetc. —isRuntimeRotationShadowHomeOmittedEntry), while the linkedsessions/archived_sessionstrees remain visible. Native Codex therefore starts, sees no thread index, and rebuilds it from every rollout file before it will submit the prompt it already has in argv. Startup stalls scale with session history: on a store with 936 rollouts the prompt sat unsubmitted for ~52 seconds.Reproduction
With runtime rotation enabled (the default) and a non-trivial session history:
Observed on 2.8.5 (and the 2.8.6 tarball carries the same classifier):
~/.codex/multi-auth/runtime-shadow-homes/…; itsconfig.tomlis created instantly, and a newstate_5.sqliteis created and keeps changing for ~52s — exactly the window during which the session is not created.threadsrow count as the canonical database (936 = 843 active + 93 archived rollouts), i.e. Codex spent the gap re-indexing the full history.Root cause
Official Codex's root grammar is:
findForwardedCommand(rawArgs)inscripts/codex.jsskips options and returns the first positional token as{ command, index }. That is not sufficient for this grammar: the first positional can be the optional root[PROMPT], not a subcommand. It also treats the token after--as a command, although--is precisely how a positional prompt is forced —codex -- execlaunches the TUI with the promptexec(verified against codex-cli 0.148.0), it does not runexec.isCodexInteractiveTuiCommandreturns true only whenfindForwardedCommandis null, so a prompt-bearing launch falls throughcreateRuntimeRotationProxyContextIfEnabledpast the canonical-home app-helper branch (useCanonicalHome: true) intocreateRuntimeRotationProxyCodexHome(...)— the same failure shape as #647 (resume/fork) and #659 (app-server), this time for the root TUI itself.A related argv hazard sits next to it: the wrapper appends its
-coverrides (model_provider,cli_auth_credentials_store) after the user argv. After a--, appended options bind to the[PROMPT]positional, so a---forced prompt would swallow them as prompt text.Expected
Prompt-bearing interactive TUI launches keep runtime rotation but use the canonical Codex home immediately, exactly like the bare TUI and interactive
resume/fork; true noninteractive request commands (exec,review) stay on the isolated shadow home; the original Codex argv reaches native Codex unchanged, with wrapper-injected options on the option side of the prompt.I have a fix ready and will open a PR shortly.