Commit Graph
891 Commits
Author SHA1 Message Date
Eric Traut 8b5ce2fd61 Add local image thumbnails to the TUI composer (#58261)
## What changed

- Show draft attachment thumbnails in reference order in inline and fullscreen views on supported terminals with local workspaces. Display a `+N` count for attachments that do not fit, and preserve editable image references when previews are unavailable or space is limited.
- Refresh previews when attached files change, apply image orientation metadata, and clear frame graphics before terminal handoffs, screen switches, and shutdown.
- Finish CLI subcommand dispatch before polling interactive TUI events.

## Testing

Add a regression test and snapshot covering thumbnail order, overflow, resizing, attachment deletion, file replacement, and fallback behavior in both inline and fullscreen views.

GitOrigin-RevId: 1ea7c89e089cecc390e145c1790b6ede8bad8d5e
2026-10-30 06:37:32 +00:00
Abhinav 55c099a142 Keep chats accessible across model provider changes (#58202)
## Why

Switching model providers can hide saved chats from resume lookup or prevent them from opening. Keep their history readable when the server rejects resuming because of a provider mismatch, missing configuration, or policy conflict.

## What changed

- Include all providers in the resume picker, named resume lookup, and `resume --last`, while retaining provider filtering for fork lookup.
- Open chats with provider errors as read-only history and show an explanation with recovery shortcuts: `c` to continue in a new chat, `n` to start fresh, and `Esc` to choose another chat.
- Continuing in a new chat prepares an editable, unsent prompt referencing the saved conversation.
- Preserve drafts and rejected prompts or steers, suppress automatic submission, and retry provider admission when reopening the chat.

## Testing

Add coverage for cross-provider discovery, read-only history, configuration recovery, continuation drafts, rejected input recovery, error rendering, and Escape handling during transcript browsing.

GitOrigin-RevId: 5aaa7a404b9a6231101599adef18d2f1e4a8020a
2026-10-30 00:45:30 +00:00
Joe Savona 797bab4746 Add an experimental UI tree renderer for the status line (#57970)
## What changed

- Add the disabled-by-default `tui_extensions_statusline` feature to render configured status items and their picker preview through a shared UI tree renderer.
- Support text, HTTP(S) links, rows, spacers, dividers, and gaps with rendering budgets, text sanitization, and width-aware truncation that keeps the ellipsis outside hyperlinks.
- Use plain text for the extension status line and hide the picker's theme color toggle while preserving the saved color preference.

## Testing

Add coverage for tree serialization and URL validation, Unicode widths, hyperlink clipping, picker previews, color preference preservation, and token usage updates across renderer switches.

GitOrigin-RevId: a6b87c2b1096765d61296d73e142834fcd53ceee
2026-10-29 03:07:15 +00:00
Eric Traut 118aae2a5f Explain safety policy blocks with turn-scoped recourse in the TUI (#57363)
## What changed

- Handle `TurnModerationMetadata` for the active turn, showing a temporary block notice while an explanation is pending.
- Validate safety recourse metadata and render topic-specific explanations with safer ways to continue for biological and cybersecurity policy blocks. Apply the explanation only when the terminal policy error matches its domain; otherwise retain the existing error handling.
- Queue input while recourse is pending and preserve prepared images when queued messages are submitted.

## Testing

Add an integration test covering biological and cybersecurity blocks, the loading notice, and fallback for a mismatched policy error, plus a snapshot of the cybersecurity explanation. Extend queued-image coverage to verify submission succeeds after the original image file is removed.

GitOrigin-RevId: dd9ca57cf3b2d842e3deb8aff5d7c3c73a92e14d
2026-10-27 05:15:31 +00:00
Ian MacLeod b52a272cff Render async questions and replies with Markdown in the TUI (#57292)
## Why

Async question replies appeared as plain user text, leaving Markdown formatting literal and repeating the full question above each answer.

## What changed

- Accent question titles with a `?` prefix while preserving Markdown in titles and suggestions.
- Render replies with a `↪ Re:` question caption and a Markdown answer. Limit captions to two rows with an ellipsis on overflow, while keeping answers complete.
- Apply the same rendering to live messages and loaded transcripts, preserving inline styles, hyperlinks, and Markdown when copying selections.

## Testing

Add snapshots and assertions for matching live and loaded transcript rendering, plus tests for caption clipping, hyperlink bounds, Markdown copying, partial selections, and whitespace-only or nonprinting answers.

GitOrigin-RevId: 0290d8a2ebfb42bd5d7374c7037cde5ae8a13b5d
2026-10-26 22:12:07 +00:00
Charlie Marsh a797dd7c6f Expose lifecycle timestamps on app-server thread items (#57172)
## What changed

- Add nullable `startedAtMs` and `completedAtMs` fields to `ThreadItem` in live notifications and turn history. Values are Unix milliseconds when recorded.
- Preserve recorded item times through history reconstruction, pagination, and resume, including command start times recorded during approval.
- Separate the Rust item payload into `ThreadItemPayload` while keeping the JSON payload flat, and update consumers, schemas, and generated TypeScript and Python types.

## Testing

Extend coverage for timestamp serialization, history reconstruction, paginated reads and resume, and persisted Python SDK items.

GitOrigin-RevId: ecbcee95af52db7c807b46a6e9deb30e5fba1f80
2026-10-26 18:13:00 +00:00
Eric Traut 7389eebf45 Fix TUI permission selection and session state handling (#55682)
## Why

Queued prompts can resume before a pending permissions menu opens, and local
`/permissions` commands can bypass guards for outstanding permission changes.
Attaching to a different project can also retain model access information from
the launch directory.

## What changed

- Route `/permissions` through app permission guards and hold queued prompts
  while the menu is pending. Settle the hold when opening is rejected, discovery
  is invalidated, or a covering request is resolved.
- Apply the custom permission profile selection check beyond embedded servers.
- Refresh API-key model access when the first attached session changes the
  working directory, including with an embedded server. Propagate the widget's
  model catalog to the app and server even when the model response matches the
  widget's already-updated catalog.
- Skip sessions reported as `thread not loaded` during name lookup for all
  server types instead of falling back to unverified list metadata.

## Testing

Add regression coverage for permission guards, queued prompts across successive
permission menus, invalidated and covered menus, model catalog propagation,
project changes on initial attachment, and name lookup across server pages with
unreadable entries.

GitOrigin-RevId: eb49cb5268ce0ce1e40009b73a0180f23e61ed72
2026-10-20 21:40:30 +00:00
Channing Conger 8dd6099e26 Remove thread title generation spinners from the TUI (#55324)
## What changed

Stop showing title-generation spinners in the footer, status line, and terminal title. Remove the associated UI pending state and animation refresh logic while retaining background title generation.

## Testing

Add a snapshot covering the footer and terminal title while automatic naming is pending. Update status-surface snapshots to cover thread names and ID fallbacks without progress indicators.

GitOrigin-RevId: 061456929149c216f0a98d7214179ec69cdaeee4
2026-10-19 17:09:36 +00:00
Felipe Coury 141bf7680d Add session-only arguments to /title and /statusline (#54387)
## What changed

Allow inline item selection, such as `/title model reasoning` and `/statusline current-dir --no-colors`, without changing saved defaults. Support `--clear` for both commands and `--colors` or `--no-colors` for `/statusline`, including color-only updates that preserve the current items.

Carry overrides with per-thread input state across navigation and reconnects, and allow these local commands in parent-owned subagent threads. Reject invalid or conflicting arguments before applying changes. Saved editor selections supersede the corresponding overrides.

## Testing

Add coverage for argument parsing, atomic updates, rate-limit item aliases and ambiguity, thread-state restoration, saved-setting interactions, and local command submission in parent-owned threads.

GitOrigin-RevId: 909cc2ede026fbf5c7f9cd52c8cf2ae835084f14
2026-10-15 19:11:32 +00:00
Felipe Coury 36803b180a Allow saving current permission settings as presets (#54385)
## Why

Creating a preset from current settings only offered the model. Permission presets need to preserve the profile, approval policy, and reviewer to restore the same settings.

## What changed

- Add a “Current permissions” option alongside “Current model” when creating a preset from settings.
- Extend `/permissions` with `--approval-policy` and `--reviewer`, including granular policies and quoted profile names.
- Share argument parsing between `/model` and `/permissions`, supporting quoted arguments and both `--setting=value` and `--setting value` forms.
- Keep full-access confirmation for every reviewer and reject automatic review when unavailable.

## Testing

Add parser tests, preset picker snapshots, and permission-selection tests covering complete settings restoration, invalid arguments, unavailable automatic review, and full-access confirmation.

GitOrigin-RevId: f4c9c3f6e264ee8ea4c5244c79f39f2deb15b771
2026-10-15 19:11:06 +00:00
Felipe Coury b095b2ef23 Support inline permission profile selection with /permissions (#54383)
## What changed

Allow `/permissions <profile-id>` to select a built-in or custom permission profile, for example `/permissions :read-only`. Support `:ask-for-approval` and `:approve-for-me` aliases while preserving feature gates, profile requirements, full-access confirmation, and Windows sandbox setup.

Hold queued input until the selection is confirmed, and retain it on cancellation or failure. Reload custom profile definitions on re-selection without leaving unchanged requests pending.

## Testing

Add coverage for unknown and disabled profiles, approval aliases, confirmation and cancellation, discovery retries, Windows sandbox setup, and queued prompts waiting for server confirmation.

GitOrigin-RevId: ada38d3cfc6d6ac4e84ce5645fe33432c55d63cc
2026-10-15 19:09:34 +00:00
Felipe Coury 111362a6a0 Add a keyboard shortcut menu for presets (#54381)
## What changed

Replace the `/presets` recall picker with a responsive menu above the composer. Press `0`–`9` to run a saved preset or create one in an empty slot; use `n`, `s`, `e`, and `d` to create, start from current settings, edit, and delete presets.

Add `tui.keymap.chat.open_presets` with an implicit `leader p` shortcut that yields to existing bindings and explicit configuration. Show the action in `/keymap` and add a shortcut tooltip.

Preserve the composer draft, respect popup ownership, and consume held-key repeats after menu actions.

## Testing

Add snapshots for empty, populated, and narrow preset menus, plus coverage for draft preservation, cancellation, held-key handling, transcript search precedence, and default shortcut conflicts.

GitOrigin-RevId: f438c7015dbd416c90cdeb479d2a15d9d6d24954
2026-10-15 19:02:34 +00:00
Felipe Coury dcd9e95459 Add /presets for reusable prompts and slash commands (#54380)
## What changed

- Add a TUI picker with ten numbered preset slots, an editor, and confirmation before replacement or deletion.
- Create presets from composer text or current model, reasoning effort, and speed settings. Run saved inputs through the normal queued submission path while preserving the composer draft.
- Persist presets under `tui.presets` in the active user configuration, respecting configuration layer ownership and leaving in-memory settings unchanged when writes fail.
- Preserve permissions when changing effort or speed for the effective model, keep default collaboration settings intact in Plan mode, and allow standard-speed selection with older app servers.

## Testing

Add persistence tests for save, replace, delete, configuration ownership, and write failures; picker and confirmation snapshots; and regression coverage for model permissions and standard-speed fallback.

GitOrigin-RevId: 5f11699112cd404cc8e954872d53495c6edd0c0a
2026-10-15 19:02:09 +00:00
Felipe Coury 0884c8047a Support inline model, reasoning, and speed selection in /model (#54378)
## What changed

Allow `/model [model] --reasoning <level> --speed <tier>` to update the current session without changing saved defaults. Both space-separated and `=` flag values are supported; omitting the model applies settings to the current model. Bare `/model` still opens the picker.

Validate model availability, supported reasoning levels, and speed tiers before applying changes. Reject unknown flags, duplicate settings, and missing values. Apply model, reasoning, and speed together after server acceptance.

Restore each thread's speed when switching threads, and use destination configuration defaults for new sessions instead of carrying over the active session's speed.

## Testing

Extend regression coverage for inline commands, invalid arguments, unchanged saved defaults, settings-only updates to hidden current models, destination speed defaults, and speed restoration on the next turn after switching threads.

GitOrigin-RevId: ad9cecbdb3554e34a6518367364978a37fb68439
2026-10-15 19:01:10 +00:00
Ian MacLeod c22a06c180 Record bucketed terminal sizes in TUI telemetry (#53859)
## What changed

- Add `terminal_columns` and `terminal_rows` buckets to `codex.tui.start`.
- Record `codex.tui.terminal_size` for new turns in the active thread and for resize bucket changes after the terminal size settles for 15 seconds. Reuse launch context and suppress duplicate turn notifications.
- Respect analytics consent for the built-in metrics exporter while allowing explicitly configured OTLP collectors. Apply consent checks to the active exporter across provider replacements.

## Testing

Add coverage for exporter replacement and consent after config reloads. Extend the PTY integration test to verify startup size buckets, turn-start observations, and delayed resize observations with analytics disabled and an explicit OTLP collector.

GitOrigin-RevId: e01a900cd3f04a36731078f725c75374596cb01b
2026-10-14 03:52:30 +00:00
Felipe Coury cc7ba33601 Add a searchable /config preferences panel to the TUI (#52990)
## What changed

- Group preferences into Appearance, Notifications, Input, Sessions, and Text selection tabs, with search and links to existing theme, status line, terminal title, and keyboard editors.
- Persist preference changes to the selected local configuration file, apply supported changes immediately, and show save errors, configuration overrides, and restart requirements in the panel.
- Add a delayed notification test and controls for notification timing while preserving custom event filters.
- Add `tui.copy_on_select_clear_selection`, disabled by default, to clear transcript selection highlights only after confirmed automatic clipboard delivery.
- Keep local configuration editors usable while disconnected and prevent held activation keys or buffered input from triggering actions across editor and reconnect transitions.

## Testing

Add regression tests and rendering snapshots for panel navigation, search, dependency states, editor handoffs, offline persistence, notification timers, custom filter preservation, and confirmed-copy deselection.

GitOrigin-RevId: a16d218046060fcb6e61705a803fcd9297266e6e
2026-10-10 22:28:01 +00:00
Benjamin Carlsson 322bbf4d84 Classify voice session failures and record terminal outcomes (#52756)
## Why

Voice failure metrics lacked cause and lifecycle phase, and session durations were recorded before the final outcome was known. A failed control send could also overwrite a more specific WebRTC error.

## What changed

- Tag `codex.voice.session.failure` with bounded `cause` and `phase` values, recording at most one failure per session.
- Capture duration when stopping and emit `codex.voice.session.duration` at cleanup with a `success` or `failure` outcome.
- Carry typed WebRTC errors into the TUI, preserve existing errors when control sends fail, and avoid duplicate errors after startup failure.
- Record app-server disconnect failures for background voice sessions as well as the visible session.

## Testing

Add coverage for terminal outcome and failure metric attributes, preservation of specific startup and audio-session errors, and startup failures without duplicate control-channel errors.

GitOrigin-RevId: 5aeda6e766093e3fce7206560aa83b6f7770dddb
2026-10-10 02:54:59 +00:00
Felipe Coury 4bad6d78e9 Report terminal program status with OSC 7501 (#52725)
## Why

Lifecycle status reporting was limited to direct iTerm2 sessions. OSC 7501 lets other terminals receive Codex's program state.

## What changed

- Emit OSC 7501 with `app=codex` and states `idle`, `working`, or `blocked` whenever stdout is a terminal, including multiplexed sessions. Report `blocked` when user action is required.
- Continue emitting iTerm2's OSC 21337 status and bounded activity details in direct iTerm2 sessions.
- Clear status before handing the terminal to an external program, as well as on suspension and exit, and re-emit the current state after returning.

## Testing

Add coverage for OSC 7501 encoding, combined iTerm2 output, clearing both protocols, and protocol selection across terminal and multiplexer environments. Update lifecycle tests and status snapshots for the new protocol.

GitOrigin-RevId: 6d2a6885687b0e7af825e954fab72db0765c9a07
2026-10-09 23:43:10 +00:00
Felipe Coury 39f4277087 Enable text selection in the fullscreen TUI footer (#52270)
## What changed

Allow mouse selection and plain-text copying of rendered status and footer text, honoring `tui.copy_on_select` and existing selection keyboard controls. Keep the selected region stable while other content updates, preserve Unicode and terminal hyperlinks, and clear selections when their region becomes invalid.

Defer warning clicks until a stationary mouse release so dragging selects text without opening the warning viewer. Preserve the composer draft and cursor while selecting footer text.

## Testing

Add unit and snapshot coverage for visible-text copying, Unicode and hyperlinks, selection invalidation, keyboard ownership, and stationary clicks versus drags. Add a fullscreen integration test for warning selection and draft preservation.

GitOrigin-RevId: dd14d7ede52e97e507be24c4d6ac0299f7388a9b
2026-10-08 20:49:14 +00:00
Felipe Coury 96d238d0b9 Include foreground activity in iTerm2 session status (#52226)
## Why

The iTerm2 session status reports `Working` without describing the current activity.

## What changed

Populate the OSC 21337 `detail` field from the TUI status header during foreground work, for example `Reading source`. Leave it empty for idle, waiting, background-only work, and the generic `Working` header.

Reuse terminal-title text filtering and the 240-character limit, then escape semicolons and backslashes for the status payload. Include detail in the emission cache so activity changes update the terminal even when the lifecycle state stays the same.

## Testing

Add coverage for foreground-only details, payload encoding, text filtering and truncation, and cache updates when the detail changes.

GitOrigin-RevId: b27a287b80e0db52be6cd9d5d246f03897e2996b
2026-10-08 18:56:04 +00:00
Felipe Coury ade12342e2 Expose Codex lifecycle status in iTerm2 sessions (#52203)
## What changed

Emit `Idle`, `Working`, or `Waiting` with colored indicators through iTerm2's `OSC 21337` session status protocol. Pending user action takes precedence over running tasks and background processes.

Limit emission to direct iTerm2 TTY sessions without a terminal multiplexer. Deduplicate successful writes, refresh status after terminal handoffs and resume, and clear status on suspension and exit.

## Testing

Add coverage for lifecycle transitions, protocol encoding, terminal detection, write retries, deduplication, and re-emission after terminal handoffs.

GitOrigin-RevId: 750e9ec92aeefc57651886a08ef6aea07675d175
2026-10-08 18:07:35 +00:00
Adam Perry @ OpenAI c9870d0157 Use PathUri for skill identity and path matching (#51482)
## Why

Skill selection and disabled-path matching need to recognize equivalent Windows paths across case and separator differences while preserving literal spaces, `%`, and `#` in native filenames.

## What changed

- Carry `PathUri` through skill metadata, discovery mappings, filesystem lookups, disabled-path sets, and invocation analytics.
- Match linked skill mentions and TUI selections by parsed path identity.
- Use `LegacyAppPathString` for app-server skill paths and regenerate schemas and SDK types, preserving native path strings on the wire.
- Preserve native catalog display paths and ordering. Keep host filesystem probes and configuration writes restricted to host-compatible paths.

## Testing

Add regression tests for Windows path identity and disabled-skill matching, literal filename characters, catalog resource reads, native path ordering, and foreign-path analytics normalization.

GitOrigin-RevId: c212916dc9fef0e7616542726e107f0d6a313267
2026-10-06 21:29:35 +00:00
Eric Traut ff9ab4aed9 Suppress repeated image paste presses in legacy terminals (#51411)
## Why

Legacy terminals report key auto-repeat as new presses, which can trigger repeated image pastes when presses accumulate during a slow paste.

## What changed

Suppress repeated `Ctrl+V` and `Alt+V` image paste presses within a sliding 250 ms window, refreshed after each suppressed press and after a paste completes. Clear suppression on other ordinary key presses or key release events so a fresh paste can proceed immediately.

## Testing

Add regression coverage for repeated presses, window expiry, and resetting suppression on another key press or a key release. Update the shortcut remapping test to release the key between image pastes.

GitOrigin-RevId: 45abc056e5bda47d1c9704702e369e63dcce29db
2026-10-06 16:41:53 +00:00
Benjamin Carlsson d42aecc56b Center TUI confirmations over their retained backdrop (#50504)
## What changed

Render confirmation dialogs as centered overlays while preserving the composer or parent picker behind them. Share dialog sizing and cursor placement across stacked views and full transcript rendering, with input still routed exclusively to the active dialog.

Use the shared confirmation preset for prompts including full access, session archive/delete, goal changes, and log upload consent.

## Testing

Add coverage for backdrop retention and cursor routing at multiple terminal sizes, and for preserving the compact viewport and composer draft after dismissing a confirmation without replaying history. Update confirmation snapshots to show the retained backdrop.

GitOrigin-RevId: 026af89904ec345e2b330317b8cc844512125d0e
2026-10-03 03:00:46 +00:00
Benjamin Carlsson 37f53199a6 Use the shared text editor for command-center task renaming (#50216)
## What changed

Replace the rename field with a single-line `TextArea` that honors configured editor bindings and the composer's Vim setting. Start renaming in insert mode and support Vim Escape recovery on legacy terminals.

Strip carriage returns and newlines from titles and pasted text, keep Vim linewise pastes inline, and scroll horizontally at grapheme boundaries to keep the cursor visible.

## Testing

Add single-line editor coverage for newline filtering, Vim commands, repeat edits, and inline yanks. Extend command-center tests to cover Vim renaming across status-filter changes and cursor placement in narrow layouts.

GitOrigin-RevId: 8d320d6b6de9f77e18292169418383929ca6ceda
2026-10-02 07:22:28 +00:00
Eric Traut cb6da58876 Use the server permission catalog for TUI permission shortcuts (#50140)
## Why

Permission shortcuts checked local configuration while the picker used the connected server's catalog and requirements. Shortcuts should respect the same server restrictions, including model-specific auto-review requirements.

## What changed

- Share a cached server catalog between the permission picker and shortcuts. Show the loading picker when no catalog is available and reuse an outstanding fetch.
- Clear the cache on session, account, working-directory, or connection changes.
- Give discovery RPCs distinct request IDs for each fetch and profile page so repeated requests after timeouts do not collide.

## Testing

Add coverage for loading and catalog reuse, managed permission restrictions, and refetching after disconnect. Update timeout coverage to verify that repeated discovery attempts use distinct IDs and each reports a timeout.

GitOrigin-RevId: 7d79874294136bfe3a654bb306eb7caf36d4df1e
2026-10-02 01:34:23 +00:00
Eric Traut e1522188e9 Add a persistent /daybreak toggle to the TUI (#49858)
## What changed

- Add `/daybreak` with account-aware help and availability messages for broader access for cybersecurity work.
- Save the selection in thread metadata and the `daybreak` default for new threads, restore it on resume, and confirm that it applies to new turns.
- Select `cyberAccessProgram` from the connected server's model catalog. Require a signed-in ChatGPT account, the OpenAI provider, and confirmed model support when Daybreak is enabled, including for faster-model retries. Keep Daybreak disabled for side conversations.

## Testing

Add tests for toggle persistence, turn access-program selection, unsupported-model rejection, side-conversation behavior, command help, and the resumed-thread banner.

GitOrigin-RevId: e3c028b0a6a8e0a862c16fdc766f374aae618ef1
2026-10-01 04:17:31 +00:00
Eric Traut f58ed54a9d Use the model catalog to select TUI cyber refusal guidance (#49857)
## What changed

Select cyber refusal notices from the current model's `available_access_programs` for ChatGPT accounts using the OpenAI provider. Show Astra-specific guidance only when an Astra model offers standard cyber access without Daybreak access, and use the limited notice when Daybreak access is available. Otherwise, show application guidance.

Remove the separate account eligibility request, background prefetching, and notice cache.

## Testing

Update tests to cover catalog-based notice selection, missing model metadata, isolation from other models' access programs, and rendering the application notice for a cyber policy error.

GitOrigin-RevId: 88e9522bd6ece2d2b9caa6cff01a4178768babb7
2026-10-01 04:17:07 +00:00
dennyku 60947e2341 Add account security setup reminders to the TUI (#49715)
## What changed

Fetch optional security setup notices asynchronously for local ChatGPT sessions using the OpenAI provider. Verify that saved credentials match the connected app server, ignore stale account responses, and validate notice text and HTTPS actions on `chatgpt.com`.

Show notices as dismissible inline banners with a browser action, while giving applicable usage banners priority. Preserve notice state and dismissal across thread changes, reconnects, and banner replacement for the same account and user.

## Testing

Add authenticated HTTP fixture tests, notice validation tests, and TUI tests covering stale responses, dismissal persistence, usage banner priority, browser actions, and wrapping in narrow terminals.

GitOrigin-RevId: b8635fcf6a26b42b6a06640601c8517d8d5e47e8
2026-09-30 19:22:34 +00:00
Eric Traut 136391a23e Resume unsent TUI input after reconnecting (#49105)
## Why

Reconnecting paused all recovered input, including queued messages that had never been sent. Those messages can resume automatically once any uncertain submissions are resolved.

## What changed

- Track unsent and unconfirmed messages separately. Reconcile submitted prompts and steers using exact client message IDs from restored history, buffered events, and later receipts.
- Remove confirmed submissions from the recovered queue and resume unsent input after replay. Keep uncertain submissions paused without resending them, and show a notice identifying the message whose delivery could not be confirmed.
- Preserve pauses for unavailable conversations, pending compact/review requests, and existing input recovery failures.
- Simplify reconnect status text and remove blanket disconnect/reconnect transcript notices.

## Testing

Update reconnect integration tests and snapshots for automatic queue resumption. Add coverage for matching and unrelated receipts, missing history, late confirmations across navigation, pending compaction, and preservation of image-failure recovery pauses.

GitOrigin-RevId: d0b9aa43c4019d472985d12bbce8ba9bbfb9253b
2026-09-29 00:17:56 +00:00
Eric Traut 334b6e7321 Remove follow-up prompt suggestions from the TUI (#48621)
## What changed

Remove automatic next-message generation after successful turns, suggestion rendering in the composer, and the associated Tab acceptance and Escape dismissal handling. Remove the `tui.prompt_suggestions` configuration option and its schema entry, along with suggestion-specific tests and snapshots.

GitOrigin-RevId: 63bf6f2ca85da6ece502c86e2a805d000bf34210
2026-09-27 05:29:53 +00:00
Felipe Coury e8fdbf1f7c Use a consistent borderless session header in the TUI (#48562)
## What changed

- Use the compact title, version, and directory layout for all session headers, including resume, fork, and clear-screen flows. Remove the boxed model row and retain the optional greeting and YOLO permissions indicator.
- Share title styling with the status card and honor the active render mode and wrapping policy when inserting a fresh header after clearing the screen.

## Testing

Update header and startup snapshots for the borderless layout, narrow widths, and halfwidth directory characters. Add assertions that clearing history preserves the raw header in raw output mode.

GitOrigin-RevId: 0b91c1ce6646f9d9d1954b1442936abe93bdcd3c
2026-09-26 22:50:16 +00:00
Felipe Coury 7703f8b354 Dismiss viewed TUI warnings when closing the viewer (#48205)
## Why

Closing the warnings viewer left reviewed diagnostics in the warning badge and subsequent visits, with no way to dismiss them.

## What changed

- Dismiss only warning pages actually rendered when closing with `Esc`, `F2`, or `Ctrl+C`, and update the footer hint to “dismiss & close”. Unviewed warnings remain available.
- Hide dismissed diagnostics from the badge and viewer while their details are unchanged. Updated details make a warning visible again.
- Reset dismissals when clearing the transcript and ignore queued dismissals from an earlier transcript.
- Cache warning counts until transcript cell identities or dismissal decisions change.

## Testing

Add regression coverage for partial dismissal, navigation that skips rendering a page, changed warning details, and transcript resets with queued dismissals. Update snapshots for the close hint and remaining warning count.

GitOrigin-RevId: 3ce88c62a7f0ff9de34062165051e22168d3db25
2026-09-25 20:26:19 +00:00
Eric Traut e154f7b807 Generate TUI prompt suggestions after successful turns (#47929)
## What changed

Connect the existing composer suggestion UI to generation when `tui.prompt_suggestions` is enabled. Request suggestions after successful live turns with known reasoning-summary settings, skipping replayed or duplicate completions and turns with queued follow-ups.

Generate suggestions in hidden, ephemeral forks of the completed turn, preserving conversation context and exposed live settings. Keep fork events out of the visible conversation and reject requests for user interaction. Cancel generation after 30 seconds, interrupt unsuccessful requests, and unsubscribe temporary threads.

Clear suggestions on new submissions, thread changes, reconnects, and feature disablement. Let Escape dismiss suggestions before entering backtrack mode.

## Testing

Add tests for live-turn eligibility and deduplication, preserved request prefixes and settings, hidden fork behavior, startup cancellation, and timeout cleanup.

GitOrigin-RevId: 92ddf3b06448adcc6f4330914cbd8102bff98046
2026-09-24 20:01:59 +00:00
Felipe Coury f6fd7f17ed Clean up temporary Codex homes after TUI tests (#47894)
## Why

TUI test helpers used `TempDir::keep()`, leaving temporary Codex homes on disk after fixtures were dropped.

## What changed

Retain `TempDir` ownership in widget and app fixtures so their homes are removed on drop. Transfer ownership to app fixtures to keep the home alive across widget replacement, and retain directory guards in tests that use configs directly.

## Testing

Add regression tests for recursive cleanup, isolation between widget homes, and app home survival across widget replacement followed by cleanup on app drop.

GitOrigin-RevId: fe80f982cc467ede4c3e1edbac8012ec3066dfb3
2026-09-24 17:43:15 +00:00
Felipe Coury 12fd929f72 Keep the TUI responsive during clipboard copies (#47847)
## Why

Native clipboard setup and writes can block, preventing the TUI from processing input or closing overlays while a copy is in progress.

## What changed

- Route clipboard copies through one session worker that retains native clipboard ownership. Keep terminal escape output on the UI thread.
- Show pending and busy status messages, reject additional copies without queuing them, and ask users to retry image paste after an active copy finishes.
- Abandon setup after five seconds and prevent late delivery. Keep the worker busy until the blocked call returns, and bound shutdown waiting for clipboard handoff.
- Match completions to their originating requests so stale results cannot clear newer selections or unexpectedly resume transcript following. Retain selections on automatic copies, failures, and unconfirmed delivery.

## Testing

Add regression tests for blocked backends, overlay exit, copy and paste ordering, setup expiry, bounded shutdown, completion status messages, and preservation of replaced or moved selections.

GitOrigin-RevId: 4ba1f8da258b9d0700b0edec9ac0ba699f536785
2026-09-24 14:15:42 +00:00
Ian MacLeod 591ffb1aae Prefer Shift-arrow hints for queued messages and questions (#47618)
## Why

Queued-message edit hints could vary by terminal instead of showing the first configured shortcut. Use the keymap consistently for queued messages and async question navigation.

## What changed

- Make `Shift+Left` the primary shortcut for advancing through questions and editing the last queued message, and `Shift+Right` for navigating back toward the composer. Keep `Alt+Up` and `Alt+Down` as alternatives.
- Remove terminal-specific hint selection and derive hints from the configured keymap, including custom chords and unbound actions.
- Update question footers, queued-input previews, and keymap picker snapshots to reflect the preferred shortcuts.

## Testing

Extend tests to cover both default shortcut pairs, configured shortcut ordering, custom chord hints, and hiding the queued-message edit hint when the action is unbound.

GitOrigin-RevId: e0f60860ef1e81c71ca0fc32369b8cbd12582b47
2026-09-23 18:39:19 +00:00
Eric Traut 00d92ad3ee Standardize TUI menu description wording and punctuation (#47329)
## What changed

Remove trailing periods from concise built-in option descriptions and disabled-option explanations, and simplify wording across TUI menus. Share the built-in permission preset descriptions between permission pickers.

Document the convention in `codex-rs/tui/styles.md`, including normal punctuation for descriptions with multiple sentences and preservation of externally supplied descriptions.

## Testing

Update menu assertions and rendering snapshots for the revised copy and line wrapping.

GitOrigin-RevId: 3231d25484178452ab001af5ddc982460d14f94a
2026-09-22 17:58:37 +00:00
Eric Traut 13a966fc65 Honor the system clock preference across more TUI timestamps (#47321)
## Why

Several TUI views hard-code 24-hour timestamps even when the detected system preference is 12-hour time.

## What changed

Use the existing `ClockFormat` preference for rate-limit and spend-control reset times, usage notices, backend banners, reset-credit expiration times, analytics timestamps, and expanded session details in the resume picker. Capture the preference when constructing views and preserve existing timezone handling, including analytics' UTC labels.

## Testing

Add coverage for midnight, noon, and next-day reset labels in both clock formats, plus 12-hour analytics rendering with UTC labels. Update snapshots for status, banners, usage notices, reset-credit details, and expanded sessions, including narrow-width layouts. Pin test fixtures to explicit clock formats for deterministic output.

GitOrigin-RevId: 73c36d603ddc4eb7800614650a14c6f2961f8b70
2026-09-22 16:23:59 +00:00
Felipe Coury d1092865f8 Allow forking conversations locked by another app in the TUI (#47185)
## Why

Conversations open in another app disable the composer. Let users continue in an editable fork while the original conversation remains owned by that app.

## What changed

- Add an `f`/`F` shortcut and footer hint to the locked conversation view, preserving local drafts and queued prompts in the fork.
- Show “Forking conversation…” while a fork is pending, block additional key input, and discard buffered input after forking from the locked view.
- Replace the previous session summary after a fork with “Fork created. You can continue here.”
- Keep the locked view and draft intact if the fork request fails.

## Testing

Add tests for shortcut ownership and modifiers, repeated input, editable forks that preserve drafts and queued prompts without taking the source lease, and failure recovery. Add snapshots for fork progress, completion, and the updated footer.

GitOrigin-RevId: 2ecdb0b7fc7e82d8295097faa567995d7a2f7d92
2026-09-22 03:49:43 +00:00
Felipe Coury bb054a2b03 Keep quota warnings visible in the TUI (#46912)
## Why

Quota warnings were hidden from normal transcript rendering, leaving no persistent reminder of remaining usage near the composer.

## What changed

- Show the most constrained quota window in the existing composer hint row, using the existing plan-specific warning thresholds. Include remaining usage, reset time, and `/status` when space permits.
- Keep the notice visible while typing or running a turn, even with tooltips disabled. Yield to interaction controls and blocking banners, and suppress the notice when usable credits are available.
- Preserve quota metadata across sparse updates and thread switches. Require a fresh account usage read to confirm recovery, ignore reads made stale by newer rolling updates, and clear notice state on account changes.
- Render quota warning history cells in both transcript modes while retaining warning counts and replay deduplication.

## Testing

Add unit, integration, and snapshot coverage for warning thresholds, narrow layouts, unchanged composer geometry, suppression, recovery, overlapping reads, account changes, and native transcript replay.

GitOrigin-RevId: e45dc94a6e7a9dad50307840b9fdb15978d053dc
2026-09-21 00:22:58 +00:00
Felipe Coury 2f34d236f5 Add /tui to choose the terminal UI mode for the next launch (#46883)
## 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
2026-09-20 20:38:26 +00:00
Eric Traut bba48e5ce8 Add independent controls for TUI visual effects (#46832)
## What changed

Replace `tui.whimsy` with `[tui.effects]` preferences for `starfield`, `shimmer`, `welcome`, `effort`, `progress`, and `title`. Each defaults to `true` and remains subordinate to the `tui.animations` master switch.

Wire the preferences into composer effects, welcome artwork, status and loading text, progress indicators, and terminal-title animations. For example, disable shimmering text while keeping progress animations:

```toml
[tui.effects]
shimmer = false
```

Keep retired `tui.whimsy` entries loadable but ignore their value. Update the configuration schema to expose the new preferences.

## Testing

Add and extend coverage for independent shimmer and progress effects, master-switch precedence, welcome and starfield controls, terminal-title blinking, and strict configuration loading with the retired setting.

GitOrigin-RevId: 28b37ba52872133b8954543cabe9ff424147f1c5
2026-09-20 16:16:46 +00:00
Eric Traut 5c5308fc9a Add an animated Codex logo to fresh conversations and onboarding (#46752)
## What changed

- Render a rotating Codex logo in unused space above the composer on fresh conversations, without moving content or the cursor.
- Fade and pause the logo while drafting or unfocused, hide it on alternate views, and dismiss it after submission or conversation activity. Respect disabled animations and stop after three rotations with a fade out.
- Replace the onboarding ASCII frame variants with the shared logo renderer, retaining a faded logo after the animation ends and allowing the existing shortcut to replay it.

## Testing

Add rendering and integration tests for logo placement, visibility, pause/resume timing, completion, and preservation of the draft, cursor, header, and footer. Add snapshots for fresh conversations and the onboarding welcome layout.

GitOrigin-RevId: b98c7dd10acea3ef25d6c1495ed22c24202d6280
2026-09-20 03:02:48 +00:00
Eric Traut 6b0a1a8325 Add a warning footer and dedicated warnings viewer to the TUI (#46751)
## 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
2026-09-20 03:02:25 +00:00
Eric Traut 9ed1b74699 Preserve startup drafts and submit them when the session is ready (#46750)
## 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
2026-09-20 03:02:02 +00:00
Eric Traut de6ae71ad4 Stabilize transcript and composer interactions in the TUI (#46749)
## Why

Composer suggestions and transient hints should preserve the draft and transcript context. Submitting a local command while reading older history should reveal its output.

## What changed

- Separate persistent status from transient footer hints in the owned transcript, sharing layout calculations for rendering, measurement, and cursor placement.
- Overlay command and mention suggestions on history without moving the composer; hide retained suggestions while transcript interactions own input.
- Show responsive, grouped shortcut help above the composer and let `Esc` dismiss it before interrupting a task or navigating history.
- Resume transcript following for submissions, slash commands, and last-response copy results while preserving the reading position during background updates.
- Reset transcript interaction state after prompt reverts and refresh retained usage information without rewriting terminal history.

## Testing

Add regression tests and snapshots for popup placement, clipped layouts, footer focus, shortcut dismissal, local-command scrolling, prompt reverts, and pagination while browsing prompts.

GitOrigin-RevId: 890147313d53f050503165a57610c381ffb93ef5
2026-09-20 02:59:37 +00:00
Eric Traut f1feda2299 Integrate the interactive transcript into the alternate-screen TUI (#46733)
## 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
2026-09-20 00:06:00 +00:00
Eric Traut 6ba6b73657 Render dynamic tool activity and preserve TUI history ordering (#46731)
## Why

The TUI ignored dynamic tool items, and replayed tool activity could differ from live output. Concurrent tool completion also needs to preserve transcript order when writing to terminal scrollback.

## What changed

- Retain dynamic tool rows, update them when calls finish out of order, and mark unfinished calls interrupted when a turn ends.
- Queue terminal output behind unfinished dynamic tools and drain settled rows in bounded batches. Preserve queued output through stream consolidation, resize, and rollback without emitting it twice.
- Align replayed file changes, MCP results, and exploration groups with live rendering. Keep hidden reasoning and terminal interaction details within compatible activity groups, and preserve finalized plan fragments.
- Ignore stale history-page responses, bound turn metadata requests to missing turns, and insert older history after session headers. Keep hidden review prompts as activity-group boundaries.

## Testing

Add regression tests and snapshots for out-of-order tool completion, interruption, ordered scrollback emission, rollback, deferred usage updates, replay consistency, overlapping history, and repeated hidden prompts.

GitOrigin-RevId: a3636cfcf4c9c43a0a5bc52a842b80a7834f1409
2026-09-20 00:03:43 +00:00
Eric Traut 30ab0ee65b Cache transcript layouts across measurement and rendering (#46720)
## Why

The transcript overlay separately generated cell content for height measurement and rendering. Active cells backed by external state could also leave the live tail stale when their revision key did not change.

## What changed

- Share retained text layouts between measurement and painting, and render only visible rows while preserving wrapping, styles, and hyperlinks.
- Reuse stable layouts across frames, invalidating them when width, animation, syntax theme, or terminal colors change. Bound retention by entry count and text size, allowing a single oversized entry.
- Refresh externally mutable cells each frame and bypass live-tail reuse when any active source is not cacheable.

## Testing

Add coverage for layout reuse, eviction, invalidation, and live-tail refresh without a revision change. Expand the transcript snapshot to cover styled text, wide glyphs, wrapping, and hyperlinks.

GitOrigin-RevId: 7dfb737e762f7f056a38774d956f618090809a62
2026-09-19 21:43:15 +00:00