You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
One place to see what the Sessions tab still needs, in what order, and what is blocked on a decision rather than on work.
Why this exists. The ordering used to live in three committed documents, and they drifted within a day of a feature merging — one still described shipped work as upcoming, two disagreed about what was a blocker, and six open issues were missing from a hand-maintained list. So the split here is deliberate and follows how long a statement stays true:
Order, priority, "is this done" → this issue, because it can be edited without a pull request.
Why A must precede B, how a mechanism works, why an approach was rejected → docs/session-finding-plan.md, because it is reviewed and versioned with the code.
The detail for one item → that item's own issue, pointed at rather than restated.
Row readability: titles shortened from the middle (~60 chars, was a 35-char hard cut) with full title on hover, search window moved to the match, match #N chip recoloured to tie it to the highlight
Live view + saved session lists: ● live scope (ps joined against the registrations; ⚠ unregistered, ⚠ 2nd process), stats toggle, save list… / 🗂 with rename & delete, the transcript recap on a member row, session-id prefix search, a scope survives resuming from it. Shared atomic-json-store.ts. 138 tests. Merged 2026-09-05
Query operators, PR references in any spelling, persisted enrichment cache, ▶ open N: title:branch:msg:project:account:recap:has: `is:live
pinnedafter:before:; #N/pr:N/owner/repo#N/ URL with three strictness levels; assistant replies mined for PR references (in-process, incremental by byte offset);~/.config/codev/enrichment-cache.json` + one background pass; open the not-running members of a saved list. Closed #140#134#145. 5 review rounds, 32 threads. Merged 2026-09-06
A result explains itself and can be walked, tty-first switch, memory chip, resizable window: up to 20 hits per session with ‹ k/N ›, ▸ context (the prompt before/after), by match chip, match path / match assistant / match recap / match reply lines; iTerm2 / Terminal.app switch by tty when the pid is registered, title when it was guessed (terminal-switch.ts, isGuessedPid), ·ttysNNN tag on same-titled live rows; swap / pressure chip; normal-mode window resizable with remembered bounds, width-aware line caps, ⤢ reset, menu-bar mode re-asserted; tooltips drawn by the app; stale working shown idle after 10 min. Design doc opens with three mermaid flow diagrams (list + detection, open, switch). Closed #110#141#146#148; #142 C0 done. 4 review rounds, 34 threads. Merged 2026-09-06
The match … markers are outlined, not filled: at up to four per row they competed with the highlighted text they point at and could not be told apart from it, since both were the same solid amber. Now amber-outlined pills, the shape the PR / account / terminal badges already use; display stays inline so no row is taller (measured: inline 0px, inline-block 2–8px). Merged 2026-09-08
v1.0.90
Measured on the reference machine 2026-08-20 — these numbers are why the above was built, and they do not need recomputing:
Titles were the biggest problem. 125 unique titles, median 44 characters, 64% longer than the old 35-char cut, and 38% written as A -> B > C chains where the newest progress is at the tail. 48 of 125 (38%) collided on their first 35 characters; the largest group was 8 sessions all rendering as the same 35-character prefix.
39% of first prompts exceed 50 characters; 42% of last prompts exceed 40.
PR references: of 2,506 (session, PR number) pairs, only 19.4% appear in both forms. URL-only 38.3%, #N-only 42.3% — so 80.6% are findable by one spelling only.
sessions: the swap tooltip reads as Claude Code's swap; it is the whole machine's #156 — the swap tooltip reads as Claude Code's swap when both of its figures are machine-wide. Measured 2026-09-08 on the reference machine: 27 claude processes held 4.24 GB of the 16.46 GB in use, about a quarter, against an intuition of nearly all of it. Reword the tooltip; do not put the per-process figure on the chip, since one vmmap --summary costs 1.8s and there are 27 of them
sessions: group the list by project (by project chip) #153 — group the list by project (by project chip, off by default, inside any scope) — ★★☆. Measured 2026-09-06: 62–78% of adjacent rows in the recency list change project, and nothing gives the per-project overview. First cut is one level by folder name; the ~/git bucket (Open question 15) decides whether that is enough. Supersedes the two cheaper affordances (Projects-tab action, clickable project name), which are not wanted.
search: the miner stores owner/repo#N with a junk owner when a tool-input newline precedes it #155 — the miner stores owner/repo#N under a junk owner (nacme/…, an n glued on the front of the owner) when a tool-input newline precedes it: JSON.stringify turns the newline into a literal \n, and PR_REF_RE's second branch is the one with no left boundary. Measured on the live cache: 139 of 6378 stored references, 32 of 134 sessions, 5 of them unfindable by their correct qualified form. One-line regex fix plus a cache-version bump to 3
No — keep session last-activity as the default, add a toggle. Changing the default makes "find what I was just working on" harder, and that is the more common case.
2
#141: extra line naming the field, or tint the matched field in place?
Reuse the existing match #N rule — add a line only when the hit is not already visible on the row. Vertical space is the scarce resource in a menu-bar popup.
3
Design stable task identity first, or fix group C's symptoms one at a time?
Neither exclusively. C0 touches none of that abstraction and proceeds now; C1–C3 wait. No candidate designs have been drafted anywhere yet — #142 and §4.7 state the problem, not a design. Drafting them is separate work and does not block C0.
4
Switch to /fork instead of the three-step rename?
No. The upstream complaint about forking is that nothing comes back — no merge-back, no branch diff, no tree view. See the /fork version table in #142; note the semantics changed twice and any note about it must carry a version.
5
Should a snapshot capture pin / hidden state?
Optional, and explicitly point-in-time. A snapshot shows what was pinned then; unpinning later does not rewrite the snapshot. That is the correct semantics for a snapshot, and it is why it must be stored beside the list rather than merged into it.
6
#134: persist the mtime cache, or let a full-text index subsume it?
Persist the cache — this reversed on 2026-09-05 once full-text indexing was deferred (Open question 8). What group A now extracts is structured rows (sessionId, prNumber, url, timestamp), which need a small indexed table, not FTS. Widen the persisted file to carry those rows. FTS returns to the table only if question 8 is answered yes.
7
Start recording review-round calibration data?
Being handled in a separate session — deliberately not tracked here, to avoid two places recording the same thing.
Open questions — still undecided
#
Question
Notes
8
Should assistant prose be full-text searchable, or only mined for PR references?
Group A needs only the second (see #140). The first means a searchable copy of the corpus and is a much larger commitment; deferred for now, which is what flipped decision 6 back to persisting the cache. Answering this yes later re-opens 6. #159 measured the nearest cheap alternative and rejected it: indexing GitHub review/comment anchors costs +0.8 ms per full pass (+3.4%), so cost is not the objection, but an anchor names a position inside a GitHub page rather than a session, and it would not generalise to this question.
9
Is a live-session resource view worth building as its own thing?
Resolved by PR #147: it is the LIVE half of the saved-lists screen, and a prerequisite for capturing what is open correctly.
10
Row numbering (1.2. … per row) as a scanning / jump aid?
Evaluated 2026-09-05, not now: recency order changes on every refresh so a number is a coordinate, not an anchor; ⌘1/2/3 already switch tabs; the row is dense. The real value is jump to the Nth result, which belongs with #146. Cheap alternative if keyboard reach is the ask: Home/End beside the existing PageUp/PageDown.
11
Resizable window in normal app mode
Filed as #148; shipped in #152, both steps (resizable + remembered bounds, width-aware line caps, ⤢ reset).
12
In the live scope, are per-row process figures noise when the scope is used as a plain "running only" browse?
Yes — decided 2026-09-05, in PR #147: per-row figures sit behind a stats toggle, off by default and remembered; the total beside the search box stays; tty is never on the row. A noise-free is:live term in #140 remains the browse-only form.
13
Should the main list show a running session that has no history.jsonl line yet (a /branch child before its first prompt)?
No for now (2026-09-05). It never did; the live scope now synthesizes a row for it, which is the workaround. The honest fix is the generation chain (#142 C2/C3); a blank interim row would be replaced by it. Repro and trade-off table in #149.
16
Should pr: gain an issue: alias? (#157) Issue references have been searchable in every spelling since #151 — GitHub numbers issues and PRs together, and (?:pull|issues) is in all four code paths — but the README, the section heading and the in-app ? sheet all say pull request, so the author himself did not know. Documenting it is certain; a second operator name for identical behaviour is the open part.
Undecided (2026-09-15). has:pr stays PR-only either way: it is about the transcript's PR badge, which has no issue equivalent.
15
Grouping key for container folders (#153): ~/git is the largest "project" in the recent list (12 of 30) — cross-repo work, tests and quick one-offs started from the parent folder, plus ~/git's own sessions. One level by folder name, or sub-group by the session's repo context (sessionRepos from #151)?
Undecided (2026-09-06). Also open: whether #153 and #142 C1/C3 (chain folding) share one "group" mechanism with two keys.
14
"Open all" for a saved list? Left out of #147 as too costly to do blindly.
Now wanted (2026-09-05, after merge) for three real moments: after a reboot / macOS update, after closing every session to reclaim memory, and when switching terminal app. Constraints: open only members that are NOT running (idempotent), show the count and a projected memory figure on the button, stagger the launches, use the current terminal setting. Remaining scope of #145.
The transcript is copied; history.jsonl is not. That one asymmetry produces all four symptoms — deep search finds the ancestor, messageCount under-reports, pins stay behind, and ordering lifts abandoned parents above the work.
Reading PR references with grep is not the expensive part. On the largest transcript in the corpus (62MB) a grep -oE sweep took 0.052s and returned 550 references after dedup. Enrichment currently reads each file three times; merging those into one alternation plus one PR sweep is two passes, i.e. cheaper than today. A hook would only cover sessions recorded from now on, and the use case is retrospective — so a hook's coverage of the actual need is zero.
Terminal choice is not where the memory goes. Measured 2026-09-05: iTerm2 itself was 368MB in one process, while 36 claude processes held 4.66GB (32 of them with a live TTY, 4.52GB), against 20.4GB of 21.5GB swap in use. Switching terminal emulator saves the 368MB, not the 4.5GB — so a session-management feature is worth building for what it does for the user, not as a memory fix.
The corpus is 88 session transcripts / 687MB (2026-09-05). A find across ~/.claude/projects returns 223 files / 775MB, but the extra 135 are nested subagent transcripts and do not belong in a session index — an easy over-count. A full background scan is a one-off few seconds; the steady state afterwards is one stat per file.
Claude Code writes a one-line "where we are, what's next" recap into the transcript: {"type":"system","subtype":"away_summary","content":"…"}. 74 of 88 sessions (84.1%) carry one; the last one runs a median of 251 characters. It is better recall material than the last assistant turn — which is often a table fragment — and costs one more pattern in the grep that already looks for custom-title / ai-title / pr-link. Used by sessions: save and restore named session-list snapshots #145.
Both search paths must share the parser — main-side full-prompt search and the renderer's filterSessionsLocally. One rule with two implementations is how this repo has produced bugs repeatedly; the read-authority saga in PR feat(sessions): pin browse modes — recency order, ungroup, pinned-only #137 took four rounds for exactly this reason.
🤖 On behalf of @grimmerk — generated with Claude Code
One place to see what the Sessions tab still needs, in what order, and what is blocked on a decision rather than on work.
Why this exists. The ordering used to live in three committed documents, and they drifted within a day of a feature merging — one still described shipped work as upcoming, two disagreed about what was a blocker, and six open issues were missing from a hand-maintained list. So the split here is deliberate and follows how long a statement stays true:
docs/session-finding-plan.md, because it is reviewed and versioned with the code.Shipped (do not redo)
match #Nsnippets, amber highlight, minor-session foldsession-marks.jsonstoreonlychip scoping both list and searchmatch #Nchip recoloured to tie it to the highlight● livescope (ps joined against the registrations;⚠ unregistered,⚠ 2nd process),statstoggle,save list…/🗂with rename & delete, the transcript recap on a member row, session-id prefix search, a scope survives resuming from it. Sharedatomic-json-store.ts. 138 tests. Merged 2026-09-05▶ open N:title:branch:msg:project:account:recap:has:`is:liveafter:before:;#N/pr:N/owner/repo#N/ URL with three strictness levels; assistant replies mined for PR references (in-process, incremental by byte offset);~/.config/codev/enrichment-cache.json` + one background pass; open the not-running members of a saved list. Closed #140 #134 #145. 5 review rounds, 32 threads. Merged 2026-09-06‹ k/N ›,▸ context(the prompt before/after),by matchchip,match path/match assistant/match recap/match replylines; iTerm2 / Terminal.app switch by tty when the pid is registered, title when it was guessed (terminal-switch.ts,isGuessedPid),·ttysNNNtag on same-titled live rows; swap / pressure chip; normal-mode window resizable with remembered bounds, width-aware line caps,⤢reset, menu-bar mode re-asserted; tooltips drawn by the app; staleworkingshown idle after 10 min. Design doc opens with three mermaid flow diagrams (list + detection, open, switch). Closed #110 #141 #146 #148; #142 C0 done. 4 review rounds, 34 threads. Merged 2026-09-06match …markers are outlined, not filled: at up to four per row they competed with the highlighted text they point at and could not be told apart from it, since both were the same solid amber. Now amber-outlined pills, the shape the PR / account / terminal badges already use;displaystays inline so no row is taller (measured: inline 0px, inline-block 2–8px). Merged 2026-09-08Measured on the reference machine 2026-08-20 — these numbers are why the above was built, and they do not need recomputing:
A -> B > Cchains where the newest progress is at the tail. 48 of 125 (38%) collided on their first 35 characters; the largest group was 8 sessions all rendering as the same 35-character prefix.#N-only 42.3% — so 80.6% are findable by one spelling only.history.jsonl— no click instrumentation needed.Groups, in suggested order
A. Aim the query, resolve PR references, persist the index — ★★★
The five items below are one change economically: one parser, one grep pass, one index. Split apart, the same file gets rewritten three times.
title:branch:msg:project:account:recap:has:is:live|pinnedafter:before:pr:), with a?cheat-sheet chip#123⇄https://github.com/o/r/pull/123⇄o/r#123(tracked in sessions: field-scoped search terms (title:, branch:, msg:, has:pr) — you cannot aim the query at one field #140;docs/session-finding-plan.md§4.6 has the shipped shape and measurements)title:is wanted early: titles get renamed often, so a bare query keeps matching body noise instead.B. Session-list snapshots — ★★★
▶ open N(only members not running, projected cost on the button, staggered launches) — Decision 14. sessions: save and restore named session-list snapshots #145 closed.C. Session identity — ★★☆
·ttysNNNtag on same-titled rows). Was: tell identically-named live sessions apart, and switch by TTY/pid instead of by window title. The most painful item today, and the one that needs no new abstraction: three live sessions shared a name during the experiment, and iTerm2's title-based switching sent all three rows to the same tab.messageCountsummed along the chain · C3 ancestors folded — all waiting on Open question 3claudeprocesses, 4.66GB resident, several up 7–17 days. Of 33 real sessions, 1 was alive with no registration in~/.claude/sessions/and 1 was registered with a dead process (pid 22290, left from the sessions: /branch creates generation chains — 23.9% of transcripts, and CodeV cannot tell them apart #142 experiment). So "save what is currently open" would omit one session and store one ghost. (An earlier note here said 5 were unregistered; four of those were infrastructure —daemon run,bg-pty-host,bg-spare, the app helper — not sessions.) Moved out of the parked group.D. Make a result legible and ordered — ★★☆
matchedAtpipeline with sessions: a search result does not say WHICH field matched #141.claudeprocesses held 4.24 GB of the 16.46 GB in use, about a quarter, against an intuition of nearly all of it. Reword the tooltip; do not put the per-process figure on the chip, since onevmmap --summarycosts 1.8s and there are 27 of themby projectchip) #153 — group the list by project (by projectchip, off by default, inside any scope) — ★★☆. Measured 2026-09-06: 62–78% of adjacent rows in the recency list change project, and nothing gives the per-project overview. First cut is one level by folder name; the~/gitbucket (Open question 15) decides whether that is enough. Supersedes the two cheaper affordances (Projects-tab action, clickable project name), which are not wanted.E. Preview / reader — ★★★ but expensive
F. Perf and small bugs — ★☆☆
bug: session status stuck on 'working' at context limit prompt #110 status stuck on(shipped in feat(sessions): explain and walk a hit, tty-first switch, memory chip, resizable window #152)workingat the context-limit promptowner/repo#Nunder a junk owner (nacme/…, annglued on the front of the owner) when a tool-input newline precedes it:JSON.stringifyturns the newline into a literal\n, andPR_REF_RE's second branch is the one with no left boundary. Measured on the live cache: 139 of 6378 stored references, 32 of 134 sessions, 5 of them unfindable by their correct qualified form. One-line regex fix plus a cache-version bump to 3G. Parked — candidates for closing
#90 · #93 · #107 · #108 · #111 · #118 · #121 · #127 · #128
Decisions taken (2026-09-05)
match #Nrule — add a line only when the hit is not already visible on the row. Vertical space is the scarce resource in a menu-bar popup./forkinstead of the three-step rename?/forkversion table in #142; note the semantics changed twice and any note about it must carry a version.(sessionId, prNumber, url, timestamp), which need a small indexed table, not FTS. Widen the persisted file to carry those rows. FTS returns to the table only if question 8 is answered yes.Open questions — still undecided
1.2.… per row) as a scanning / jump aid?⌘1/2/3already switch tabs; the row is dense. The real value is jump to the Nth result, which belongs with #146. Cheap alternative if keyboard reach is the ask:Home/Endbeside the existingPageUp/PageDown.⤢reset).statstoggle, off by default and remembered; the total beside the search box stays; tty is never on the row. A noise-freeis:liveterm in #140 remains the browse-only form.history.jsonlline yet (a/branchchild before its first prompt)?pr:gain anissue:alias? (#157) Issue references have been searchable in every spelling since #151 — GitHub numbers issues and PRs together, and(?:pull|issues)is in all four code paths — but the README, the section heading and the in-app?sheet all say pull request, so the author himself did not know. Documenting it is certain; a second operator name for identical behaviour is the open part.has:prstays PR-only either way: it is about the transcript's PR badge, which has no issue equivalent.~/gitis the largest "project" in the recent list (12 of 30) — cross-repo work, tests and quick one-offs started from the parent folder, plus~/git's own sessions. One level by folder name, or sub-group by the session's repo context (sessionReposfrom #151)?Facts worth not re-deriving
/branchcopies the transcript to a new sessionId while the same process keeps writing — pid unchanged,sessions/<pid>.jsonupdated in place, the parent left intact and still resumable. 21 of 88 transcripts on disk carryforkedFrom— 23.9%. Full evidence in sessions: /branch creates generation chains — 23.9% of transcripts, and CodeV cannot tell them apart #142; written up asdocs/session-finding-plan.md§4.7 in PR docs: correct two assumptions a live experiment falsified #143.history.jsonlis not. That one asymmetry produces all four symptoms — deep search finds the ancestor,messageCountunder-reports, pins stay behind, and ordering lifts abandoned parents above the work.grepis not the expensive part. On the largest transcript in the corpus (62MB) agrep -oEsweep took 0.052s and returned 550 references after dedup. Enrichment currently reads each file three times; merging those into one alternation plus one PR sweep is two passes, i.e. cheaper than today. A hook would only cover sessions recorded from now on, and the use case is retrospective — so a hook's coverage of the actual need is zero.claudeprocesses held 4.66GB (32 of them with a live TTY, 4.52GB), against 20.4GB of 21.5GB swap in use. Switching terminal emulator saves the 368MB, not the 4.5GB — so a session-management feature is worth building for what it does for the user, not as a memory fix.findacross~/.claude/projectsreturns 223 files / 775MB, but the extra 135 are nested subagent transcripts and do not belong in a session index — an easy over-count. A full background scan is a one-off few seconds; the steady state afterwards is onestatper file.{"type":"system","subtype":"away_summary","content":"…"}. 74 of 88 sessions (84.1%) carry one; the last one runs a median of 251 characters. It is better recall material than the last assistant turn — which is often a table fragment — and costs one more pattern in the grep that already looks forcustom-title/ai-title/pr-link. Used by sessions: save and restore named session-list snapshots #145.filterSessionsLocally. One rule with two implementations is how this repo has produced bugs repeatedly; the read-authority saga in PR feat(sessions): pin browse modes — recency order, ungroup, pinned-only #137 took four rounds for exactly this reason.🤖 On behalf of @grimmerk — generated with Claude Code