6681f07fc059d38803267dfeb7e73782c0bb9c30
Export a new countSensitiveMessages() function that returns how many messages in an array contain at least one sensitive pattern match. Checks both content and toolInput fields, counting each message at most once regardless of how many matches it contains. Tests verify zero counts for clean messages, correct counting with mixed sensitive/clean messages, and the single-count-per-message invariant when multiple secrets appear in one message. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Session Viewer
Browse, filter, redact, and export Claude Code sessions as self-contained HTML files.
Session Viewer reads session data from ~/.claude/projects/ and presents it in a dark-themed web interface with full-text search, message filtering, sensitive data redaction, and one-click HTML export.
Quick Start
# Install dependencies
npm install
# Run in development mode (starts both server and client with hot reload)
npm run dev
# Or run from the CLI entry point (opens browser automatically)
node bin/session-viewer.js
The API server runs on http://localhost:3848 and the Vite dev server on http://localhost:3847 (proxying API requests to the backend).
Features
Session Navigation
- Project grouping -- Sessions are organized by their originating project directory.
- Session metadata -- Each session displays its summary, first prompt, message count, duration, and last-modified date.
- Sorted by recency -- Most recently modified sessions appear first.
Message Display
- Nine message categories --
user_message,assistant_text,thinking,tool_call,tool_result,system_message,hook_progress,file_snapshot, andsummary, each with a distinct color indicator. - Collapsible sections -- Thinking blocks, tool calls, and tool results collapse by default to reduce noise.
- Diff rendering -- Git-style diffs are auto-detected and rendered with line-level syntax coloring.
- Code blocks -- Fenced code blocks display a language label and a copy-to-clipboard button.
- Time gap indicators -- Gaps of more than five minutes between messages are shown as labeled dividers.
- Hash anchor links -- Each message has a copyable anchor link (
#msg-{uuid}) for deep linking.
Search
- Full-text search across message content and tool input.
- Match cycling -- Navigate between matches with
Enter/Shift+EnterorCtrl+G/Ctrl+Shift+G. - Match counter -- Displays current position and total matches (e.g., "3/12").
- Minimap -- A scrollbar overlay shows match positions as yellow ticks with a viewport indicator. Click a tick to jump to that match.
- Dimming -- Non-matching messages are visually dimmed while search is active.
- Keyboard shortcut -- Press
/to focus the search bar;Escapeto clear and blur.
Filtering
- Category toggles -- Show or hide any of the nine message categories. Thinking and hook progress are hidden by default.
- Filters compose with search -- Category filters and search operate independently.
Redaction
- Manual redaction -- Click the eye icon on any message to select it, then confirm to redact. Redacted messages are replaced by a visual divider.
- Auto-redaction -- Toggle automatic detection of sensitive data (API keys, tokens, secrets, PII) using 37 regex patterns derived from gitleaks. Matching content is replaced with
[REDACTED]inline. - Export-aware -- Both manual and auto-redaction states are respected during export.
Export
- Self-contained HTML -- Export the current session view as a standalone HTML file with embedded CSS and syntax highlighting.
- Respects filters -- The export includes only visible messages and applies the current redaction state.
- Clean filenames -- Output files are named
session-{id}.htmlwith sanitized IDs.
Architecture
src/
client/ React + Vite frontend
components/ UI components (SessionList, SessionViewer, MessageBubble, etc.)
hooks/ useSession, useFilters
lib/ Markdown rendering, sensitive redactor, types, utilities
styles/ CSS custom properties, Tailwind, design tokens
server/ Express backend
routes/ /api/sessions, /api/export
services/ Session discovery, JSONL parser, HTML exporter
shared/ Types shared between client and server
bin/ CLI entry point
tests/
unit/ Vitest unit tests
e2e/ Playwright end-to-end tests
fixtures/ Test data
Tech Stack
| Layer | Technology |
|---|---|
| Frontend | React 18, Tailwind CSS, Vite |
| Backend | Express 4, Node.js |
| Markdown | marked + marked-highlight + highlight.js |
| Testing | Vitest (unit), Playwright (e2e) |
| Language | TypeScript (strict mode) |
API Endpoints
| Method | Path | Description |
|---|---|---|
| GET | /api/health |
Health check |
| GET | /api/sessions |
List all sessions (30s server cache) |
| GET | /api/sessions/:id |
Get session detail with parsed messages |
| POST | /api/export |
Generate self-contained HTML export |
Scripts
| Script | Description |
|---|---|
npm run dev |
Start server + client with hot reload |
npm run build |
TypeScript compile + Vite production build |
npm run test |
Run unit tests (Vitest) |
npm run test:e2e |
Run end-to-end tests (Playwright) |
npm run typecheck |
TypeScript type checking |
npm run lint |
ESLint |
Configuration
| Variable | Default | Description |
|---|---|---|
PORT |
3848 |
API server port |
SESSION_VIEWER_OPEN_BROWSER |
unset | Set to 1 to auto-open browser on start |
Security
- Path traversal protection -- Session discovery validates all paths stay within
~/.claude/projects/. - HTML escaping -- All user content is escaped before interpolation in exports.
- Filename sanitization -- Export filenames strip non-alphanumeric characters.
- Localhost binding -- Both the API server and Vite dev server bind to
127.0.0.1only.
Description
Languages
TypeScript
84.7%
HTML
8.8%
CSS
5%
JavaScript
1.5%