Snoop
Captures, processes, and summarizes Claude Code run transcripts for debugging and review.
Why Snoop?
Observability. Claude Code makes it difficult to review a specific transcript for a run. Snoop groups relevant messages by user prompt in your project ('.claude/transcripts') to make post-mortem analysis easier.
Debug failed sessions. When Claude goes off track, review the transcript to find where and why.
Catch anti-patterns. The reviewer agent identifies loops, scope creep, redundant reads, and incomplete work.
ESC interrupt tracking. Partial transcripts preserve exactly where you interrupted and what was pending.
Zero friction. Runs automatically. Keeps 10 transcripts, auto-cleans older ones.
How it works
Snoop uses Claude Code's hook system to capture transcripts at two points:
| Hook | Trigger | Action |
|---|
UserPromptSubmit | User sends a message | Check for pending tool_use without tool_result (indicates ESC interrupt). Save partial transcript with interrupt marker. |
Stop | Session ends normally | Merge any partial transcripts, write final JSONL, update latest pointer, prune old files. |
StopFailure | Session ends in API error (rate limit, 5xx, auth) | Same pipeline as Stop. Resulting transcript has 0 output tokens, 0 tool calls, and no lastAssistantPreview. |
Interrupt detection: When you press ESC mid-response, Claude's last message contains a tool_use block that never received a tool_result. Snoop detects this pattern and inserts an interrupt marker before your next message.
Subagent capture: The Task tool spawns subagents that run in separate contexts. Snoop loads their transcripts from Claude Code's internal subagents/ log directory and merges them into the main transcript, tagged with subagent: "agent-xxx".
File lifecycle:
- During session: partial transcripts saved as
.partial_{session_id}.jsonl
- On stop: partials merged into
{random_id}.jsonl (8-char ID)
- Cleanup: keeps 10 most recent transcripts, deletes older ones
Installation
# From marketplace
/plugin marketplace add rcrsr/claude-plugins
/plugin install snoop@rcrsr
# Or load locally
claude --plugin-dir /path/to/snoop
Quick Start
# Review your last session
/snoop:review
# Review specific transcript
/snoop:review abc12345
# Focus on specific concern
/snoop:review token usage
Status Line
After each session, Snoop outputs a status line:
[snoop] abc12345 | 2m 30s | 45 msgs | 150,000 in (50,000 p / 15,000 cw5m / 5,000 cw1h / 80,000 cr / 53% ce) | 5,000 out | 20% s46 / 80% o47 | 2 si (Explore, claude-code-guide) | 12 ti (Read, Edit, Bash)
| Field | Meaning |
|---|
abc12345 | Transcript ID (use with /snoop:review abc12345) |
2m 30s | Session duration |
45 msgs | Total messages captured |
150,000 in | Total input tokens (prompt + cache read + cache write) |
50,000 p | Prompt tokens (non-cached input) |
15,000 cw5m | Cache write tokens (5-minute ephemeral tier) |
5,000 cw1h | Cache write tokens (1-hour ephemeral tier) |
80,000 cr | Cache read tokens |
53% ce | Cache efficiency (cache read / total input) |
5,000 out | Output tokens |
20% s46 / 80% o47 | Output share by model, sorted descending. Only shown when multiple models are used (e.g. subagents on a different model). Shortcodes: s=sonnet, o=opus, h=haiku + major + minor version digits. |
2 si (...) | Subagent invocations with types (falls back to ID if unknown) |
12 ti (...) | Tool invocations with list of unique tools used |
Notes: cw1h only appears when 1-hour tier has tokens. Model breakdown only appears when >1 model is present.
With ESC interrupts:
[abc12345 | 1m 15s | ⚠️ 2x ESC | 23 msgs | ...]
Gotchas
Focus mode hides the status line. Claude Code's focus mode (toggle with /focus) suppresses all hook systemMessage output, so you won't see the [snoop] ... line after each turn. Transcripts are still captured to disk — only the UI notification is hidden. Toggle focus off with /focus if you want the live status back.
Token Counting
All token counts are API-reported. Main conversation usage comes from streaming message chunks (last chunk per request carries the cumulative total). Subagent usage comes from toolUseResult.usage.
Meta Tags
Add <snoop:meta key="value" .../> anywhere in conversation to enrich the transcript meta record.
Reserved attributes (special handling):
| Attribute | Effect |
|---|
file | Custom transcript path (relative to project root, always .jsonl extension) |
description | Free-text description stored in meta record |
tags | Comma-separated tags, stored as array |