Description
Problem
Switching between pinned sessions with Ctrl-1/2/3 has a noticeable pause, especially once the sessions have long transcripts. That undermines the quick-switch flow: the shortcut changes the route immediately, but the destination is not immediately usable.
This is a performance follow-up to #36193, not another session-navigation proposal.
What the V2 TUI does today
Checked against origin/v2 at 27e7b0558a:
session.quick_switch.Nresolves the pinned slot and immediately navigates to the destination session (packages/tui/src/context/local.tsx).- On every session ID change,
createSessionRowssynchronously reduces the destination's cached transcript into render rows, then reconciles those rows (packages/tui/src/routes/session/rows.ts). - Session hydration requests the newest 200 messages in one page and keeps them in the shared data store (
packages/tui/src/context/data.tsx). A message can expand into many rendered rows because assistant content/tool parts are embedded in it. - The session view mounts a
SessionRowViewfor every reduced row in the loaded transcript (packages/tui/src/routes/session/index.tsx). There is no viewport window or incremental transcript mounting on the switch path. - The message API itself already supports bounded, cursor-based pagination (
packages/server/src/handlers/message.tsandpackages/core/src/session.ts), so the missing piece is mainly TUI-side loading/rendering policy rather than a new storage primitive.
This explains why repeatedly switching among already-known sessions can still lag: route lookup is cheap, but transcript reduction/reconciliation/layout work scales with the loaded transcript and its parts.
Desired behavior
Quick-switch latency should be effectively independent of total session length. Switching to an already-open/pinned session should paint the destination chrome and newest visible transcript promptly, while older history loads or mounts only when needed.
Scope
- Measure the switch path separately: route navigation, transcript fetch/cache lookup, row reduction/reconciliation, and terminal layout/render.
- Bound work performed before the first destination frame (for example, a recent/visible window rather than all 200 loaded messages and all nested parts).
- Use the existing cursor pagination to load older history when the user scrolls upward, or otherwise virtualize/window mounted transcript rows.
- Preserve live updates, sticky-bottom behavior, message navigation, revert boundaries, and full transcript export.
- Add a representative long-session performance regression check or timing fixture so this does not drift back.
Acceptance criteria
- Back-to-back
Ctrl-1/2/3switches among long pinned sessions no longer have transcript-length-dependent pauses. - The destination's header/composer and newest visible messages appear before older history is fetched or mounted.
- Scrolling upward can still reach the complete transcript without losing ordering or live event updates.
- The issue includes before/after timings from a repeatable long-session fixture.
Source discussion: https://slack.com/archives/C0BFMFJ5FJS/p1785255726318509
Activity
bhuvan0808 commentedon Aug 5, 2026
I'd like to work on this, happy to submit a PR. Let me know if there's a preferred approach @thdxr or any other maintainer.
Dante-dan commentedon Sep 29, 2026
I traced the switch pause to the TUI retaining every older message page loaded while scrolling a session. Re-entering that session reduces the whole cached transcript again, so the work grows with history length.
I’m working on a bounded cache release for oversized sessions: release the message cache when its view unmounts, clear its pagination cursor so re-entry starts at the newest page, and ignore an older page that resolves after release. Small session caches should stay intact. I’m adapting the approach from the closed, unmerged #45940 and will cover the release threshold and pagination race in tests.
neriousy commentedon Nov 13, 2026
Closing as completed. #39568 makes session switching mount the newest 40 rows first and add older ones in chunks. #44656 paginates history, so a session first loads only its latest 20 messages and fetches older pages on scroll. In the PR's measurements, a switch to a 243-row session went from about 167ms to about 43ms. If switching is still slow on a current build, please open a new issue with timings.