Claude Session Management Suite

SkillWeb & browsing

Manage Claude Code sessions — search by topic or ID, browse recent sessions with full metadata (tags, summaries, titles, cost), view title/nickname history timelines, resume in Ghostty tabs, spawn interactive or headless sessions, monitor live sessions, and bootstrap new setups. Triggers on resume session, find session, list sessions, recent sessions, spawn session, session history, what was I working on, open in ghostty, title history, session nicknames.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Claude Session Management Suite skill

What this skill tells your AI

The instructions your AI receives, as published by tdimino/claude-code-minoan in skills/planning-productivity/claude-tracker-suite/SKILL.md and read by ahel’s review.

Search, browse, monitor, and manage Claude Code session history across all projects.

Tools Overview

ToolPurpose
claude-tracker-searchSearch sessions by keyword or ID prefix
claude-tracker-pickInteractive fzf picker: fuzzy-find recent sessions, preview, Enter resumes in Ghostty
index-transcripts.jsBuild/refresh the transcript full-text index (FTS5 over user+assistant text) and extract title history events
backfill-summaries.jsGenerate missing session summaries (claude CLI or OpenRouter; disabled by default, --enable to run)
audit-suite.jsSelf-audit: inventory, portability, daemons, DB coverage, search recall → AUDIT.md
search-regression.jsRecall regression fixtures for the search stack (exit 1 on regression)
open-sessions.jsList top N sessions, open selected in Ghostty tabs
claude-tracker-resumeFind and resume crashed/inactive sessions
claude-tracker-aliveCheck which sessions have running processes
claude-tracker-watchDaemon: auto-summarize new sessions, update active-projects.md
claude-trackerList recent sessions with status badges
new-session.shStart a new session in Ghostty or headless, with optional prompt
resume-session.shOpen a session in a Ghostty tab (optionally open project in Cursor)
detect-projects.jsScan sessions to find all projects, check CLAUDE.md coverage
bootstrap-claude-setup.jsGenerate complete ~/.claude/ config for new machine
update-active-projects.pyRegenerate active-projects.md with enriched session data
checkpoint-session.jsCreate/query named bookmarks within sessions
quote-session.jsCapture/search notable phrases with FTS5
tag-session.jsManual session tagging with provenance
claude-tracker-recentShow last N sessions with full metadata (title, tags, summary, cost, model)
claude-wrapper.shShell function cc for named Claude sessions with auto tab titles
save-workspace.jsSnapshot alive sessions to ~/.claude/workspace-state.json
restore-workspace.shRestore saved sessions into Ghostty tabs
open-file-explorer.shOpen yazi file explorer in a Ghostty split pane

Standalone Scripts

Commands delegate to standalone Node.js scripts (avoids shell escaping issues with inline node -e):

ScriptCalled ByPurpose
scripts/search-sessions.js/claude-tracker-searchKeyword search or --id prefix lookup across all sessions
scripts/open-sessions.jsDirect invocationList top N sessions, open selected in Ghostty tabs
scripts/list-sessions.js/claude-trackerList recent sessions with status badges
scripts/new-session.sh/spawnStart new interactive or prompt-driven session in Ghostty or headless
scripts/resume-session.shDirect invocationOpen session in Ghostty tab, optionally open project in Cursor
scripts/detect-projects.jsDirect invocationProject discovery and CLAUDE.md scaffolding
scripts/bootstrap-claude-setup.jsDirect invocationNew machine setup generator
scripts/checkpoint-session.js/checkpoint, /checkpoint-listCreate and query session checkpoints
scripts/quote-session.js/quote, /quote-searchCapture and search tagged phrases via FTS5
scripts/tag-session.js/tagManual session tagging with provenance
scripts/recent-sessions.js/claude-tracker-recentLast N sessions with title, tags, summary, model, cost
scripts/claude-wrapper.shSource in .zshrcShell function cc for named sessions with tab titles
scripts/save-workspace.jsDirect / launchdSnapshot alive sessions to workspace-state.json (deduped; never overwrites a good snapshot with an empty one)
scripts/restore-workspace.shDirect invocationRestore sessions from workspace-state.json into Ghostty tabs
scripts/claude-tracker-pickDirect invocationfzf session picker with preview; Enter→Ghostty, Ctrl-O→current terminal, Ctrl-Y→copy
scripts/index-transcripts.jsHooks / launchd / in-processIncremental transcript FTS indexer (EXTRACTOR_VERSION 4; prunes deleted; extracts title history events)
scripts/backfill-summaries.jsDirect invocationHermetic summary backfill, claude or OpenRouter provider (disabled by default)
scripts/audit-suite.jsDirect invocationSuite self-audit → AUDIT.md
scripts/search-regression.jsAfter search changesRecall fixtures incl. expected-fail semantic-gap marker
scripts/open-file-explorer.shDirect invocationOpen yazi in a Ghostty split pane
~/.claude/scripts/ghostty-resume.shDirect invocationThe single terminal opener for the suite—opens sessions in Ghostty tabs or splits

All scripts use ~/.claude/lib/tracker-utils.js for shared utilities (path decoding, session parsing, live-session detection, git remote detection) and ~/.claude/lib/tracker-db.js for SQLite access (node:sqlite DatabaseSync, WAL mode, singleton lazy-open). No npm dependencies—the DB module uses Node's built-in node:sqlite (Node >= 22.13).

Quick Start

# Search by topic
claude-tracker-search "kothar mac mini"

# Lookup by session ID prefix (exact directory from JSONL ground truth)
node ~/.claude/skills/claude-tracker-suite/scripts/search-sessions.js --id d7b8f4dd

# Search by session name/slug only (fast — no body scan)
claude-tracker-search "thera" --name

# List top 10 sessions, open selected in Ghostty tabs
node ~/.claude/skills/claude-tracker-suite/scripts/open-sessions.js

# Check what's alive
claude-tracker-alive

# Resume crashed sessions in Ghostty
claude-tracker-resume --open

# Start auto-summarize daemon
claude-tracker-watch --daemon

Search

claude-tracker-search "$ARGUMENTS"

How search works: the default path queries the transcript full-text index (FTS5 over all user+assistant conversation text, built by index-transcripts.js), merged with metadata FTS over titles/slug/summary/first-prompt (bm25 column weights: custom_title 3x, auto_title 2x, summary 2x, first_prompt 1.5x, slug 1x). Multi-word queries match per-term at the session level (terms may appear in different messages), expand through synonym groups in references/synonyms.json, and fall back from AND to OR with a labeled partial-match notice. Ranking: IDF-weighted saturated match-density with a short-session damp. Results include highlighted snippet excerpts.

Before every body search, search-sessions.js runs an in-process index refresh (1.5s budget) so sessions from today are searchable within seconds of their last turn. The refresh line reads Index refreshed: N session(s) in Xms — M still pending. Pass --no-refresh to skip it.

Former-title fallback: default search also checks title_history for sessions whose past titles match the query but whose current title does not. A session renamed away from a name the user remembers still surfaces under a "former-title matches" heading, capped to avoid crowding body results. Each former-title hit prints its old name, provenance, date, and a link to the full timeline via the titles subcommand.

Flag / SubcommandDescription
--limit <n>Max results (default: 15)
--id <prefix>Lookup by session ID prefix (8+ chars)
--nameTitles/slugs/summaries only via metadata FTS (fastest)
--deepBypass the index: streaming raw JSONL scan (new/unindexed sessions; whole-phrase matching)
--openResume the top hit in a new Ghostty tab immediately
--copyCopy the top hit's resume command to the clipboard (opt-in; nothing writes clipboard by default)
--no-refreshSkip the on-demand index catch-up before searching
titles <id-prefix>Print the chronological title/nickname timeline for a session (all rename, slug, cache, and summarizer events)

Transcript Index & Summary Backfill

# Incremental index refresh (skips unchanged files; runs automatically via hooks and launchd)
node ~/.claude/skills/claude-tracker-suite/scripts/index-transcripts.js

# Full rebuild (also forced automatically when EXTRACTOR_VERSION bumps)
node ~/.claude/skills/claude-tracker-suite/scripts/index-transcripts.js --rebuild

# Single session (what the hooks call)
node ~/.claude/skills/claude-tracker-suite/scripts/index-transcripts.js --session <id>
node ~/.claude/skills/claude-tracker-suite/scripts/index-transcripts.js --stdin --quiet --debounce 120

# Budget-limited refresh (what search-sessions.js calls in-process)
node ~/.claude/skills/claude-tracker-suite/scripts/index-transcripts.js --budget 1500

# Backfill missing summaries — DISABLED BY DEFAULT, requires --enable
# (or TRACKER_SUMMARIZER=1). Hermetic when run: --safe-mode
# --no-session-persistence, no hooks fire, no synthetic sessions persist.
node ~/.claude/skills/claude-tracker-suite/scripts/backfill-summaries.js --enable
node ~/.claude/skills/claude-tracker-suite/scripts/backfill-summaries.js --enable --session <id-prefix>  # force one

# OpenRouter backend instead of claude CLI (default model moonshotai/kimi-k2;
# key from OPENROUTER_API_KEY or ~/.config/env/secrets.env)
node ~/.claude/skills/claude-tracker-suite/scripts/backfill-summaries.js --enable --provider openrouter

# Preview excerpts without any LLM calls (no gate needed)
node ~/.claude/skills/claude-tracker-suite/scripts/backfill-summaries.js --dry-run

# NOTE: the watcher-daemon auto-name path (update-active-projects.py) is also
# gated off by default; set TRACKER_AUTO_NAME=1 to re-enable it.

# Recall regression suite — run after touching search code or synonyms
node ~/.claude/skills/claude-tracker-suite/scripts/search-regression.js

# Suite self-audit → AUDIT.md (P0-P3 findings)
node ~/.claude/skills/claude-tracker-suite/scripts/audit-suite.js

The indexer runs automatically through three channels: Stop and SessionEnd hooks (--stdin --quiet --debounce 120 async on Stop, --stdin --quiet --debounce 10 sync on SessionEnd), the hourly com.claude.transcript-index launchd agent (plist in scripts/, installed in ~/Library/LaunchAgents/, logs in ~/.claude/logs/transcript-index.{log,err}), and in-process from search-sessions.js before every body search (1.5s budget). Sessions are searchable within seconds of their last turn.

Incremental indexing skips files whose size, mtime, and extractor version (currently EXTRACTOR_VERSION 4) all match transcript_index_state. Bumping the version constant forces a full reindex under new extraction rules. Read errors are never recorded as indexed—the session stays eligible for the next run, preventing a partial read from permanently masking content from search. Deleted transcripts are pruned on full (unlimited) runs.

Since v4, the indexer also extracts title history events from each transcript: /rename custom-title lines (source user), slug changes (source slug). Custom-title lines route by the line's own sessionId field, not the containing file—a /rename after /resume writes into the active transcript but targets the previous session. Claude Code's own metadata scanner gets this wrong, overwriting the active session's title with the rename target's title. Consecutive duplicate title values within a file collapse to a single event.

Known lexical limit: a session can only be found by words that actually occur in it—the [expected fail] regression fixture documents this; a semantic (rlama) layer is the designated future fix.

Interactive Picker (restart recovery)

~/.claude/skills/claude-tracker-suite/scripts/claude-tracker-pick              # fuzzy-find recent 50
~/.claude/skills/claude-tracker-suite/scripts/claude-tracker-pick --here      # resume in current terminal
~/.claude/skills/claude-tracker-suite/scripts/claude-tracker-pick --project thera --limit 100

Enter opens the session in a Ghostty tab, Ctrl-O resumes in the current terminal, Ctrl-Y copies the resume command. Preview shows title, summary, and first prompt. Pair with restore-workspace.sh (bulk restore from the launchd snapshot)—the picker is for choosing, restore is for "give me back everything".

Resume Crashed Sessions

claude-tracker-resume                    # List crashed sessions with resume commands
claude-tracker-resume --open             # Reopen each in a new Ghostty tab
claude-tracker-resume --open --limit 3   # Reopen at most 3
claude-tracker-resume --dry-run          # Preview without acting
claude-tracker-resume --days 14          # Widen the look-back window (default 7)

A crashed session is the newest transcript per project (within the look-back window) that has no live Claude process, for projects with no live tab at all. Liveness comes from ~/.claude/sessions/<pid>.json PID files via tracker-utils.getLiveSessions(). Sessions older than 3 days show an OLD badge.

Workspace Stamp & Restore (claude + codex)

Survive a logout/reboot with every agent session intact:

node ~/.claude/skills/claude-tracker-suite/scripts/save-workspace.js   # Stamp now (also runs every 5 min via launchd)
claude-tracker-resume --workspace --dry-run                            # Preview the restore
claude-tracker-resume --workspace                                      # Reopen every session in Ghostty tabs, in order

The stamp (~/.claude/workspace-state.json) captures all live Claude Code sessions (from the authoritative ~/.claude/sessions/<pid>.json PID files) and Codex CLI sessions (native binary PIDs joined to their open rollout files via lsof; the earliest-opened rollout is the main thread, its filename carries the UUID). Entries are TTY-ordered so tabs restore in their original order. Empty-protection means a post-logout stamp never clobbers the last good one. Restore warns when the stamp is >15 min old and reports per-agent counts.

Alive Detection

Check which sessions have running Claude processes:

claude-tracker-alive                     # Running + stale sessions overview
claude-tracker-alive --running           # Only sessions with active processes
claude-tracker-alive --stale             # Only sessions with no process
claude-tracker-alive --all-kinds         # Include headless/background sessions
claude-tracker-alive --json              # Machine-readable output

Source of truth is Claude Code's PID files (~/.claude/sessions/<pid>.json), verified against one ps pass via getLiveSessions(). Matching is by sessionId—a crashed session next to a live sibling in the same directory is no longer reported RUNNING. Sessions >3 days without a process show an OLD badge.

Auto-Summarize Daemon

Watch for new sessions and auto-populate summary cache:

claude-tracker-watch --status            # Check if daemon is running
claude-tracker-watch --daemon            # Start in background
claude-tracker-watch --stop              # Stop running daemon
claude-tracker-watch --verbose           # Foreground with debug output

Dormant: it watches sessions-index.json, which Claude Code no longer writes, so it never fires on current versions. Kept for reference; see references/daemon-setup.md for the launchd agents that do run (workspace-snapshot, transcript-index, db-maintain).

Recent Sessions (Full Metadata)

claude-tracker-recent                          # Last 10 sessions with full metadata
claude-tracker-recent --limit 20               # Last 20 sessions
claude-tracker-recent --json                   # Machine-readable JSON output
claude-tracker-recent --project myapp          # Filter by project
claude-tracker-recent --model opus             # Filter by model
claude-tracker-recent --since 7d               # Last 7 days only

Shows per session: title (custom or auto), summary, all tags (color-coded by type), project name, age, model, cost, turn count, git branch, session ID, and resume command. Add --copy to put the first resume command on the clipboard (never done by default).

Session Listing

claude-tracker                           # All recent sessions

Status badges: ACTIVE (process running, recent heartbeat), STALE (process exists but no recent activity), OLD (older than 24 hours), CRASHED (process not found, no clean exit).

When speculator is running, the session listing includes Ghostty tab count and window count in the header, plus TTY badges per session showing which Ghostty tab it occupies.

Detect Projects

node ~/.claude/skills/claude-tracker-suite/scripts/detect-projects.js                # List all
node ~/.claude/skills/claude-tracker-suite/scripts/detect-projects.js --suggest      # Suggest additions
node ~/.claude/skills/claude-tracker-suite/scripts/detect-projects.js --scaffold     # Create CLAUDE.md stubs
node ~/.claude/skills/claude-tracker-suite/scripts/detect-projects.js --since 30d    # Recent only

Update Active Projects

python3 ~/.claude/scripts/update-active-projects.py              # Regenerate active-projects.md
python3 ~/.claude/scripts/update-active-projects.py --summarize  # Show sessions needing summaries

The generated table includes Model, Turns, and Cost columns from enriched session data (extracted from JSONL transcripts). Git worktree sessions show a tree emoji badge. The auto-name path (one-shot claude --model haiku call for sessions without summaries) is disabled by default—set TRACKER_AUTO_NAME=1 to re-enable it. Native Claude Code session summaries stopped generating around v2.1.31 (February 2026), so sessions-index.json summary fields are stale for newer sessions; use backfill-summaries.js or the transcript index instead.

Bootstrap New Setup

Generate a complete ~/.claude/ configuration for a new machine:

node ~/.claude/skills/claude-tracker-suite/scripts/bootstrap-claude-setup.js --user "Name" --dry-run
node ~/.claude/skills/claude-tracker-suite/scripts/bootstrap-claude-setup.js --user "Name"

Creates directory structure, global CLAUDE.md, userModel template, agent_docs stubs, and project CLAUDE.md scaffolds. Follow up with /claude-md-manager to enrich generated files.

Resume in Ghostty Tab

The single terminal opener for the suite is ~/.claude/scripts/ghostty-resume.sh. It writes a tiny launcher script to ~/.claude/run/launch/ and has Ghostty run it in a new tab or split.

~/.claude/scripts/ghostty-resume.sh <session-id>
~/.claude/scripts/ghostty-resume.sh <session-id> --project ~/my-project --name "auth-fix"
~/.claude/scripts/ghostty-resume.sh <session-id> --split right       # split the current tab
~/.claude/scripts/ghostty-resume.sh <session-id> --print             # write launcher, print its path
~/.claude/scripts/ghostty-resume.sh --exec "claude -n foo" --project ~/my-project  # arbitrary command

On Ghostty >= 1.3.0, the opener uses the AppleScript dictionary (new surface configuration with initial working directory + initial input, then new tab or split)—no keystrokes, no clipboard, no focus dependency. On older builds it falls back to activate + Cmd-T + one Cmd-V paste of the launcher path (clipboard saved/restored). --split requires the scripting dictionary (>= 1.3.0); without it, the flag is ignored and a tab opens instead.

The launcher itself checks the project directory and transcript before running exec claude --resume <id>, falling back to a fresh session with a reason when either is missing. Launchers are pruned after a day; ~/.claude/run/ is gitignored. Claude Code sets tab titles itself (-n / derived name)—nothing is injected.

Exit codes: 0 opened, 1 bad arguments or unresolvable session, 2 Ghostty or Accessibility unavailable.

resume-session.sh is a thin wrapper that delegates to the opener, with --cursor to also open the project in Cursor.

New Session / Spawn

Start a new Claude Code session in a terminal tab or headless:

# Interactive session in Ghostty (default)
~/.claude/skills/claude-tracker-suite/scripts/new-session.sh ~/my-project

# With a specific model
~/.claude/skills/claude-tracker-suite/scripts/new-session.sh ~/my-project --model opus

# Prompt-driven session in Ghostty tab
~/.claude/skills/claude-tracker-suite/scripts/new-session.sh ~/my-project --prompt "fix the login bug"

# Headless — runs in current terminal, returns JSON
~/.claude/skills/claude-tracker-suite/scripts/new-session.sh ~/my-project --headless --prompt "summarize the README"

# Headless with specific model and output format
~/.claude/skills/claude-tracker-suite/scripts/new-session.sh ~/my-project --headless --prompt "fix tests" --model haiku --output-format text

Headless and prompt-driven modes use claude -p (the Agent SDK CLI). Terminal modes delegate to ghostty-resume.sh --exec.

Workflow: Find and Resume

  1. claude-tracker-search "topic" — find matching sessions
  2. claude-tracker-recent — browse last 10 sessions with full metadata
  3. claude --resume <session-id> — resume in current terminal
  4. ~/.claude/scripts/ghostty-resume.sh <session-id> — resume in a new Ghostty tab
  5. claude-tracker-resume --open — auto-resume all crashed sessions in Ghostty

Workflow: Monitor Active Work

  1. claude-tracker-alive — see what's running vs stale
  2. claude-tracker-watch --daemon — keep summaries auto-updated
  3. Read ~/.claude/agent_docs/active-projects.md — curated project overview

Native Claude Code Features

Claude Code 2.1.263+ provides session management primitives that overlap with parts of this suite. Where native is sufficient, use it directly:

  • claude -r|--resume [id|name|search-term] — built-in picker with search across all projects
  • -n/--name — name a session at launch (shown in /resume picker and tab title)
  • /rename — rename the current session
  • --fork-session — fork a session for exploratory work
  • --from-pr — start a session seeded with a PR's context
  • --bg + claude attach — background sessions with attach/detach
  • -w/--worktree — worktree isolation

This suite's cleanupPeriodDays is 99999 so transcripts never expire.

SQLite Database (tracker.db)

Single SQLite database at ~/.claude/tracker.db consolidates all session metadata, git tracking, tags, and three capabilities: checkpoints, phase tracking, and tagged phrases.

API module: ~/.claude/lib/tracker-db.js — synchronous node:sqlite DatabaseSync (built into Node >= 22.13, no native module to rebuild), WAL mode, singleton lazy-open. The compat shim keeps the prepare/run/get/all/exec/pragma/transaction surface the call sites were written against and throws on a missing named parameter. isAvailable() is a real open probe (attempts a read-only open); tryDb() in tracker-utils.js prints tracker-db unavailable: <reason> — falling back to JSONL scan to stderr once per process instead of failing silently.

# Query directly
sqlite3 ~/.claude/tracker.db "SELECT COUNT(*) FROM sessions;"
sqlite3 ~/.claude/tracker.db "SELECT phase, COUNT(*) FROM phases GROUP BY phase;"
sqlite3 ~/.claude/tracker.db "SELECT phrase, GROUP_CONCAT(tag) FROM tagged_phrases tp LEFT JOIN tagged_phrase_tags tpt ON tpt.phrase_id = tp.id GROUP BY tp.id ORDER BY tp.timestamp DESC LIMIT 10;"

Migration (idempotent): node ~/.claude/scripts/migrate-to-sqlite.js

Title / Nickname History

The title_history table records every name a session has ever had, with provenance. Sources: user (from /rename custom-title lines), slug (auto-nickname from Claude Code), cache (May 2026 metadata import from session-summaries.json), summarizer (from backfill-summaries.js).

# Print the title timeline for a session
node ~/.claude/skills/claude-tracker-suite/scripts/search-sessions.js titles <id-prefix>

Shortened here. Read the whole file on GitHub.

Signals

GitHub stars
41
Forks
4
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
claude-tracker-suite
Source
github.com/tdimino/claude-code-minoan