--resume picker labels sessions with real prompts as "(session)" — title lookup only reads 64KB head/tail
Summary
The --resume picker labels sessions (session) — the fallback meant for
empty sessions — even when the transcript contains plenty of real prompts. The
label only reflects whether a title-bearing line happened to land inside the
64 KB the picker reads, not whether the session has content.
Same root cause likely explains #75602 (custom titles on disk but not shown,
"visible earlier, then disappeared without the underlying data changing").
Environment
- Version: 2.1.211
- Platform: linux, xterm-256color
Mechanism
The picker's lite loader (XId) derives the row label from a windowed read.Npl reads zL = 65536 bytes from offset 0 (head) and 64 KB from size - zL
(tail). The middle of the transcript is never read. All three label sources come
only from those two windows:
let{head:n,tail:o}=await Npl(e,t,r);
let m = LT(o,"lastPrompt") || aBy(n) || yId(n,"content",200) || yId(n,"text",200) || "";
let g = LT(o,"customTitle") ?? LT(n,"customTitle");
let y = LT(o,"aiTitle") ?? LT(n,"aiTitle");
if(!s.firstPrompt && !s.customTitle && !s.aiTitle) s.firstPrompt="(session)";
A session is labeled (session) when it has no customTitle, no in-windowaiTitle, and more than 64 KB of trailing content after its lastlast-prompt line (large tool results, file-history-delta runs). The
session is not empty — the picker just never read far enough to find its title.
Repro
A transcript where:
- the first 64 KB has no
"type":"user"line and no"content":"/"text":"
(e.g. mode, permission-mode, a large file-history-snapshot),
- real
user+last-promptlines sit in the middle, - the last 64 KB has no
lastPrompt/aiTitle/customTitle
(e.g. a long file-history-delta run).
Then claude --resume in that project.
A/B on one 141 KB file containing 4 genuine user prompts:
| file | picker row |
|---|---|
| as above | (session) |
| + one last-prompt line appended into the tail (~200 bytes, prompts untouched) | renders that prompt |
Only in-window-ness changed. The prompts never moved.
Expected vs actual
- Expected: the row shows the session's prompt (or its title).
- Actual:
(session), indistinguishable from a genuinely empty session.
Why it's worth fixing
Cosmetic — sessionId is untouched and the row resumes correctly — but real
sessions look empty and unidentifiable, and it misleads anyone debugging it: it
presents as transcript corruption or a broken SessionEnd hook. It cost me a
couple of sessions chasing lifecycle theories before I read XId.
The margin is thinner than it looks. Across my transcripts the last
title-bearing line normally sits 113–1462 bytes from EOF (these lines are
rewritten often), but I have one at EOF-34483 — over half the tail window
consumed. A single large trailing tool result pushes it out.
Possible fix
When both windows come up empty, fall back to a bounded scan for a
title-bearing line before declaring the session untitled — rather than
labeling a session with content as (session).
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗