Data Flow from Conversation JSONL Files to Analytics Dashboard UI

The analytics pipeline watches Claude Code session files in ~/.claude/**/*.jsonl, processes them through a multi-stage aggregation engine, and transmits real-time metrics via WebSocket to a React dashboard that renders live visualizations without browser refresh.

The davila7/claude-code-templates repository implements a complete analytics pipeline that transforms raw Claude Code conversation logs into interactive dashboard visualizations. Understanding the data flow from conversation JSONL files to the analytics dashboard UI demonstrates how the system achieves sub-second latency between file changes and UI updates. This architecture leverages filesystem watchers, in-memory caching, and persistent WebSocket connections to stream processed analytics directly to your browser.

Filesystem Detection and Conversation Identification

The pipeline initiates when Claude Code writes session data to ~/.claude/**/*.jsonl. The FileWatcher class in src/analytics/core/FileWatcher.js establishes a recursive filesystem monitor using chokidar to detect additions and modifications in real-time.

// src/analytics/core/FileWatcher.js (L42-L46)
this.watcher = chokidar.watch(path.join(this.claudeDir, '**/*.jsonl'), { 
  ignored: /(^|[\\/])\../ 
});

When the watcher detects a file event, the getConversationId method normalizes the path to extract conversation identifiers. Files named conversation.jsonl map to project names, while other *.jsonl files provide their filename (minus extension) as the conversation ID.

// src/analytics/core/FileWatcher.js (L136-L142)
if (fileName === 'conversation.jsonl') { 
  // ... project name extraction
} else if (fileName.endsWith('.jsonl')) { 
  return fileName.replace('.jsonl', ''); 
}

JSONL Parsing and Message Extraction

Upon identification, ConversationAnalyzer recursively traverses the Claude directory to ingest matching files. Located in src/analytics/core/ConversationAnalyzer.js, this module reads each line of the JSONL file, parses the JSON payload, and constructs a flat array of message and tool objects.

// src/analytics/core/ConversationAnalyzer.js (L74-L87)
// Search for .jsonl files recursively ...
const files = await glob('**/*.jsonl', { cwd: this.claudeDir, absolute: true });

// Build a message object (L121)
const messageObj = {
  id: filename.replace('.jsonl',''),
  // ... additional metadata
};

State Aggregation and In-Memory Caching

Raw message objects flow into StateCalculator and specialized analyzers such as AgentAnalyzer and YearInReview2025 to compute aggregated metrics. These modules calculate token usage totals, tool invocation frequencies, per-agent statistics, and annual review summaries from the parsed conversation data.

To eliminate redundant disk I/O, DataCache in src/analytics/data/DataCache.js stores each file's parsed content in memory after the first read. Subsequent analytics calculations or dashboard queries retrieve data from this in-memory cache rather than re-reading the conversation JSONL files from disk.

Real-Time WebSocket Distribution

When calculated state changes, NotificationManager emits a JSON payload through WebSocketServer. The server runs on localhost:3001 by default and maintains persistent connections to all connected dashboard clients, broadcasting updates immediately upon processing.

// src/analytics/notifications/WebSocketServer.js
const wss = new WebSocket.Server({ port: 3001 });

wss.broadcast = data => wss.clients.forEach(c => 
  c.readyState === WebSocket.OPEN && c.send(JSON.stringify(data))
);

This push-based architecture eliminates polling overhead and ensures the UI receives updates the moment new conversation data becomes available.

Dashboard Subscription and UI Rendering

The dashboard frontend establishes a WebSocket connection to ws://localhost:3001 within the React components located in dashboard/src/pages/analytics/[slug].tsx. Incoming messages update React state objects—including sessions, agents, tools, and tokenUsage—which drives the visualization layer.

AnalyticsChart.jsx in dashboard/src/components/AnalyticsChart.jsx consumes this state to render interactive tables, line charts, and pie charts using Chart.js and Recharts. The entire flow—from filesystem write to visual update—completes automatically while the CLI tool runs, providing developers with instantaneous visibility into their Claude Code usage patterns according to the davila7/claude-code-templates source code.

Summary

  • FileWatcher uses chokidar to monitor ~/.claude/**/*.jsonl for changes and extracts conversation IDs from filenames via getConversationId.
  • ConversationAnalyzer parses each JSONL line into structured message objects while DataCache prevents redundant disk reads by storing content in memory.
  • StateCalculator, AgentAnalyzer, and YearInReview2025 aggregate raw messages into metrics including token usage and tool breakdowns.
  • WebSocketServer broadcasts state updates on port 3001 to all connected dashboard clients in real-time via the broadcast method.
  • The React dashboard in dashboard/src/pages/analytics/[slug].tsx subscribes to the WebSocket and renders live charts via AnalyticsChart.jsx without requiring manual refresh.

Frequently Asked Questions

How does the analytics system detect new Claude Code conversations?

The FileWatcher class creates a recursive filesystem watcher using chokidar on the pattern **/*.jsonl within the Claude data directory (~/.claude/). When Claude Code writes to conversation.jsonl or creates new session files, the watcher emits add or change events that trigger the processing pipeline immediately.

What port does the WebSocket server use for dashboard updates?

The WebSocketServer listens on port 3001 by default. The React dashboard components connect to ws://localhost:3001 to receive real-time JSON payloads containing aggregated session metrics, eliminating the need for HTTP polling or manual page refreshes.

Where is the conversation data cached to prevent repeated file reads?

The DataCache module in src/analytics/data/DataCache.js stores the raw content of each JSONL file in memory after the first read. Subsequent analytics calculations or dashboard queries retrieve data from this in-memory cache rather than re-reading files from disk, significantly improving performance when processing large conversation histories.

Which React components handle the WebSocket connection and chart rendering?

The page component in dashboard/src/pages/analytics/[slug].tsx manages the WebSocket subscription and state updates, while dashboard/src/components/AnalyticsChart.jsx implements the actual visualization layer using Chart.js and Recharts to render the aggregated metrics received from the analytics pipeline.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →