A local timeline for everything you do with coding agents. It indexes the JSONL transcripts that Claude Code, Codex and Qwen already write to disk, and gives you a single page where a month of work is legible: what you worked on, when, which files and skills were involved, what it would have cost on API pricing, and which sessions belong together.
Everything runs on your machine. No transcript is uploaded anywhere; the only outbound calls are optional one-line title generation through your own claude CLI.
A timeline, not a log. Sessions, prompts, files, skills, MCP calls and tool calls are laid out on a real time axis, so a day reads at a glance — where the long stretches went, where the work fragmented.
Sessions with names. A session's ID tells you nothing. Every session gets a one-line title generated from what actually happened in it (Auth: fix token refresh loop), cached in the database and reused everywhere — timeline, search, the topic graph.
Topics that mean something. Sessions are clustered by which files they actually touched (Jaccard overlap), not by which folder they ran in. A month of work in one repo splits into the threads it really consisted of, and the mini-graph on each session shows its neighbours in that thread.
What it cost. Per-session spend at Anthropic list prices (input, output, cache write at 1.25×, cache read at 0.1×), rolled up per day and per window, plus a cache hit rate — a long session with a low hit rate is usually where the money went.
Full-text search over the lot. SQLite FTS5 across prompts, file paths, skills, titles and summaries, with a ⌘K palette in the UI.
Resume anything. One click builds the claude --resume / codex resume / qwen --resume command for a session and can launch it in a new terminal.
- Python 3.11+ (standard library only — no pip install)
- macOS or Linux
- Optional: the
claudeCLI, for generated titles and summaries - Optional:
ccusage, for the subscription usage bar
git clone https://github.com/<you>/session-inspector.git
cd session-inspector
cp scripts/config.example.json scripts/config.json # then edit it
python3 scripts/session-index.py rebuild # first full index
python3 scripts/session-index.py export # generate the UI data
python3 scripts/sessions-inspector-serve.py --port 8766Open http://localhost:8766/sessions-inspector.html.
rebuild walks ~/.claude/projects, ~/.codex/sessions and ~/.qwen/projects; on a year of history it takes a couple of minutes. After that, incremental only reads what changed and is what you want on a schedule.
Everything environment-specific lives in scripts/config.json (gitignored). All keys are optional — see scripts/config.example.json for the annotated shape. The interesting ones:
| Key | What it does |
|---|---|
claude_cli |
Path to the claude binary for title generation. Omit to use claude from PATH. |
plan |
Your subscription's 5-hour prompt limits, drawn in the usage bar. |
project_labels |
cwd substring → short label, for grouping sessions by project. |
ubiquitous_files |
Files nearly every session touches. Excluded from topic clustering, where they'd otherwise link everything to everything. |
notes_vault / ops_projects |
Optional. Where the "write session card" button files its output. |
python3 scripts/session-index.py incremental # index new/changed sessions, refresh the export
python3 scripts/session-index.py search "rate limit" # full-text search
python3 scripts/session-index.py show 8129840d # one session in detail
python3 scripts/session-index.py timeline --date today
python3 scripts/session-index.py titles --limit 100 --since 7d # backfill titles
python3 scripts/session-index.py statstitles runs several claude -p calls in parallel and caches the result forever; --force regenerates. If the CLI isn't available, sessions fall back to a heuristic title (skill name, or the opening words of the first prompt) and nothing else breaks.
A scheduled incremental every half hour keeps the page live. Example agents are in launchd/ (macOS); on Linux the equivalent is two cron lines:
*/30 * * * * cd ~/session-inspector && python3 scripts/session-index.py incremental
40 3 * * * cd ~/session-inspector && python3 scripts/session-index.py titles --limit 120 --since 7d~/.claude/projects/**.jsonl ─┐
~/.codex/sessions/**.jsonl ─┼─→ session-index.py ─→ store/sessions.db (SQLite + FTS5)
~/.qwen/projects/**.jsonl ─┘ │
├─→ sessions-data.js
sessions-inspector.html (single file, no build)
│
sessions-inspector-serve.py (static + a few POST endpoints)
The database is in WAL mode, so the scheduled indexer and a long title backfill don't lock each other out. The UI is one HTML file with no dependencies and no build step — open it directly from disk if you don't need the resume/generate buttons.
A few UI labels are in Russian (the author's language). They're plain strings in store/sessions-inspector.html if you want to change them.
Your transcripts contain everything you've ever pasted into an agent. Accordingly:
store/sessions.dbandstore/sessions-data.jsare gitignored. Don't commit them.scripts/config.jsonis gitignored — it holds your paths and project names.- The server binds to localhost.
- Title and summary generation sends session metadata (first prompt, file names, duration) to your own
claudeCLI. Skip those commands if that's not acceptable for your data.
MIT