English · 简体中文
Local web viewer for AI coding CLI sessions on this machine. Browse recent sessions from Claude Code, Codex, Devin, and Grok in one place, search across tools, inspect token/tool usage when metadata exists, and resume any session in a new Terminal window with a single click.
CLI resume lists (claude --resume, codex resume, grok --resume, …) show
ids and timestamps — not what was said. This viewer shows the opening prompt
and last reply of every session so you can spot the one you want and pick up
where you left off.
macOS only. Uses launchd for autostart and AppleScript /
open -nato launch Ghostty, iTerm, or Terminal.app. Auto-detects whichever is installed, in that order.
./install.sh # install as launchd agent (run at login, keep alive)
open http://localhost:7333Or run in the foreground: python3 server.py.
Frontend (optional rebuild after UI changes):
cd frontend && npm install && npm run buildserver.py serves frontend/dist/ when present, otherwise
sessions-index.html.
| Source | Default path | Resume | Usage notes |
|---|---|---|---|
| Claude Code | ~/.claude/projects/*/*.jsonl |
claude --resume <id> |
Lifetime sums from assistant message.usage; context ≈ peak input+cache |
| Codex | ~/.codex/sessions/**/rollout-*.jsonl |
codex resume <id> |
Last cumulative token_count; context ≈ max per-turn total |
| Devin | ~/.local/share/devin/cli/sessions.db |
devin -r <id> |
Aggregated from message_nodes |
| Grok | $GROK_HOME/sessions (default ~/.grok/sessions) |
grok --resume <id> |
Context size only on disk (signals.json); headless one-shots (is_non_interactive) are skipped |
Usage on the card is a short chip (ctx · out · tools · turns). Click it (or
press u on the active card) for a modal with overview KPIs, token mix,
activity counts, and a short note on how that source measures tokens.
Context is peak / window occupancy — not a full-session billing total. Grok often only has that size signal (labelled size only on the chip).
| Key | Action |
|---|---|
j / k or arrows |
Move active card |
Enter |
Resume in Terminal |
c |
Copy resume command (not ⌘C — system copy still works) |
p |
Pin / unpin |
u |
Open usage modal (when usage exists) |
⌘K / Ctrl+K |
Command palette |
server.py— thin entry point (python3 server.py/ launchd).siv/— stdlib-only backend on127.0.0.1:7333:GET /serves the viewer.GET /api/sessions?limit=100scans session files live, with an mtime/size cache so only changed files are re-parsed.POST /api/resumeopens a Terminal window with a validatedcd <cwd> && <tool> resume <id>command. If the recorded cwd belongs to another machine, the home-dir prefix is remapped to this machine.- Host badges come from the username in each session’s cwd
(
/Users/<name>/...or/home/<name>/...). - Parsers:
siv/sources/(claude,codex,devin,grok).
frontend/— React card UI (search, source/host filters, pin, usage modal).sessions-index.html— legacy single-file viewer (fallback if dist is missing).install.sh— launchd plist + optional frontend build. Logs:~/Library/Logs/session-index-viewer.log.index-sessions.sh— legacy shell indexer; superseded byserver.py.
If you sync session trees with Syncthing (or similar):
| Path | Sync-friendly? |
|---|---|
~/.claude/projects |
Yes (per-file jsonl) |
~/.codex/sessions |
Yes (per-file jsonl) |
~/.grok/sessions |
Yes if you sync only session dirs and ignore session_search.sqlite / *.lock |
Devin sessions.db |
No — single SQLite DB does not merge across machines |
No extra viewer config is required: each session is labelled by the username in its recorded cwd, and the host filter picks those labels up. Sessions that share a username across machines appear under the same host.
Avoid writing the same session id on two machines at once (conflict copies).
