## What changed
- Display the leading `/` in the prompt marker instead of the editable text, sharing prefix state with shell mode's `!`.
- Preserve command prefixes and text element offsets across submission, queuing, history, and external editing. Keep prefixes literal in plain-text composers.
- Track composer-owned slash command elements separately, omit them from exported draft elements, and refresh them when command availability changes.
- Let backward deletion at the start of the text remove the prompt prefix while preserving selected-text deletion and Vim Replace recovery.
## Testing
Add regression coverage for slash prompt cursor placement, prefix deletion, history search highlighting, dynamic command availability, and Vim Replace restoration, including Unicode text. Update rendering snapshots for the slash prompt marker.
GitOrigin-RevId: 0da42da8e98bf7885f9b0ba2c8d5ad4f44d6847e
## Why
A running shared background server owns its feature settings until it restarts. Differences from a client's configuration files or defaults should not trigger a compatibility warning or a restart request.
## What changed
- Check shared-service features only when explicitly overridden on the command line.
- Exclude overrides superseded by active legacy managed configuration or feature requirements, while supporting older servers without `configRequirements/read`.
- Pass only the remaining explicit feature overrides to a requested daemon restart.
## Testing
Update compatibility tests for stale daemon overrides, explicit enable/disable requests, managed configuration, and older servers. Extend CLI startup tests to verify the feature overrides persisted after a restart.
GitOrigin-RevId: ac92c9c02cd70fa233203ebef1182fd119325dd1
## Why
GovCloud guidance was tied to Bedrock credential setup, so users with an already configured provider could miss it.
## What changed
Check for GovCloud during TUI startup using the app server's resolved provider, including when connecting to a server. Require acknowledgment before proceeding and save `notice.hide_gov_cloud_guidance = true` to suppress the screen on subsequent launches. Quitting the guidance exits startup without saving acknowledgment.
## Testing
Add a terminal integration test covering acknowledgment persistence, quitting without saving, and suppression after restart. Retain coverage for explicit acknowledgment and scrolling in short panes.
GitOrigin-RevId: f09fd73a66fb02f94ebdd3c3b0dbe5712dfa9be7
## Why
Fresh starts connected to an app server can bootstrap with stale client model settings before reading the server configuration. An empty model catalog can also prevent startup even when managed new-thread defaults provide a model.
## What changed
- Read server configuration before model bootstrap for fresh starts using a local daemon or remote server without an explicit profile.
- Preserve explicit model and reasoning-effort overrides, clear implicit client settings when `config/read` is unsupported, and allow managed new-thread defaults to supply a model when the catalog is empty.
- Use the launch directory for local daemon configuration reads and the server directory for remote reads.
## Testing
Update startup-default tests to cover managed model selection with an empty catalog. Strengthen the reconnect test with a stale client model and an assertion that `config/read` uses the server directory.
GitOrigin-RevId: 8fe1485c6e66c8d46560b34d904ce1724458993a
## Why
Concurrent Linux test spawns can inherit writable descriptors for executable fixtures, preventing those fixtures from being executed even after the writing test closes its descriptor.
## What changed
Replace direct executable fixture writes and copies across the Rust tests with `codex_utils_cargo_bin::write_executable` and `copy_executable`. These existing helpers complete writes and copies in separate processes on Linux.
Remove the empty temporary inode before creating fake bubblewrap executables, and stage tampered bubblewrap bytes in a separate data file before copying them into the executable fixture. Add the required test dependencies.
GitOrigin-RevId: c875c83088731a4933ef1574e8d79d8cecc12f54
## Why
Explicit launch permissions such as `--yolo` can be lost during reconnect recovery, causing subsequent input to use different approval and sandbox settings.
## What changed
Remember explicit local launch approval policies, approvals reviewers, and permission profiles at startup and when creating new sessions. Restore the approvals reviewer independently of profile overrides during reconnect recovery. Keep constrained profiles that cannot be expressed through legacy turn parameters under server control.
## Testing
Add regression coverage for `--yolo` across new sessions and reconnects, later permission-picker choices, reviewer-only overrides, and server-owned constrained profiles. Extend the reconnect integration test to submit the preserved draft and verify its approval and sandbox settings.
GitOrigin-RevId: 7a77dc41b2a357ab17fec9ba6cb2361f4a8f4aa5
## What changed
- Mark `api_key_model_discovery` as stable and enable it by default, while preserving explicit user opt-outs and provider catalog requirements.
- Fall back to bundled models when discovery is disabled at runtime, including when a remote catalog has already been loaded.
## Testing
Extend model-list coverage for default enablement, app overrides, and user configuration precedence. Add a regression assertion that runtime opt-outs hide loaded catalogs without additional fetches, and update daemon compatibility tests for the new default.
GitOrigin-RevId: feaf732757792cc58063f21a5327d0e633f079f4
## Why
Client provider defaults can override the app server's configured provider and hide its sessions from resume and fork history.
## What changed
- Omit implicit provider overrides from thread start, resume, and fork requests so the server can resolve its defaults.
- Use the server's effective provider for named history lookup, `--last`, and resume and fork pickers, while honoring explicit CLI and selected-profile choices.
- Respect managed provider requirements when resolving history filters and preserve the active session's provider when forking it.
## Testing
Add app-server regression tests for provider defaults, explicit choices, configuration changes, selected profiles, and managed requirements. Add CLI coverage for resume and fork pickers and `--last` with local daemon and embedded servers, plus a picker rendering snapshot.
GitOrigin-RevId: a077758b13a5e55552b52e5532ad4bebe86dce7e
## What changed
- Skip folder trust prompts for locally discovered projectless directories without a saved trust decision. Apply workspace-write permissions and granular approval defaults only when local execution, configuration, and managed policy allow them.
- Prompt for Windows sandbox setup when needed before enabling implicit workspace-write permissions.
- Restore saved task permissions on resume unless explicitly overridden, and keep ordinary turns from overwriting the server's saved permission profile. Track explicit approval reviewer choices separately from restored permissions.
- Let `/cd` request folder trust with a “Keep current directory” option. Recheck task activity and background terminals before switching, and enforce destination permission requirements.
## Testing
Add regression coverage for projectless defaults and session transitions, explicit permission overrides, saved profile preservation, trust discovery, destination policy conflicts, and the directory consent and Windows sandbox prompts.
GitOrigin-RevId: cf74f5a90245f2aee96caa80d76de64da6ec1ebd
## Why
The five-attempt limit could stop reconnection before the existing 120-second budget expired, preventing recovery from longer temporary failures.
## What changed
Continue retrying with an eight-second delay after the initial backoff until reconnection succeeds or the shared deadline expires.
## Testing
Update the exhaustion test to require the full 120-second budget. Extend the integration test to recover after five failed `thread/resume` attempts and verify draft preservation and notification delivery.
GitOrigin-RevId: 321d4ad100dbec1254bfe8aafd67ff63fb9a6e93
## Why
Opening a separate-window editor from the fullscreen TUI leaves the alternate screen, hiding the draft and the instruction to save and close the editor.
## What changed
Preserve and repaint the last Codex frame when handing the terminal to an external editor, while releasing keyboard and mouse input modes. Track whether the alternate screen's keyboard mode is active so cleanup does not pop it twice if the editor switches screens. Restore TUI modes and the alternate screen when the editor returns.
## Testing
Add terminal integration coverage for separate-window editors, terminal editors that switch or reuse screens, and inline mode. Verify the visible draft and handoff hint, disabled mouse reporting, edited draft recovery, and continued typing. Add a unit test for balanced keyboard stacks whether or not the editor leaves the alternate screen.
GitOrigin-RevId: c2ff1046a933f5f9e3168663e2c326999845c578
## What changed
- Add `gpt-6-sol` and `gpt-6-luna` catalog entries and refresh model descriptions.
- Offer migrations from `gpt-5.5`, `gpt-5.6-sol`, and `gpt-5.6-terra` to `gpt-6-sol`, and from `gpt-5.6-luna` to `gpt-6-luna`.
- Retarget retired `gpt-5.4` and `gpt-5.4-mini` selections to GPT-6 Sol and Luna, respectively.
- Recommend `gpt-6-luna` in the rate-limit switch prompt.
## Testing
Extend migration tests to cover the new targets, their default reasoning effort, and prompting again after a previously acknowledged migration to an older target. Update model-picker and rate-limit prompt snapshots.
GitOrigin-RevId: d3a093d18ce44a903383504ab8f5cbbc911d602d
## Why
Automatic daemon launches could silently fall back to embedded mode when shared feature settings differed from the session's requirements. Changing those settings affects other clients, and restarting the server may interrupt active or queued work.
## What changed
- Offer interactive choices to run without the daemon, restart with the required settings, or cancel. Default to cancel and require explicit confirmation for restart.
- Allow restart only for managed daemons with a feature mismatch, then recheck compatibility once. Noninteractive required-daemon failures return an error with `--no-daemon` guidance; optional attachment retains its fallback behavior.
- Preserve saved feature overrides on startup and require confirmation before applying requested shared-feature disables, including on fresh starts.
- Merge confirmed settings under the lifecycle lock, persist changes after the old process stops, and avoid restarting when the saved overrides already match.
## Testing
Add recovery-menu snapshots and confirmation tests, compatibility tests for required and optional attachment, daemon ownership and settings-preservation tests, and CLI terminal tests for cancellation, embedded fallback, confirmed restart, and disabling shared features.
GitOrigin-RevId: d50a6cf7e476b9647237431e8fc0fc6041ed17db
## What changed
Promote `daemon_auto_start` to stable and enable it by default for eligible interactive launches. Remove its entry from `/experimental`.
## Testing
Update daemon startup, `--no-daemon`, and startup failure tests to exercise the default without explicitly enabling the feature. Disable daemon startup in unrelated TUI and path-safety test fixtures.
GitOrigin-RevId: 107d71108b96d09431148d7d61f10c6381929e05
## What changed
Default `tui.fullscreen_transcript` to `true`, including when the `[tui]`
section is absent, and apply the same default to the first frame. Update the
configuration schema to match. Alternate-screen restrictions still take
precedence, and `tui.fullscreen_transcript=false` restores terminal scrollback.
## Testing
Update configuration and startup tests for the new default, including an empty
`[tui]` section and `--no-alt-screen`. Adjust PTY tests to cover default fullscreen
entry and explicit opt-out to terminal scrollback.
GitOrigin-RevId: e460dcd058d52c50da2abc5113bbb678e845d5fc
## What changed
Add a picker for Scrollback and Fullscreen modes that requires explicit
confirmation and saves `tui.fullscreen_transcript` to the selected user config
file. Keep the running renderer unchanged and explain that a restart is required
and launch overrides still apply. Report save failures without changing the
stored preference in memory.
## Testing
Add picker snapshots and tests for confirmation, cancellation, selected-config
persistence, and failed saves. Add a PTY test covering mode changes in both
directions across restarts while verifying that the current session stays in
its original mode.
GitOrigin-RevId: 7f231ab37c89e2168133fcfd6aaee54775aa7972
## What changed
- Group shortcut help into Navigate, Tasks, and View sections using the shared shortcut renderer, adapting to one, two, or three columns and indicating when more height is needed.
- Show movement hints in the footer, move the new-worktree hint into help, and remove the idle search row. Give task-list column headers consistent styling.
- Change the default task-deletion binding from `Delete` to `Backspace`, while preserving text editing in search and rename inputs.
## Testing
Add snapshots for responsive help layouts, custom bindings, and active search. Add regression coverage for `Backspace` editing without deleting tasks, and update keymap conflict tests for the new default.
GitOrigin-RevId: 45d7f122c9474f1c054450800dcca5a9b2bbbcc5
## What changed
Use `tui.fullscreen_transcript` to opt into the fullscreen transcript, including scrolling, selection, and search. It defaults to `false`; `--no-alt-screen` and `tui.alternate_screen = "never"` still take precedence.
The new preference controls both the first frame and application startup. Boolean CLI overrides for it are allowed during daemon startup. The old `features.transcript_v2` flag is deprecated and ignored, with a notice directing users to the new setting; it does not migrate into or override the preference.
## Testing
Add coverage for default terminal scrollback, fullscreen persistence through startup, alternate-screen restrictions, daemon override validation, and independence from the deprecated flag. Update existing history and activity tests to use the new preference.
GitOrigin-RevId: 4117bf1ee548fa8d101a594f9506673d87c74c15
## What changed
- Show the active grouping in the header and place the search hint or active search/rename field above the task list.
- Move connection, worktree creation, refresh error, and server version notices to the footer, preserving the title and task counts. Give active key chord hints priority over notices.
- Clip long search and rename input at grapheme boundaries and position the cursor using the visible suffix.
- Show `Loading tasks…` while the initial task refresh is pending.
- Use standard picker defaults for the agent sign-in selection.
## Testing
Add regression coverage for long Unicode search and rename input, including combining characters, joined emoji, and cursor placement. Update layout snapshots and assertions for footer notices, key chord priority, and search editing during reconnection.
GitOrigin-RevId: 57da83c4c0beaa89fe88d3be03b468a9f2a739c6
## Why
Keep diagnostics accessible without adding warning rows to the live conversation or changing the composer layout.
## What changed
- Show a deduplicated warning count in the passive footer, yielding to interactive hints.
- Open warning details with `F2`, `/warnings`, or a click on the warning notice. Support navigation, scrolling, and copying individual diagnostics while preserving the draft.
- Retain startup, runtime, MCP, and deprecation diagnostics in the full transcript. Group MCP details by server and preserve warnings during replay.
- Respect existing custom bindings and chord prefixes when enabling `F2`.
- Show an immediate explanation when `/pets` is unavailable.
## Testing
Add regression tests and snapshots for warning counts, draft preservation, viewer navigation and copying, narrow layouts, terminal scrollback, and keybinding conflicts.
GitOrigin-RevId: 2bc586430da60347cfbaa5bf128bc48f7f9dc777
## Why
The startup composer accepted edits but ignored submission. Its first frame also preceded configured screen settings, and startup failures could leave typed text unavailable.
## What changed
- Honor configured submit bindings during startup, retaining one confirmation until the session and protected input screens are ready. Repeated submit keys do not duplicate the message; edits, `Esc`, disconnects, or destination changes cancel confirmation while preserving the draft.
- Apply local screen, status-line, keymap, and paste settings before the first editable frame. Anchor the composer at the bottom in owned-screen mode and retain the loading frame until resumed history is ready to render.
- Keep an in-memory recovery copy through submission acknowledgment. On startup failure, restore the terminal before printing unsent text, expanding paste placeholders and escaping terminal control characters.
## Testing
Add regression coverage for deferred single submission, configured key chords, cancellation, protected input, paste handling, draft recovery, initial screen settings, and loading-frame handoff, plus a startup layout snapshot.
GitOrigin-RevId: 1eb4c63027f7d59af5d42d8545cd5cb5c3594306
## What changed
- Render transcript history and live output above the composer when `features.transcript_v2` is enabled and alternate-screen rendering is available. Handle scrolling, selection, copying, links, and older-history pagination in the main view.
- Add a clickable return-to-latest control with new-activity hints and temporary clipboard status. Let plain Enter return to latest when the composer is empty.
- Reflow retained transcript content during drawing and preserve the launch-selected screen mode across configuration reloads and session transitions, including `--no-alt-screen` restrictions.
- Enter the alternate screen with its first synchronized frame, and box CLI startup futures to reduce stack usage during session transitions.
## Testing
Add regression coverage for transcript layout, input routing, follow controls, clipboard status, and screen-mode persistence. Add a PTY test for the first alternate-screen frame and clean exit, and extend session-transition coverage through the CLI dispatcher.
GitOrigin-RevId: 1daf077826c7744b0f57399d10d159923dc87a97
## Why
Prompt layouts use inconsistent selection styles, and long content can crowd out choices and keyboard hints in small terminals.
## What changed
- Apply shared picker surfaces, selection highlights, accent colors, and shortcut styling across approval, question, startup, and session prompts.
- Reuse numbered picker rows with wrapping and selected-item visibility. Bound folder paths to preserve trust disclosures and choices, prioritizing the repository root when space is limited.
- Give multiline prompts a shared layout for rendering and cursor placement, with Escape hints that reflect Vim mode.
- Present local providers as vertical choices with inline status, adding arrow-key and `j`/`k` navigation plus `1`/`2` selection shortcuts.
## Testing
Add snapshots and regression tests for narrow and short viewports, long trust paths, multiline cursor placement after resizing, selection styling, provider shortcuts, and confirmation behavior.
GitOrigin-RevId: 89bb133dfa0d085d568a3a84473afd9e2fb20838
## Why
Feature overrides previously forced embedded mode even when they could work with the shared daemon. A running daemon can also have different feature settings from the current invocation, including when the invocation uses defaults.
## What changed
- Allow selected Boolean feature overrides and `suppress_unstable_features_warning` in daemon mode. Keep explicit overrides that disable shared services in embedded mode.
- Pass shared-service feature overrides to newly launched daemons and persist them for restarts and updates without changing a running daemon's settings.
- Check daemon feature settings with `experimentalFeature/list` before attaching. Warn and fall back to embedded mode on mismatches, failed checks, or an incompatible code-mode host fallback policy. Skip this check for the agents overview.
- Resolve worktree configuration before daemon selection and allow worktree sessions to auto-start the daemon.
- Forward `suppress_unstable_features_warning` in thread configuration overrides.
## Testing
Add coverage for override eligibility and precedence, launch-feature persistence and reuse, and TUI fallback warnings for feature and host-policy mismatches. Extend worktree integration coverage to exercise daemon auto-start and warning suppression.
GitOrigin-RevId: 68c316f74843b1dfd8fa39bdb48bd1f649fee57f
## What changed
- Add `features.daemon_auto_start`, disabled by default and available through `/experimental`, to start the shared local server for eligible new, resumed, and forked sessions. Changes take effect on the next launch, and disabling the feature persists an explicit `false`.
- Require successful daemon startup and connection when auto-start applies. On failure, show guidance to rerun the same command with `--no-daemon` instead of silently falling back to an embedded server.
- Preserve embedded mode for excluded launches, including Bedrock sign-in, and carry exclusion warnings through resume and fork pickers. Honor `--no-daemon` without an exclusion warning.
- Update `/import` guidance to recommend restarting with `codex --no-daemon`.
## Testing
Add CLI and TUI coverage for automatic daemon attachment, startup and connection failures, `--no-daemon`, picker warning persistence, and Bedrock onboarding with and without a running daemon. Add snapshots and configuration-write assertions for the experimental toggle.
GitOrigin-RevId: 2e8eb163bc7ddd268a86c7546c05a85356c1e9ee
## What changed
- Run with `--no-daemon` without starting or probing the shared server, even when it is already running. Preserve the flag through `resume` and `fork`, and honor it for session archive commands.
- Reject combinations with `--remote`, `codex agents`, and `codex queue`, which require a server connection. Point users to `codex --no-daemon` when the agents overview cannot start its shared server.
- Centralize daemon eligibility checks and exclude launches using `--profile` or `CODEX_EXEC_SERVER_URL` from implicit daemon reuse.
## Testing
Add coverage for flag propagation, incompatible command combinations, and daemon eligibility. Add a PTY test verifying that `--no-daemon` starts the TUI without creating daemon state or connecting to an existing control socket.
GitOrigin-RevId: acc6a7cb339df6433bb8273c796194cdceda37c1
## What changed
- Probe for screen readers at startup on macOS, Windows, and Linux, with a 450 ms timeout. Include Windows Narrator detection in the current login session.
- Save `tui.animations = false` when a screen reader is detected and no user animation preference is configured. Preserve explicit preferences and config comments, and retain a session default if saving fails.
- Record the attempt in `tui.screen_reader_detection_done`; either boolean value skips future detection. Allow explicit animation preferences to override the screen-reader default on reload.
## Testing
Add tests for one-time detection, timeouts, preference preservation, temporary CLI overrides, persistence failures, and preference reloads. Verify rendering without animation frame requests and interactive startup that records detection without replacing an explicit preference.
GitOrigin-RevId: f61c19dfd053f97e8cfed68dce7389fa7601120d
## What changed
- Replace the inline task composer with a session list: `n` opens a blank session in the selected checkout without sending an initial turn or interrupting running agents.
- Use single-letter action shortcuts and `Enter` to open a session. `Esc` cancels search or rename without closing the list; `Ctrl+C` quits from the list.
- Load destination settings for new sessions while carrying over explicit permission choices. Retain blank sessions and their drafts across navigation until the first turn.
## Testing
Update tests and snapshots for command center navigation, shortcuts, blank draft restoration, destination defaults, permission carryover, and directory trust.
GitOrigin-RevId: bddd04fdbe6ac2f5b7bd70293fd04f673b97ba02
## What changed
- Fade Astra stars over one second after 15 seconds from the first visible frame, or quickly on composer input, drafts, voice input, and popups. Disconnected key handling also dismisses the animation.
- Preserve placeholder and draft text, including spaces. Stop scheduling animation frames when unfocused or finished, while allowing the idle deadline to elapse without terminal focus.
- Hide the terminal cursor before repainting and cache its style to avoid redundant anchor repairs. Invalidate cursor state after screen transitions, external programs, resume, and caught-panic recovery.
## Testing
Add regression tests and snapshots for fade timing, input dismissal, focus changes, text preservation, and frame scheduling. Add cursor redraw tests and a PTY test for cursor visibility and shape restoration after a caught panic. Update the reconnect test to wait until both the draft and notification are visible.
GitOrigin-RevId: 0c9aaa13e6bde820f88e3757457063680d7921a3
## What changed
- Check directory trust when dispatching tasks from Agent Command Center, resuming sessions, and opening loaded tasks.
- Return connected users to Agent Command Center when they cancel folder consent. Clear launch prompts and images on startup cancellation, and restore the composer draft when task dispatch is canceled.
- Reload local configuration after saving folder trust and review startup hooks before creating a new task.
- Label connected consent screens with “Back to Agent Command Center”; retain quit behavior for embedded sessions.
## Testing
Add a terminal integration test covering unknown and untrusted folders, server-authoritative trust, cancellation and retry, resumed tasks with changed directories, and hook review before task creation. Update consent-screen snapshots.
GitOrigin-RevId: db88d2113fd47bc4c57369cc20ebf3042e6fb7ab
## Why
Resume and fork selection can change the working directory. Folder consent needs to cover the selected destination, and existing tasks in untrusted folders may retain settings and history loaded while trusted.
## What changed
- Move startup consent after destination selection and reload local configuration when trust is saved.
- Check both selected and saved folders for local daemon resumes, and reread the task after consent to catch working directory changes.
- Resolve local trust using project markers, Git roots, and normalized paths, honoring explicit working directory decisions and canonical path precedence.
- Offer restricted-folder consent without changing saved trust, with distinct wording for existing tasks that may retain configuration or hooks. Preserve remote checks scoped to explicit `--cd`.
## Testing
Extend trust lookup coverage for parent/child decisions, repositories without project configuration, path aliases, and custom project markers. Update restricted-folder snapshots and add an existing-task snapshot.
GitOrigin-RevId: caf8c70f1e953c4f7b4ddc89dd29bb1fd8ed62f1
## Why
Session transitions need stack headroom to rebuild configuration and the chat widget. Tokio stores task outputs inline even when it boxes the task future, so returning a large `Config` adds stack pressure during task allocation.
## What changed
Box the configuration build result inside the runtime worker and unbox it after joining. Box the `App::run` future to keep the large event loop out of enclosing startup futures.
## Testing
Extend the production-stack TUI integration test to enter `/side`, verify the process remains running, and return to the saved conversation with Ctrl+C.
GitOrigin-RevId: 44975300bb837bf3645ff762cf7bcdc44a277f41
## Why
Session transitions need stack headroom for embedded-server initialization and configuration loading. Running them inside event dispatch risks exhausting the TUI thread's stack.
## What changed
- Queue `/resume` and valid `/cd` requests for processing after event dispatch returns.
- Reject additional `/cd` requests while one is pending, and recheck the source session, working directory, idle state, and remote-environment restrictions before applying it.
## Testing
Add a Unix PTY regression test that exercises `/resume`, worktree conversation forks, `/cd`, and new worktree conversations through the real TUI event loop. Update the directory-change test to verify that dispatch queues the request without immediately changing configuration.
GitOrigin-RevId: 4950921931dfaba9e55e6bb04f98f7ba64b72122
## Why
The macOS startup symlink test applies its own Seatbelt policy, which cannot
run inside Bazel's sandbox.
## What changed
- Tag the TUI Bazel tests with `no-sandbox` so the startup test can install
its policy.
- Verify that the mocked write tool reports a successful exit before checking
the file written through the symlink.
GitOrigin-RevId: c12eb00f995985fccc053765399fbb0eb7ce70d9
## What changed
- Add the macOS-only `allow_symlinked_codex_home` user setting. When enabled in the execution host's `$CODEX_HOME/config.toml`, writable roots at or beneath that home may traverse symlinks.
- Keep the exception disabled by default and prevent project config, command-line overrides, and ignored user config from enabling it. Other writable roots remain subject to symlink checks.
- Propagate the resolved setting through local, interactive, and exec-server sandbox paths, including `CODEX_HOME` aliases.
- Explain the opt-out in symlink rejection errors, including that it trusts targets outside `CODEX_HOME` and targets that change between commands.
## Testing
- Add macOS coverage for shell commands, patches, filesystem helpers, process execution, and interactive startup with enabled, disabled, aliased, and out-of-scope homes.
GitOrigin-RevId: 99fcdf611200c9e1b7713cf06f7fdea5bfa7f089
## Why
An app-server thread can still be closing when the TUI reconnects. Its
`thread/resume` request then uses the same `-32600` error code as an unavailable
thread, even though the thread can be resumed once closing finishes.
## What changed
Treat the thread-specific "is closing" response as a transient reconnect error
so the existing reconnect loop retries instead of marking the conversation
unavailable.
## Testing
Extend the active reconnect and end-to-end reconnect tests to cover a closing
thread that resumes successfully on the next attempt.
GitOrigin-RevId: 30ce232b8894065fef346a86128b3ff9bf36ba1f
## What changed
- Reconnect out-of-process TUI sessions after the app-server transport drops, bootstrap a fresh client, and resume the active thread.
- Preserve cached transcripts, drafts, runtime settings, task-tool capabilities, and live notification routing across the new connection.
- Keep recovered or possibly submitted input paused for manual review instead of resending it, and leave conversations that cannot be resumed available as read-only cached views.
- Show reconnect progress and actionable failure states while still allowing drafts to be edited or copied.
## Testing
- Add app-level coverage for successful recovery, failed and unavailable resumes, input quarantine, and preserved session state.
- Extend the terminal integration test to verify that a draft survives reconnection, the thread is resumed without starting a turn, and notifications arrive through the replacement connection.
GitOrigin-RevId: 5dcb867c89e226a0c545d6313a77424c233cd47a
## Why
Losing an external app-server connection can leave a submission's outcome uncertain. The TUI must preserve local work without retrying it or allowing stale server events to trigger more actions.
## What changed
- Enter an offline state when an external app-server transport disconnects during startup, event streaming, or submission.
- Keep conversation drafts, queued input, expanded pastes, attachments, and agent-overview input editable while blocking submissions, remote actions, and automatic queue replay.
- Show a connection-lost notice that directs users to copy their work and relaunch, while retaining `Ctrl-C` and an empty-composer `Ctrl-D` as quit shortcuts.
- Cancel pending views and asynchronous work, and ignore stale completions after the disconnect. Embedded app-server behavior is unchanged.
## Testing
Added unit, snapshot, and pseudo-terminal coverage for lost startup and mutation replies, offline draft editing, queued-input recovery, stale-event quarantine, agent-overview behavior, and end-to-end preservation without reconnection or resubmission.
GitOrigin-RevId: 7219a95fad676dda447d625db9e465345b469d58
## What changed
Remove the unused `codex-cli` dev-dependency and the no-op import that kept it
visible to `cargo-shear`. TUI tests continue to locate spawned binaries through
`codex-utils-cargo-bin`.
GitOrigin-RevId: ba5855590c6f0300845170f15f39d77c0611a60a
## Why
Configuration and app-server initialization can take time before the main TUI is ready, leaving users unable to begin drafting a prompt.
## What changed
- Show a provisional composer while startup work runs and carry its text, cursor position, paste state, and attachments into the initialized chat.
- Limit the provisional composer to safe editing and cancellation, and quarantine input around session pickers, approvals, and other actionable startup screens.
- Preserve configuration validation before terminal checks and recover terminal state cleanly from startup failures and caught panics.
## Testing
- Cover startup editing, multiline and large pastes, keymaps, cancellation, session-picker handoff, approval boundaries, and draft restoration.
- Verify non-interactive launches report configuration errors before terminal errors.
GitOrigin-RevId: fe04a85cfbbcff21ff87fa81fd17474827858575
## Why
During inline-mode resize reflow, replayed history can overlap a zero- or
one-row history region and leave stale terminal characters visible in the
composer. Resetting the previous render buffer is insufficient because
default-style spaces may still compare equal and be skipped.
## What changed
- Mark every cell in an invalidated viewport for unconditional repainting.
- Invalidate the viewport after flushing pending history when history can
overlap it.
## Testing
Add regression coverage for repainting spaces over stale cells and a manual
`tmux` resize smoke test for preserving visible multiline draft text.
GitOrigin-RevId: 5a8a480e2fc50c801561de6a4598a3ab8c12b8d6
## What changed
- Allow up to five seconds for focus-triggered input to appear in the PTY test.
- Check for unexpected foreground and background palette queries while waiting for both immediate and delayed input, so either focus path fails with the palette-specific error.
GitOrigin-RevId: b8ed4f1ced257865140b1518c8959f65371e744f
## Why
Refreshing the terminal palette on a focus event can block the input loop and
discard keystrokes entered while focus is returning.
## What changed
- Keep the palette cached by the startup probe when handling `FocusGained`.
- Continue updating focus state and requesting a redraw without issuing new
foreground or background color queries.
## Testing
- Verify a queued key is delivered after `FocusGained`.
- Exercise focus regain in a pseudo-terminal with immediate and delayed input,
and verify it emits no additional palette queries.
GitOrigin-RevId: 16e26f81c1343d01f6d0baeff3f204bcc91dd6f3
The workspace denies `clippy::expect_used` in production. Although
`clippy.toml` allows `expect` in tests, Bazel Clippy compiles
integration-test helper code in a way that does not receive that
exemption, which encouraged verbose `unwrap_or_else(... panic!(...))`
and equivalent `match`/`let else` forms.
This allows `clippy::expect_used` once at each integration-test crate
root (including aggregated suites and test-support libraries), then
replaces manual panic-based Result and Option unwraps with
`expect`/`expect_err`. Standalone `tests/*.rs` files remain their own
crate roots. Intentional assertion and unexpected-variant panics remain
unchanged, and the production `expect_used = "deny"` lint remains in
place.
The cleanup is mechanical and net-negative in line count.
## Why
`terminal_resize_reflow` is now stable and should behave as always on.
Keeping the disabled runtime paths around made the feature look
configurable even though the rollout is complete, and old config could
still suggest there was a supported off mode.
## What Changed
- Marked `terminal_resize_reflow` as `Stage::Removed` while keeping it
default-enabled for compatibility.
- Ignored `[features].terminal_resize_reflow` config entries so stale
`false` settings no longer affect the effective feature set.
- Removed TUI branches that depended on the flag being disabled, so
draw, replay buffering, stream finalization, and resize scheduling all
assume resize reflow is active.
- Simplified resize smoke coverage to exercise the always-on behavior
only.
## Verification
- `just test -p codex-features`
- `just test -p codex-tui resize_reflow`
- `just test -p codex-tui initial_replay_buffer
thread_switch_replay_buffer`
## Why
The TUI startup test surface had drifted into expensive, brittle
coverage:
- `tui/tests/suite/no_panic_on_startup.rs` was already ignored as flaky
while still spawning a PTY to exercise malformed exec-policy rules.
- `tui/tests/suite/model_availability_nux.rs` used a seeded session,
cursor-query spoofing, and repeated interrupts to verify a narrow
resume-path invariant.
- `app/tests.rs` had started accumulating unrelated startup and summary
coverage in one flat module even after the surrounding app code was
split into feature modules.
This keeps those behaviors covered while making the tests cheaper to
understand and less likely to rot. It also preserves the malformed-rules
regression from #8803 without requiring a terminal orchestration test.
## What changed
- Replaced the malformed `rules` startup PTY case with a direct
exec-policy loader regression:
[`rules_path_file_returns_read_dir_error`](https://github.com/openai/codex/blob/21b6b5622f18b8cac0ea41fd083b3106778d9ffc/codex-rs/core/src/exec_policy_tests.rs#L264-L284)
- Made the existing fresh-session-only startup tooltip behavior explicit
with
[`should_prepare_startup_tooltip_override`](https://github.com/openai/codex/blob/21b6b5622f18b8cac0ea41fd083b3106778d9ffc/codex-rs/tui/src/app/thread_routing.rs#L1272-L1279),
then added focused coverage for the resume/fork gate and the persisted
NUX counter.
- Split startup and session-summary coverage out of
`tui/src/app/tests.rs` into dedicated modules so the test layout better
mirrors the current app architecture.
- Converted one single-message goal validation snapshot into semantic
assertions where layout was not the behavior under test.
- Removed the two PTY-heavy suite files that the narrower tests now
supersede.
## Verification
- `cargo test -p codex-core rules_path_file_returns_read_dir_error`
- `cargo test -p codex-tui startup_`
- `cargo test -p codex-tui session_summary_`
- `cargo test -p codex-tui
goal_slash_command_rejects_oversized_objective`
## Why
`CODEX_RS_SSE_FIXTURE` let integration-style CLI, exec, and TUI tests
bypass the normal Responses transport by reading SSE from local files.
That kept test-only behavior wired through production client code. The
affected tests can stay hermetic by using the existing
`core_test_support::responses` mock server and passing `openai_base_url`
instead.
## What Changed
- Removed the `CODEX_RS_SSE_FIXTURE` flag,
`codex_api::stream_from_fixture`, the `env-flags` dependency, and the
checked-in SSE fixture files.
- Repointed the affected core, exec, and TUI tests at `MockServer` with
the existing SSE event constructors.
- Removed the Bazel test data plumbing for the deleted fixtures and
refreshed cargo/Bazel lock state.
## Verification
- `cargo build -p codex-cli`
- `cargo test -p codex-api`
- `cargo test -p codex-core --test all responses_api_stream_cli`
- `cargo test -p codex-core --test all
integration_creates_and_checks_session_file`
- `cargo test -p codex-exec --test all ephemeral`
- `cargo test -p codex-exec --test all resume`
- `cargo test -p codex-tui --test all
resume_startup_does_not_consume_model_availability_nux_count`
- `just bazel-lock-update`
- `just bazel-lock-check`
- `just fix -p codex-api -p codex-core -p codex-exec -p codex-tui`
- `git diff --check`
## Why
Some consumers expect conventional hyphenated HTTP headers. Codex
already sends the session and thread IDs on outbound Responses requests,
but it only uses the underscore spellings today, which makes those IDs
harder to consume in systems that normalize or reject underscore header
names.
Full context here:
https://openai.slack.com/archives/C08KCGLSPSQ/p1778248578422369
## What changed
- `build_session_headers` now emits both `session_id` and `session-id`
when a session ID is present.
- It does the same for `thread_id` and `thread-id`.
- Added regression coverage in `codex-api/tests/clients.rs` and
`core/tests/suite/client.rs` so both the lower-level client tests and
the end-to-end request tests assert the two header spellings are
present.
## Test plan
- Added header assertions in `codex-api/tests/clients.rs`.
- Added request-header assertions in `core/tests/suite/client.rs` for
both the `/v1/responses` and `/api/codex/responses` request paths.
## Why
Message history was implemented inside `codex-core` and surfaced through
core protocol ops and `SessionConfiguredEvent` fields even though the
current consumer is TUI-local prompt recall. That made core own UI
history persistence and exposed `history_log_id` / `history_entry_count`
through surfaces that app-server and other clients do not need.
This change moves message history persistence out of core and keeps the
recall plumbing local to the TUI.
## What changed
- Added a new `codex-message-history` crate for appending, looking up,
trimming, and reading metadata from `history.jsonl`.
- Removed core protocol history ops/events: `AddToHistory`,
`GetHistoryEntryRequest`, and `GetHistoryEntryResponse`.
- Removed `history_log_id` and `history_entry_count` from
`SessionConfiguredEvent` and updated exec/MCP/test fixtures accordingly.
- Updated the TUI to dispatch local app events for message-history
append/lookup and keep its persistent-history metadata in TUI session
state.
## Validation
- `cargo test -p codex-message-history -p codex-protocol`
- `cargo test -p codex-exec event_processor_with_json_output`
- `cargo test -p codex-mcp-server outgoing_message`
- `cargo test -p codex-tui`
- `just fix -p codex-message-history -p codex-protocol -p codex-core -p
codex-tui -p codex-exec -p codex-mcp-server`
Fixes multiple scrollback and terminal resize issues: #5538, #5576,
#8352, #12223, #16165, and #15380.
## Why
Codex writes finalized transcript output into terminal scrollback after
wrapping it for the current viewport width. A later terminal resize
could leave that scrollback shaped for the old width, so wider windows
kept narrow output and narrower windows could show stale wrapping
artifacts until enough new output replaced the visible area.
This is also the foundation PR for responsive markdown tables. Table
rendering needs finalized transcript content to be width-sensitive after
insertion, not only while content is first streaming. Markdown table
rendering itself stays in #18576.
## Stack
- PR1: resize backlog reflow and interrupt cleanup
- #18576: markdown table support
## What Changed
- Rebuild source-backed transcript history when the terminal width
changes. `terminal_resize_reflow` is introduced through the experimental
feature system, but is enabled by default for this rollout so we can
validate behavior across real terminals.
- Preserve assistant and plan stream source so finalized streaming
output can participate in resize reflow after consolidation.
- Debounce resize work, but force a final source-backed reflow when a
resize happened during active or unconsolidated streaming output.
- Clear stale pending history lines on resize so old-width wrapped
output is not emitted just before rebuilt scrollback.
- Bound replay work with `[tui.terminal_resize_reflow].max_rows`:
omitted uses terminal-specific defaults, `0` keeps all rendered rows,
and a positive value sets an explicit cap. The cap applies both while
initially replaying a resumed transcript into scrollback and when
rebuilding scrollback after terminal resize.
- Consolidate interrupted assistant streams before cleanup, then clear
pending stream output and active-tail state consistently.
- Move resize reflow and thread event buffering helpers out of `app.rs`
into dedicated TUI modules.
- Add focused coverage for resize reflow, feature-gated behavior,
streaming source preservation, interrupted output cleanup,
unicode-neutral text, terminal-specific row caps, and composer/layout
stability.
## Runtime Bounds
Resize reflow keeps only the most recent rendered rows when a row cap is
active. The default is `auto`, which maps to the detected terminal's
default scrollback size where Codex can identify it: VS Code `1000`,
Windows Terminal `9001`, WezTerm `3500`, and Alacritty `10000`.
Terminals without a dedicated mapping use the conservative fallback of
`1000` rows. Users can override this with `[tui.terminal_resize_reflow]
max_rows = N`, or set `max_rows = 0` to disable row limiting.
## Validation
- `just fmt`
- `git diff --check`
- `cargo test --manifest-path codex-rs/Cargo.toml -p codex-tui reflow`
- `cargo test --manifest-path codex-rs/Cargo.toml -p codex-tui
transcript_reflow`
- `just fix -p codex-tui`
- PR CI in progress on the squashed branch