Before submitting
Area
apps/web
Steps to reproduce
- Open a long thread (several hundred messages, many tool calls) and scroll to the bottom.
- Switch to another thread.
- Switch back.
It also happened right after relaunching the desktop app: the long thread I returned to opened in the middle.
Expected behavior
The transcript returns to where I left it: here, the bottom, on the latest reply.
Actual behavior
It opens at an unpredictable position: sometimes at the very top, sometimes in the middle, with the "Scroll to end" button shown. The result differs between attempts. To continue, I have to scroll all the way down.
Likely cause
From reading the code; the client does not log positions, so I have not confirmed which path fired in my case.
MessagesTimeline.tsx saves the thread's position, including atEnd, in handleScroll (lines 1021–1046). It runs on every LegendList onScroll, including scrolls caused by layout, and one frame after every change to rows (lines 1102–1105). Nothing checks that the user scrolled.
atEnd is true only within 40 px of the end (resolveTimelineIsAtEnd in MessagesTimeline.logic.ts). If the content is briefly more than 40 px past the viewport while I sit at the bottom, atEnd: false is saved. That can happen when a row is measured taller than its 90 px estimate, or when the composer footer grows: maintainScrollAtEnd deliberately does not re-pin for footer growth.
- On the next visit,
ChatView.tsx (lines 5724–5739) turns live follow off and shows "Scroll to end", and the timeline restores the saved row. If that row is not in the loaded window, it falls back to the saved pixel offset (MessagesTimeline.tsx:873), which lands at the top or in the middle. After a relaunch the thread first loads only the last 10 turns, and a replacement snapshot drops older pages (packages/client-runtime/src/state/threads.ts:453).
The "Scroll to end" button already ignores isAtEnd=false changes that the user did not cause while following (ChatView.tsx:5640–5648). The position save has no such check.
Suggested fix
Save atEnd: false only after user scroll input (the same signal that turns live follow off), or keep atEnd: true while live follow is on.
Impact
Minor bug or occasional failure
Version or commit
0.0.43-nightly.20260924.2200, again on 0.0.43-nightly.20260928.2375; code references are to main @ 94f92a7
Environment
Desktop app on Linux (NixOS, Wayland, niri); provider Claude (Opus 5.5)
Logs or stack traces
Screenshots, recordings, or supporting files
No response
Workaround
Scroll to the bottom by hand.
Before submitting
Area
apps/web
Steps to reproduce
It also happened right after relaunching the desktop app: the long thread I returned to opened in the middle.
Expected behavior
The transcript returns to where I left it: here, the bottom, on the latest reply.
Actual behavior
It opens at an unpredictable position: sometimes at the very top, sometimes in the middle, with the "Scroll to end" button shown. The result differs between attempts. To continue, I have to scroll all the way down.
Likely cause
From reading the code; the client does not log positions, so I have not confirmed which path fired in my case.
MessagesTimeline.tsxsaves the thread's position, includingatEnd, inhandleScroll(lines 1021–1046). It runs on every LegendListonScroll, including scrolls caused by layout, and one frame after every change torows(lines 1102–1105). Nothing checks that the user scrolled.atEndis true only within 40 px of the end (resolveTimelineIsAtEndinMessagesTimeline.logic.ts). If the content is briefly more than 40 px past the viewport while I sit at the bottom,atEnd: falseis saved. That can happen when a row is measured taller than its 90 px estimate, or when the composer footer grows:maintainScrollAtEnddeliberately does not re-pin for footer growth.ChatView.tsx(lines 5724–5739) turns live follow off and shows "Scroll to end", and the timeline restores the saved row. If that row is not in the loaded window, it falls back to the saved pixel offset (MessagesTimeline.tsx:873), which lands at the top or in the middle. After a relaunch the thread first loads only the last 10 turns, and a replacement snapshot drops older pages (packages/client-runtime/src/state/threads.ts:453).The "Scroll to end" button already ignores
isAtEnd=falsechanges that the user did not cause while following (ChatView.tsx:5640–5648). The position save has no such check.Suggested fix
Save
atEnd: falseonly after user scroll input (the same signal that turns live follow off), or keepatEnd: truewhile live follow is on.Impact
Minor bug or occasional failure
Version or commit
0.0.43-nightly.20260924.2200, again on 0.0.43-nightly.20260928.2375; code references are to main @ 94f92a7
Environment
Desktop app on Linux (NixOS, Wayland, niri); provider Claude (Opus 5.5)
Logs or stack traces
Screenshots, recordings, or supporting files
No response
Workaround
Scroll to the bottom by hand.