Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
# Changelog

## 1.0.89

- Feat: a search result explains itself and can be walked ([#141](https://github.com/grimmerk/codev/issues/141), [#146](https://github.com/grimmerk/codev/issues/146))
- **Every hit, not the first.** The `match #N` line gains `‹ 2/12 ›` when a session's prompts hit more than once, stepping the snippet through them; the main-side search now returns up to 20 hits per session, each with its prompt time
- **The prompts around a hit**, one click (`▸`) away on the match line: the prompt before (`↑`) and after (`↓`). The smallest useful version of the reader in #66 — user prompts only; assistant text is not in the index
- **`by match`** chip while searching: order results by when the match happened instead of the session's last activity, so the session where you typed the word an hour ago is not buried under one touched five minutes ago. Off by default — "what was I just working on" is the commoner question
- **`match path` / `match assistant` / `match recap` / `match reply`** lines say which field a row matched in when that field is not on the row (the path, the assistant's mined references, a recap the row is not showing, a reply hidden behind a recap). Fields that render — title, branch, project name, badge, first/last prompt — already carry the highlight, so they add no line: vertical space stays the scarce resource
- Feat: switch to a running session by its **terminal (tty)** first, title second ([#142](https://github.com/grimmerk/codev/issues/142) C0). Three `/branch` siblings deliberately share a title, and the title-first match sent every one of their rows to the same iTerm2 tab; a process has exactly one tty, so that is what the click matches now (iTerm2 and Terminal.app; Ghostty has no per-tab tty, [#63](https://github.com/grimmerk/codev/issues/63), and keeps title-then-cwd). Running rows that share a title show their tty (`·ttys003`) so they can be told apart on screen. **The order follows where the pid came from**: a pid read from Claude Code's own registration file is exact and goes tty-first; a pid the detection had to *guess* (a same-cwd match or a terminal-tab title, for a process whose registration names a session the history does not know yet) keeps the old title-first order, because a guessed tty can point at a sibling — the case that made title-first the safe choice in 2026-03. Both keys are tried when the session has a title, only the order changes; without one, tty is the only key (`src/terminal-switch.ts`, flow diagrams in `docs/claude-session-integration-design.md`)
- Feat: a **memory warning chip** beside `● live` when the machine is under pressure — swap past 8GB, or macOS's own pressure level at warn (amber) / critical (red) — with the figures in the live chip's tooltip otherwise. Read from `sysctl vm.swapusage` and `kern.memorystatus_vm_pressure_level` on the same refresh as the process table, so it costs nothing extra. Added the night 42 `claude` processes at 5.1GB pushed a 32GB machine to 18GB of swap: swap was the number that said so first
- Feat: **normal app mode's window can be resized** and reopens at its last position and size (a remembered window that would land on an unplugged display is ignored); the header is already a drag region, so the macOS title-bar double-click action applies to it. **Line caps follow the width**: the character caps on title, messages, branch, reply and recap were tuned for the 800px default and now scale up with the list's measured width (never down), so a wider window shows more of each line rather than more empty space; the Projects list grows with the window instead of stopping at 480px with a scrollbar mid-window; a `⤢` beside the shortcut label in the header (normal mode only) resets the window to its default size and position, since macOS zoom only restores the previous user size ([#148](https://github.com/grimmerk/codev/issues/148), both steps). Menu-bar mode is re-asserted at every show — default size, centred, not resizable — so a window resized in normal mode does not carry its size across a mode switch
- Fix: **tooltips now show.** Every hint in the switcher (chips, badges, controls, the per-process figures) is drawn by the app instead of relying on the native `title` tooltip, which Chromium paints only while the window is the key window — a frameless popup the pointer merely crosses usually is not, so the hints almost never appeared
- Fix: a session parked at Claude Code's context-limit prompt no longer shows as `working` forever — no hook fires there, so a `working` status untouched for 10 minutes is shown as idle ([#110](https://github.com/grimmerk/codev/issues/110))
- Docs: README on keeping the machine responsive — sessions grow with time, Spotlight should skip `~/Library/Application Support/Claude` and `~/.claude`, and what the swap chip means

## 1.0.88

- Feat: aim the search — field-scoped terms, PR references in any spelling, `is:live`, and a persisted enrichment cache ([#140](https://github.com/grimmerk/codev/issues/140), [#134](https://github.com/grimmerk/codev/issues/134))
Expand Down
16 changes: 13 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ Bare words search everything; **operators aim the query** (the `?` chip beside t

Every term must hold. An operator with an unreadable value (`after:soon`) is reported under the box and ignored rather than silently matching nothing.

A result also says **why and when**: the `match #N` line steps through a session's prompt hits, up to 20 of them (`‹ 2/12 ›`) and unfolds (`▸`) the prompt before and after the hit; a `by match` chip orders results by when the match happened rather than by the session's last activity; and when the matching field is not on the row — the project path, something the assistant said, a recap the row is not showing — a `match path` / `match assistant` / `match recap` / `match reply` line names it. Fields that are on the row (title, branch, project name, PR badge, first/last prompt) already carry the highlight and add no line.

#### Finding a pull request

A PR can be found from two kinds of evidence, both indexed:
Expand Down Expand Up @@ -84,7 +86,7 @@ Two chips beside the search box, on the [Session Buddy](https://sessionbuddy.com
| `save list…` | Appears whenever the list is scoped (`● live`, `only`, or a search): **saves exactly what is on screen as a named list**. The default name is today's `MMDD`, then `MMDD-2`, `MMDD-3` — a label, not an identity. |
| `🗂 N` | Shows the saved lists. Click one to view its members **in the order they were captured** and resume any of them; `✎` renames, `✕` (then `delete?`) deletes. |

A saved member stores what you recognise a session by — title, branch, pin state at capture, the last messages, and the **recap** line Claude Code writes into the transcript (the `※ recap:` "where we are, what's next" line), which replaces the last-reply line on the member's row; a recap much older than the session's last activity is marked `⏱`, since its "next step" may already be done. A member whose transcript is gone still reads as the session it was. Opening a session from a list or from the live scope **leaves you in that scope** when you come back (only the search box is cleared), so you can work through a set one session at a time. A list's header also carries **`▶ open N`** — resume the N members that are **not** running, for the moments that call for the whole set: after a reboot or a macOS update, after closing everything to reclaim memory, or to move the set to another terminal app (change the terminal in Settings, then press it). It asks once, showing the projected cost (`open 12 · ~1.7GB?`, from the mean size of the processes currently running), opens only what is not already running (so pressing it twice opens nothing new), launches one session every 0.7s rather than all at once, and reports members it skipped because their project folder or transcript is gone. Lists live in `~/.config/codev/session-lists.json`; a file that cannot be trusted as written is reported at load, never rewritten.
A saved member stores what you recognise a session by — title, branch, pin state at capture, the last messages, and the **recap** line Claude Code writes into the transcript (the `※ recap:` "where we are, what's next" line), which replaces the last-reply line on the member's row; a recap much older than the session's last activity is marked `⏱`, since its "next step" may already be done. A member whose transcript is gone still reads as the session it was. Opening a session from a list or from the live scope **leaves you in that scope** when you come back (only the search box is cleared), so you can work through a set one session at a time. A list's header also carries **`▶ open N`** — resume the N members that are **not** running, for the moments that call for the whole set: after a reboot or a macOS update, after closing everything to reclaim memory, or to move the set to another terminal app (change the terminal in Settings, then press it). It asks once, showing the projected cost (`open 12 · ~1.7GB?`, from the mean size of the processes currently running), opens only what is not already running (so pressing it twice opens nothing new), launches one session every 0.7s rather than all at once, and reports members it skipped because their project folder or transcript is gone. Lists live in `~/.config/codev/session-lists.json`; a file that cannot be trusted as written is reported at load, never rewritten. Titles, branches and recaps are re-read from the transcripts when the popup is opened (or the Sessions tab is entered), not while it stays open — a `/rename` in the terminal shows up on the next open.

**Simple rule**: when running multiple sessions in the same project directory at the same time, give each running session a name. Closed sessions don't need names — they won't cause issues.

Expand All @@ -99,12 +101,20 @@ For the full same-cwd accuracy matrix (detection + switch by launch method and t

| Terminal | Switch method | Launch method | Notes |
|----------|--------------|---------------|-------|
| iTerm2 | Title match → TTY fallback | AppleScript new tab/window | Most reliable; cross-reference fixes detection for bare `claude` + `/rename`'d sessions |
| Terminal.app | Title match → TTY fallback | AppleScript `do script` | Built-in macOS terminal; same TTY accuracy as iTerm2 |
| iTerm2 | TTY match → title fallback when the pid is registered (exact); title match → TTY fallback when it was guessed | AppleScript new tab/window | Most reliable; cross-reference fixes detection for bare `claude` + `/rename`'d sessions |
| Terminal.app | Same order rule as iTerm2 | AppleScript `do script` | Built-in macOS terminal; same TTY accuracy as iTerm2 |
| Ghostty | Title match → cwd fallback | AppleScript new tab/window | Needs `/rename` for same-cwd. **Note:** Ghostty may not support `⌘+V` (paste) and `⌘+Z` (undo) in CodeV's search bar by default — add `keybind = super+v=paste_from_clipboard` and `keybind = super+z=undo` to `~/.config/ghostty/config` ([ghostty#10749](https://github.com/ghostty-org/ghostty/issues/10749#issuecomment-4131892831)) |
| cmux | Title match → TTY fallback | CLI new-workspace | Same as iTerm2 (requires cmux v0.63+); requires socket access in cmux Settings (`automation` or `allowAll`) |
| VS Code | URI handler (session-level) | `open -b` + URI handler | Requires Claude Code VS Code extension v2.1.72+; `[VSCODE]` badge on active sessions; adaptive resume via IDE lock file polling (~0.5s if project already open) |

#### Keeping the machine responsive

Three things learned from a night of cursor stutter on a 32GB machine running ~40 Claude Code sessions:

- **Sessions grow while they sit.** A Claude Code process gains memory over time even when idle (upstream: [anthropics/claude-code#37240](https://github.com/anthropics/claude-code/issues/37240) measures ~500MB per hour of use, [#18859](https://github.com/anthropics/claude-code/issues/18859) idle sessions reaching ~15GB each). 42 processes held 5.1GB resident and had pushed the machine to 18GB of swap. Close sessions when a task is done, or `save list…` the set, close it all, and `▶ open N` later. When swap passes 8GB or macOS reports memory pressure, a `swap …` chip appears beside `● live` (amber at warn, red at critical); the figures are always in the live chip's tooltip. macOS only empties swap on a restart.
- **Exclude two folders from Spotlight** (System Settings → Spotlight → Search Privacy; press `⌘⇧.` in the file picker to show hidden folders, or `⌘⇧G` and type the path): `~/Library/Application Support/Claude` — Claude Desktop writes gigabytes of IndexedDB churn there and Spotlight re-indexes it ([anthropics/claude-code#43390](https://github.com/anthropics/claude-code/issues/43390), 12GB on the reference machine) — and `~/.claude`, where every running session appends to its transcript. Both showed up as `mds_stores` at 50–100% of a core.
- **A compositor that has run for weeks is a suspect of its own.** With every app closed the stutter remained until a restart; `WindowServer` was at 1.2GB and 30–80% CPU after 37 days of uptime. If nothing in Activity Monitor explains a stutter, restart before debugging further.

### Multi-Account Support (Claude Code)

Run multiple Claude Code accounts (e.g. personal + work) on one machine. Each account gets its own config dir (via `CLAUDE_CONFIG_DIR`); the default account stays at `~/.claude` untouched. The Sessions tab aggregates sessions from every account (non-default ones get a purple account badge), and each session always resumes under the account it belongs to.
Expand Down
Loading
Loading