DevTools for Claude Code — See exactly what Claude did, how much it cost, where it failed, and what it was thinking.
A real-time visualization dashboard for Claude Code sessions. Browse, search, and analyze your coding sessions with interactive execution trees, token cost tracking, thinking trace exploration, and error debugging — all in your browser.
3 commands to get started:
$ git clone https://github.com/anaypaul/claude-session-visualizer.git
$ cd claude-session-visualizer && npm install
$ npm run dev # Open http://localhost:3458
Quick Start • Features • How It Works • Development • Contributing
If you find this useful, give it a star — it helps others discover it.
Every Claude Code session generates a rich transcript — messages, tool calls, agent spawns, thinking blocks, and token usage — stored as JSONL files on your machine. Claude Session Visualizer reads these files and renders them as an interactive, real-time dashboard in your browser.
Think of it as DevTools for Claude Code: you can see exactly what Claude did, how much it cost, where it failed, and what it was thinking.
- Claude Code power users who want to understand and optimize their sessions
- Developers debugging failed or expensive Claude Code runs
- Teams evaluating different prompting strategies across sessions
- Anyone curious about what happens inside a Claude Code session
- Node.js 18+ (check with
node -v) - Claude Code installed (sessions are stored in
~/.claude/)
# Clone the repository
git clone https://github.com/anaypaul/claude-session-visualizer.git
cd claude-session-visualizer
# Install dependencies
npm install
# Start the dashboard (backend + frontend)
npm run devOpen http://localhost:3458 in your browser. That's it.
The dashboard will automatically discover all your Claude Code sessions (active and historical) and display them in the sidebar. Click any session to explore it.
The default view renders your session as a threaded conversation with:
- User/Assistant messages with markdown rendering and model badges
- Tool call cards — color-coded by type (Bash, Read, Write, Agent, etc.), expandable to show full input/output
- Thinking blocks — collapsible, showing Claude's reasoning process
- Full-text search — search across all messages, tool calls, and thinking blocks
- Filter toggles — show/hide by message type, sidechain, errors, or specific agent
An interactive graph (powered by React Flow) showing the complete execution flow:
- Agent nodes (large) — main session and every subagent with status, type, and message count
- Tool call nodes (small) — every tool invocation as a color-coded child node
- Collapsible groups — click an agent to expand/collapse its tool calls
- Error highlighting — failed tool calls glow red
- Pan, zoom, minimap — navigate large execution trees with ease
A stacked area chart tracking cumulative token consumption over the session:
- Four token types — input, output, cache read, cache creation
- Running cost estimate — in USD, using model-specific Anthropic pricing (Opus / Sonnet)
- Per-turn tooltips — hover to see the cost breakdown for any individual turn
- Real-time updates — the chart grows as the session progresses
A dedicated view for Claude's reasoning:
- Density sparkline — see where Claude was thinking hardest (longest thinking blocks)
- Keyword search — search across all thinking blocks with match highlighting
- Trigger context — see which user message triggered each thinking block
- Stats — estimated token count, character count, and average thinking length
A debugging view that surfaces every failure:
- Error density strip — red dots on a session timeline showing where errors occurred
- Failure rate — X errors out of Y tool calls (Z%)
- Recovery detection — did Claude retry the same tool, try a different approach, or give up?
- Error cards — tool name, input summary, error message, and what happened next
Browse all your Claude Code sessions across every project:
- 65+ sessions discoverable from
~/.claude/projects/ - Filter by status — All / Live / Closed
- Search — by session ID, project name, or working directory
- Project badges — see which project each session belongs to
- Metadata — message count, session duration, file size
A kanban-style view of Claude Code tasks:
- Three columns — Pending, In Progress, Completed
- Dependency tracking — blocked-by and blocks relationships
- Owner badges — who (or which agent) owns each task
Claude Session Visualizer is a local-only tool. It reads files from your machine — nothing is sent to any server.
~/.claude/
projects/ Hono Backend (port 3457) Browser (port 3458)
├── *.jsonl ────────> File Watcher (chokidar) ──────> React + Zustand
└── sessions/ JSONL Parser React Flow
└── *.json SSE Broadcaster <────── EventSource
REST API <────── fetch()
- Claude Code writes conversation data as append-only JSONL files in
~/.claude/projects/ - File watcher (chokidar) detects changes using byte-offset tracking — only reads new data, never re-reads the full file
- JSONL parser normalizes raw messages into a clean schema, grouping streamed assistant responses by
message.id - SSE broadcaster pushes events to all connected browsers in real time
- React frontend receives events via
EventSource, updates the Zustand store, and re-renders the active view
| File | What it contains |
|---|---|
~/.claude/sessions/{pid}.json |
Active session registry (PID, session ID, working directory) |
~/.claude/projects/{path}/{sessionId}.jsonl |
Full conversation transcript (messages, tool calls, thinking) |
~/.claude/projects/{path}/{sessionId}/subagents/agent-{id}.jsonl |
Subagent conversation transcripts |
~/.claude/projects/{path}/{sessionId}/subagents/agent-{id}.meta.json |
Agent metadata (type, description) |
~/.claude/tasks/{groupId}/{taskId}.json |
Task definitions (subject, status, dependencies) |
- 100% local — the dashboard runs on your machine and reads local files only
- Read-only — it never writes to or modifies any Claude Code files
- No telemetry — no data is sent anywhere
- No authentication — designed for single-user local use
| Layer | Technology |
|---|---|
| Backend | Hono (TypeScript), Node.js |
| Real-time | Server-Sent Events (SSE) |
| File watching | chokidar v4 |
| Frontend | React 18, Vite |
| State | Zustand v5 |
| Graph viz | React Flow (@xyflow/react) |
| Charts | Recharts |
| Language | TypeScript throughout |
claude-session-visualizer/
├── server/ # Backend (Hono, port 3457)
│ ├── index.ts # Server entry point
│ ├── api.ts # REST API (session listing, conversation loading)
│ ├── hooks.ts # Claude Code hook receiver (10 endpoints)
│ ├── sse.ts # SSE broadcaster (client management, event dispatch)
│ ├── parser.ts # JSONL parser (message normalization, grouping)
│ ├── watcher.ts # File watcher (byte-offset tracking, session discovery)
│ └── types.ts # Shared type definitions (the contract)
├── src/ # Frontend (React, port 3458)
│ ├── main.tsx # React entry point
│ ├── App.tsx # Dashboard layout (sidebar, tabs, metrics)
│ ├── store.ts # Zustand store (sessions, messages, agents, tasks)
│ ├── types.ts # Frontend type definitions
│ ├── hooks/
│ │ └── useSSE.ts # SSE connection hook
│ ├── components/
│ │ ├── SessionList.tsx # Session browser (filter, search, history)
│ │ ├── ConversationTimeline.tsx # Message timeline with search integration
│ │ ├── MessageBubble.tsx # Individual message renderer
│ │ ├── ToolCallCard.tsx # Tool call visualization
│ │ ├── ThinkingBlock.tsx # Inline thinking block (collapsible)
│ │ ├── AgentGraph.tsx # Execution tree (React Flow)
│ │ ├── TaskBoard.tsx # Kanban task board
│ │ ├── MetricsPanel.tsx # Token/tool metrics
│ │ ├── TokenBurnChart.tsx # Cost waterfall chart
│ │ ├── ThinkingExplorer.tsx # Thinking trace viewer
│ │ ├── ErrorReplayView.tsx # Error investigation view
│ │ └── MessageSearchBar.tsx # Search & filter bar
│ └── utils/
│ └── messageFilter.ts # Message filtering logic
├── index.html # HTML entry point
├── package.json
├── tsconfig.json
└── vite.config.ts # Vite config (proxy 3458 → 3457)
npm run dev # Start both backend and frontend in dev mode
npm run dev:server # Start only the backend (port 3457)
npm run dev:client # Start only the frontend (port 3458)
npm run build # Production build (TypeScript check + Vite build)
npm run preview # Preview the production buildThe tab system is plug-and-play. To add a new visualization:
-
Create
src/components/MyNewView.tsx:import { useStore } from '../store'; export function MyNewView() { const messages = useStore(s => s.messages); // Your visualization here return <div>...</div>; }
-
Register it in
src/App.tsx:import { MyNewView } from './components/MyNewView'; type TabId = '...' | 'myview'; const TABS = [ ...existing, { id: 'myview', label: 'My View' }, ]; const TAB_COMPONENTS = { ...existing, myview: MyNewView, };
-
That's it. No backend changes needed if your view uses existing data from the store.
To stream new data types from backend to frontend:
- Add the event type to
server/types.tsin theSSEEventunion - Emit it from
server/watcher.tsorserver/hooks.tsviabroadcast(event) - Handle it in
src/store.tsinsidehandleSSEEvent() - Consume it in any component via
useStore()
By default, the visualizer discovers sessions by watching JSONL files. For lower-latency updates, you can configure Claude Code to send HTTP hooks directly to the visualizer.
Add this to your ~/.claude/settings.json:
{
"hooks": {
"PreToolUse": [{ "matcher": "*", "hooks": [{ "type": "http", "url": "http://localhost:3457/hooks/pre-tool-use" }] }],
"PostToolUse": [{ "matcher": "*", "hooks": [{ "type": "http", "url": "http://localhost:3457/hooks/post-tool-use" }] }],
"SubagentStart": [{ "matcher": "*", "hooks": [{ "type": "http", "url": "http://localhost:3457/hooks/subagent-start" }] }],
"SubagentStop": [{ "matcher": "*", "hooks": [{ "type": "http", "url": "http://localhost:3457/hooks/subagent-stop" }] }],
"Stop": [{ "hooks": [{ "type": "http", "url": "http://localhost:3457/hooks/stop" }] }],
"SessionStart": [{ "matcher": "*", "hooks": [{ "type": "http", "url": "http://localhost:3457/hooks/session-start" }] }],
"SessionEnd": [{ "hooks": [{ "type": "http", "url": "http://localhost:3457/hooks/session-end" }] }]
}
}Make sure Claude Code has been run at least once. Session data is stored in ~/.claude/projects/. Check that this directory exists and contains .jsonl files:
ls ~/.claude/projects/Click a session in the sidebar to load it. If sessions appear but messages don't load, check the backend is running:
curl http://localhost:3457/healthIf ports 3457 or 3458 are in use, update them in:
server/index.ts(line 13) for the backend portvite.config.ts(line 11-12) for the frontend port and proxy target
- Session comparison view (side-by-side metrics for two sessions)
- File activity heatmap (which files Claude touched most)
- Session tagging and annotations
- Export sessions as JSON/CSV
- Deep linking (
?session=<id>URL parameter) - Code-splitting for faster initial load
Contributions are welcome! Here's how to get started:
- Fork the repository
- Create a branch for your feature (
git checkout -b feat/my-feature) - Make your changes — see Development for the project structure
- Test locally — run
npm run devand verify in the browser - Submit a pull request with a clear description of what you built
- TypeScript strict mode — no
anyunless absolutely necessary - All styling inline (no CSS modules or Tailwind) — keeps the project self-contained
- New views should read from the Zustand store, not fetch data independently
- Keep the backend read-only — never write to Claude Code's files
This project is licensed under the MIT License.
Built with Claude Code.