`claude agents`: list selection snaps back to the just-exited session ~3 s after returning with `←`, discarding arrow-key navigation (regression in 2.1.257)

Status Open
Reported on v2.1.257
Maintainer reply None cached
Activity 0 comments · opened Sep 3, 2026

TL;DR

After returning from a session to the claude agents list with , the first list refresh (about 3 s later) moves the highlight back to the row of the session you just left, discarding any Up/Down navigation made in that window. Navigation after that point sticks. Started with 2.1.257; unchanged in 2.1.258 and 2.1.259.

Problem

Coming back from a session and immediately arrowing to another row is the normal way to hop between background sessions. Since 2.1.257 the list silently undoes that: a few seconds after it reappears, the selection snaps back to the exited session. It is easy to then press Enter and re-open the wrong session. There is no visual cue that the keypresses were discarded other than the highlight moving.

Observations that narrow it:

  • Direction does not matter. Press Up and the highlight snaps back down; press Down and it snaps back up. The selection is being replaced with the exited session's identity, not shifted by a reorder.
  • Reproduces whether the exited session is still working or already Done, so it is not driven by the exited session's own completion/state write.
  • Restarting the claude agents host process (reattaching to the already-running 2.1.259 daemon) does not change it.
  • The snap-back coincides with a visible full-list repaint: the exited row's status glyph and age column ("14m" → "15m") repaint in the same frame the highlight jumps, and the header's cwd line briefly flips to a different project directory.

Repro

Environment: Claude Code 2.1.259 (claude agents host, daemon and workers all 2.1.259), WSL2 Ubuntu on Windows 11, Windows Terminal, inside tmux. Nothing in the behaviour looks terminal-specific.

  1. claude agents with several background sessions in the list (here: 5+ pinned rows).
  2. Open a session that is not in the first row (here: row 5). It can be mid-turn or Done.
  3. Press to return to the list.
  4. Within ~3 s of the list reappearing, press Up four times (or Down, if the row is not last).

Expected: the highlight stays on the row you navigated to.

Actual: roughly 3 s after the list appeared, the highlight snaps back to the row of the session you just exited. Pressing Up/Down again after that works normally.

Timed from a 15 s screen recording (frames extracted at 8 fps; highlight-row located per frame by sampling row background luminance). t is seconds from recording start:

t= 2.38  list appears after `←`; highlight on row 5 (the session just exited);
         footer reads "enter to return"
t= 4.00  Up -> row 4      footer flips to "enter to open"
t= 4.88  Up -> row 3
t= 5.12  Up -> row 2
t= 5.38  Up -> row 1
~5       header cwd line flips to a different project's directory
t= 5.62  highlight bar leaves row 1; footer back to "enter to return";
         row 5's status glyph + age column repaint in the same frame
         => selection is on row 5 again (the exited session)
t=12.5   Up again -> row 1, and it holds for the rest of the recording

Repro status: executed (operator-driven, recorded, timed as above).

Onset

Local install times of the versions involved:

| version | installed (local) | symptom |
|---|---|---|
| 2.1.251 and earlier | — | never seen |
| 2.1.257 | 2026-09-01 12:53 | first observed the same day |
| 2.1.258 | 2026-09-01 17:37 | present |
| 2.1.259 | 2026-09-02 17:34 | present |

2.1.257's changelog carries several claude agents return-path and render changes that fit the shape:

Source is not public, so these are pointers to the release that introduced it rather than to the code.

Suggested fix

Treat "select the row you came from" as a one-shot initial value applied when the list mounts after , not as state re-applied on the first subsequent refresh. If the return path stores the exited session id and a later effect (roster update, spare-pool respawn, attach-journal write) re-applies it, guard that effect with "the user has not navigated since mount". More generally: preserve the selected job id across refreshes and fall back to the exited row only when that id is no longer in the list. That also covers the reorder case 2.1.257 fixed.

Debouncing the refresh only shortens the window; suppressing refresh after return would lose the 2.1.257 reorder fix.

Not in scope

The header cwd line flipping to an unrelated directory on the same repaint was observed but not diagnosed; mentioned only as a marker of the refresh. Nothing about daemon lifecycle is being claimed.

View original on GitHub ↗