Skip to content

desktop: session scroll position is lost when switching sessions and back (v2 2.0.29, Windows) #55699

Open

Description

@renzhizhang2003

Summary

On OpenCode Desktop v2 (opencode v2.0.29, Windows), switching from a long session to another session and then back drops the timeline to the bottom of the conversation instead of restoring the scroll position left when the session was last active. The reading position is lost on every switch.

Follow-up to #55114 (closed as not planned for Desktop 1.18.x, with the instruction to open a new issue with a v2 version if it still reproduces).

Environment

  • opencode version: v2.0.29 (opencode --version)
  • OS: Windows 11 (Microsoft Windows NT 10.0.26200.0, x64)
  • Terminal: Unavailable: desktop app UI session (terminal environment variables are not set)
  • Shell: C:\WINDOWS\system32\cmd.exe
  • Install/channel: OpenCode Desktop, release build (v2)
  • Active plugins: oh-my-openagent@latest

Reproduction

  1. Open a session with a long conversation (long enough that the timeline scrolls).
  2. Scroll up so the viewport rests in the middle of the conversation, away from the bottom.
  3. Switch to a different session.
  4. Switch back to the original session.
  5. Observe: the timeline is at the bottom of the conversation instead of the position left in step 2.

Expected Behavior

The timeline should return to the scroll position left when the session was last active, and should only follow to the bottom when the user left it at the bottom (or new content is being appended).

Actual Behavior

The timeline jumps to the bottom on every switch back. No error is shown; the previously read position must be found again by scrolling manually. Occurs consistently and does not require new messages to arrive in the session.

Additional Context

Activity

  1. opencode-agent commented on Oct 15, 2026

    @opencode-agent
    Contributor

    Thanks for the detailed report and for linking back to #55114.

    I couldn't reproduce this here because it happens in the Desktop app's session timeline, and this sandbox can't run the desktop app or a browser. A maintainer with the Desktop app will need to confirm it.

    The current code matches what you describe. The timeline's "follow the bottom" state starts out pinned, and it treats a session it wasn't last tracking as pinned too. I didn't find anything that saves or restores each session's scroll position, so switching back probably lands at the bottom. I haven't seen it happen myself, though.

    Related issues, most closely related first:

  2. khalidshimul commented on Oct 20, 2026

    @khalidshimul

    Still reproduces on OpenCode Desktop v2 2.0.32 (Windows), so this is not fixed as of the current release. Adding my confirmation as the v2 report requested in #55114.

    Environment

    • opencode version: 2.0.32 (Desktop release build)
    • OS: Windows 11, Microsoft Windows NT 10.0.26200.0, x64
    • Terminal: Unavailable: desktop app UI session (no terminal environment attached)
    • Shell: C:\WINDOWS\system32\cmd.exe
    • Install/channel: OpenCode Desktop, release build (%LOCALAPPDATA%\Programs\@opencodedesktop, installed 2026-10-19)
    • Active plugins: none configured

    Reproduction

    1. Open a session with a long transcript that requires scrolling.
    2. Scroll up and leave the viewport mid-conversation, away from the bottom.
    3. Switch to a different session tab.
    4. Switch back to the original session tab.

    Expected Behavior

    The timeline returns to the scroll position it was left at, and only follows to the bottom when it was already at the bottom.

    Actual Behavior

    The timeline jumps to the bottom on every switch back. 100% reproducible, no new messages need to arrive, and no error is shown.

    Additional Context

  3. Echo3clipse commented on Oct 28, 2026

    @Echo3clipse

    The issue still occurs on OpenCode Desktop 2.2.0.

    I would like to add: This doesn't only pertain to the output timeline scroll position, which always jumps to the bottom, but it also pertains to the input text field scroll position.

    So if I add a lot of text in the input field (which is tiny as it is) and switch sessions and back, the input text field scroll position always jumps to the top again.

    So both scroll positions should be remembered in a session on desktop: output and input. Right now it's a UX nightmare.

  4. magiccodelab commented on Nov 3, 2026

    @magiccodelab

    Confirming this on v2.2.5 (current master 1bf08ae) and adding the code paths, because the Desktop renderer uses the same packages/app session timeline as the web app — this is not specific to Electron or to the Desktop tab strip.

    Repro

    1. Open a long session and scroll up, away from the bottom.
    2. Switch to another session tab.
    3. Switch back.
    4. The timeline is at the bottom instead of the previous position.

    It does not depend on new messages arriving. A 356-message session makes it very visible.

    Expected

    Restore the reading position. Only follow the newest content if the session was at the bottom when it was left.

    Actual

    Every switch back re-pins to the bottom.

    Root cause

    • packages/app/src/session/timeline/interaction.ts:312-331: a sessionKey change calls pin(); a params.id change calls pin() + scrollToEnd(). Both fire on a normal tab switch.
    • interaction.ts:21,50: follow is a single { sessionKey, pinned } slot. pinned() returns true for any session other than the last tracked one, so an "unpinned" state is not remembered per session.
    • packages/app/src/session/timeline/virtualizer.tsx:257-259: the comment states that route navigation detaches and reattaches the scroll element, which drops its offset.
    • virtualizer.tsx:288-296: on reattach, if pinned, it calls scrollToEnd(); initialOffset is MAX_SAFE_INTEGER when pinned, otherwise 0. There is no saved offset to restore.
    • packages/app/src/session/timeline/cache.ts and the virtualizer cache keep measurements and disclosure state, but not scroll position.
    • packages/app/src/session/screen.tsx:431 swaps cached timeline views through a <Show>, so the previous scroller is detached while another session is routed.

    Possible fix

    • Save a per-session logical anchor (top visible row/message key plus intra-row offset) when the timeline becomes inactive, and restore it before the first paint after reactivation. A raw scrollTop is fragile because virtualized row measurements change.
    • Store follow/pinned per session instead of one slot, or persist it in the existing layout.sessionView scroll map.
    • Remove the unconditional pin() / scrollToEnd() on session change. Pin on first open, or only when the session was left at the bottom.
    • If new content arrived while away, keep the anchor and use the existing "jump to latest" button instead of jumping silently.

    Related: #59493 (duplicate report). I can test a patch against this branch if that helps.

  5. yassine-safraoui commented on Nov 4, 2026

    @yassine-safraoui

    +1 this, it's super annoying when reviewing some response that take a lot of time to churn through

  6. sathwick-p commented on Nov 4, 2026

    @sathwick-p

    +1 Yes, can we please get this fixed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions