TUI: interactive history search
What variant of Codex are you using?
CLI (TUI)
What feature would you like to see?
An Atuin-style Ctrl+R interactive history search in the TUI composer: open a popup
list of fuzzy-matched history (persistent + in-session), navigate with ↑/↓, Enter
inserts the selected entry, and Esc cancels and restores the prior draft
(including attachments/pending pastes).
Summary
Add an Atuin-like interactive history search to the TUI chat composer, triggered by Ctrl+R.
While active, typing edits a search query (not the draft), results are shown in a popup list,↑/↓ navigates matches, Enter inserts the selected history entry, and Esc cancels and restores
the prior draft (including attachments / pending pastes).
Motivation / user story
When iterating on prompts, it’s common to recall and lightly edit something typed earlier (often
from a prior session). Shell users expect Ctrl+R to open an interactive reverse-search and quickly
insert a previous command; bringing this to the composer makes prompt iteration much faster than
repeated Up/Down navigation.
UX / behavior
Entering search
- Press
Ctrl+Rin the composer: - Opens a “History search” popup.
- Captures the current draft so it can be restored on cancel:
- text, text elements, local image paths
- mention targets
- pending large-paste payloads
- cursor position
- Starts fetching persistent history entries on-demand (bounded, see below).
While search is open
- Query editing (affects search query only):
- Type plain characters → append to query
Backspace→ delete last characterCtrl+W→ delete previous “word” (whitespace-delimited)Ctrl+U→ clear query- Paste text → appended to query (newlines treated as spaces)
- Navigation:
Up/Ctrl+P→ move selection up (wrap)Down/Ctrl+N→ move selection down (wrap)Ctrl+R→ also moves selection up (older match)- Accept / cancel:
Enter→ accept selection and insert into composerEsc→ cancel and restore captured draft exactly
Preview
- The composer textarea previews the currently selected match while the popup is open.
Matching / ranking
- Fuzzy match:
codex_common::fuzzy_match::fuzzy_match(case-insensitive subsequence). - Scope:
- In-session submissions (full fidelity: text + elements + attachments).
- Cross-session persistent history (text-only).
- Ranking:
- Primary: fuzzy score (lower is better).
- Tie-break: recency (newer first).
Persistent history fetching (no protocol changes)
Uses existing request/response:
Op::GetHistoryEntryRequest { log_id, offset }GetHistoryEntryResponseEvent { log_id, offset, entry }
Bounded prefetch while searching:
HISTORY_SEARCH_MAX_PERSISTENT_SCAN = 500HISTORY_SEARCH_MAX_IN_FLIGHT = 8HISTORY_SEARCH_TARGET_MATCHES = 200
Edge cases / expectations
- Empty history → popup shows “no matches”.
- Multi-line history entry → display first line + ellipsis.
- Cancel restores draft including:
- attachments
- mention link targets
- pending large-paste placeholder payloads
- cursor position
Implementation notes
- Adds a new popup variant to the composer’s popup state machine:
ActivePopup::HistorySearch- Adds a dedicated popup UI component:
codex-rs/tui/src/bottom_pane/history_search_popup.rs- Reuses
ChatComposerHistorycaches + existing persistent history lookup ops. - Prevents other popups (slash/file/skill) from stealing focus while history-search is active.
- Updates the shortcut overlay to include
Ctrl+R. - Updates
docs/tui-chat-composer.mdwith the new behavior.
Tests / validation
- Unit tests in
codex-rs/tui/src/bottom_pane/chat_composer.rsfor: - opening search + previewing latest match
- filtering by query + accepting with Enter
- cancel restoring draft + pending pastes
- prefetch issuing expected
GetHistoryEntryRequestops when persistent history exists - Snapshot updates for footer shortcut overlay.
- Commands run:
just fmtcargo test -p codex-tui
Additional information
This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗