TUI: scroll-synced sticky header showing the user prompt for the currently-visible transcript region
Summary
Add a scroll-synced sticky context header to the TUI transcript view: while the user scrolls up through history, pin a small header at the top of the viewport showing the user prompt that the currently-visible content belongs to. As the top of the viewport crosses from one turn into another, the header updates to that turn's user message.
This is the reading counterpart to the already-requested composer docking (#14045) and prompt-jump shortcut (#21732): not "keep the input box reachable" and not "jump between prompts", but "always tell me which prompt I'm currently looking at."
Problem
In a long session, when I scroll up to re-read earlier output, I lose track of which of my prompts produced the block I'm now looking at. The turn boundary is often far above the current viewport, so I have to scroll further up just to find the owning prompt, then scroll back down.
This is especially painful in the default view because history is written into the terminal's native scrollback — the app has no control over what's on screen, so scrolling can also surface blank gaps / duplicated frames (reflow + redraw artifacts), making it even harder to orient.
Requested behavior
- While viewing transcript history, render a 1–2 line sticky header at the top of the viewport containing the user message of the turn the top-most visible content belongs to (truncated with an ellipsis if long).
- As scrolling moves the top of the viewport into a different turn, the header swaps to that turn's user prompt.
- When at the bottom (latest), the header can hide or show the most recent prompt.
- Applies to the app-controlled transcript overlay (Ctrl+T) where this is straightforward; ideally the main scroll view too.
Why this is feasible here
Codex already has a structured, cell-based history model (each user message / assistant reply / exec is a cell). The transcript overlay is an app-owned, alt-screen pager that already knows its scroll offset and viewport. So the data needed — "which user turn does the top visible cell belong to" — already exists; this is purely a rendering-layer addition to the overlay (map top-visible line → owning cell → owning user message → draw as a pinned header row). No protocol or history-model change.
The default native-scrollback view can't do this (the terminal owns scrolling, the app can't draw over it) — which is exactly why scoping this to the transcript overlay is the practical target.
Prior art
Claude Code's terminal TUI does exactly this: scrolling its internal buffer keeps a sticky header at the top showing the prompt the current region belongs to. It works because that TUI fully owns its scroll viewport — the same condition Codex's transcript overlay already satisfies.
Related issues (distinct from this one)
- #14045 — sticky composer/input box on scroll (input reachability). Different surface.
- #26311 — pin composer input box to bottom of pane. Different surface.
- #21732 — shortcut to jump between user prompts in the transcript. Complementary (navigation vs. orientation).
- #4607 — sticky header for what the agent is working on (multi-tab disambiguation). Different content.
- #21945 — transcript overlay rebuild performance. Same surface, unrelated concern.
Success criteria
- Scrolling up in the transcript keeps a header visible showing the owning user prompt of the top-most visible content.
- The header updates as the viewport crosses turn boundaries.
- No cursor/composer drift or layout jank introduced.
2 Comments
I inspected the current
mainimplementation (at680934adc4) and would be happy to implement this if a maintainer agrees with the scope and invites an external PR.A focused implementation can stay entirely inside the existing transcript overlay:
TranscriptOverlayalready owns the ordered committed cells andPagerViewownsscroll_offset.desired_height(width), so the overlay can map the top visible row to a committed cell at the current width.UserHistoryCelland render a single truncated prompt row above the content viewport.I would cover:
instasnapshot for the visible sticky header.This intentionally does not change normal transcript fidelity or collapse tool output. If this approach aligns with the intended UX, could a maintainer invite a PR?
@fcoury, since you recently worked on transcript pagination and earlier-prompt navigation in these TUI modules, would you be open to advising on the scope above and, if it aligns with the intended UX, inviting an external PR?