Commit Graph

4 Commits

Author SHA1 Message Date
ecd63cd1c3 Add React client: session browser, message viewer, filters, search, redaction, export
Full React 18 client application for interactive session browsing:

app.tsx:
- Root component orchestrating session list, viewer, filters, search,
  redaction controls, and export — wires together useSession and
  useFilters hooks
- Keyboard navigation: j/k or arrow keys for message focus, Escape to
  clear search and redaction selection, "/" to focus search input
- Derives filtered messages, match count, visible UUIDs, and category
  counts via useMemo to avoid render-time side effects

hooks/useSession.ts:
- Manages session list and detail fetching state (loading, error,
  data) with useCallback-wrapped fetch functions
- Auto-loads session list on mount

hooks/useFilters.ts:
- Category filter state with toggle, set-all, and preset support
- Text search with debounced query propagation
- Manual redaction workflow: select messages, confirm to move to
  redacted set, undo individual or all redactions, select-all-visible
- Auto-redact toggle for the sensitive-redactor module
- Returns memoized object to prevent unnecessary re-renders

components/SessionList.tsx:
- Two-phase navigation: project list → session list within a project
- Groups sessions by project, shows session count and latest modified
  date per project, auto-drills into the correct project when a session
  is selected externally
- Formats project directory names back to paths (leading dash → /)

components/SessionViewer.tsx:
- Renders filtered messages with redacted dividers inserted where
  manually redacted messages were removed from the visible sequence
- Loading spinner, empty state for no session / no filter matches
- Scrolls focused message into view via ref

components/MessageBubble.tsx:
- Renders individual messages with category-specific Tailwind border
  and background colors
- Markdown rendering via marked + highlight.js, with search term
  highlighting that splits HTML tags to avoid corrupting attributes
- Click-to-select for manual redaction, visual selection indicator
- Auto-redact mode applies sensitive-redactor to content before render
- dangerouslySetInnerHTML is safe here: content is from local
  user-owned JSONL files, not untrusted external input

components/FilterPanel.tsx:
- Checkbox list for all 9 message categories with auto-redact toggle

components/SearchBar.tsx:
- Debounced text input (200ms) with match count display
- "/" keyboard shortcut to focus, × button to clear

components/ExportButton.tsx:
- POSTs current session + visible/redacted UUIDs + auto-redact flag
  to /api/export, downloads the returned HTML blob as a file

components/RedactedDivider.tsx:
- Dashed-line visual separator indicating redacted content gap

lib/types.ts:
- Re-exports shared types via @shared path alias for client imports

lib/constants.ts:
- Tailwind CSS class mappings per message category (border + bg colors)

lib/markdown.ts:
- Configured marked + highlight.js instance with search highlighting
  that operates on text segments only (preserves HTML tags intact)

styles/main.css:
- Tailwind base/components/utilities, custom scrollbar, highlight.js
  overrides, search highlight mark, redaction selection outline,
  message dimming for non-matching search results

index.html + main.tsx:
- Vite entry point mounting React app into #root with StrictMode

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 22:56:37 -05:00
090d69a97a Add Express server: session discovery, JSONL parser, HTML exporter, API routes
Server-side implementation for reading, parsing, and exporting Claude
Code session logs:

session-discovery.ts:
- Walks ~/.claude/projects/ directories, reads sessions-index.json from
  each project folder, supports both the current {version, entries}
  format and the legacy raw array format
- Aggregates sessions across all projects, sorted by most recently
  modified first
- Gracefully handles missing directories, corrupt index files, and
  missing entries

session-parser.ts:
- Parses Claude Code JSONL session files line-by-line into normalized
  ParsedMessage objects
- Handles the full real-world format: type="user" (string or
  ContentBlock array content), type="assistant" (text, thinking,
  tool_use blocks), type="progress" (hook events with structured data
  fields), type="summary" (summary text field), type="file-history-
  snapshot", and silently skips type="system" (turn_duration metadata)
  and type="queue-operation" (internal)
- Detects <system-reminder> tags in user messages and reclassifies them
  as system_message category
- Resilient to malformed JSONL lines (skips with continue, no crash)

html-exporter.ts:
- Generates self-contained HTML exports with no external dependencies —
  all CSS (layout, category-specific colors, syntax highlighting) is
  inlined in a <style> block
- Dark theme (GitHub dark palette) with category-specific left border
  colors and backgrounds matching the Claude Code aesthetic
- Renders markdown content via marked + highlight.js with syntax
  highlighting, inserts "content redacted" dividers where redacted
  messages were removed
- Outputs a complete <!DOCTYPE html> document with session metadata
  header (project name, date, message count)

routes/sessions.ts:
- GET /api/sessions — returns all discovered sessions with 30-second
  in-memory cache to avoid re-scanning the filesystem on every request
- GET /api/sessions/:id — looks up session by ID from cache, parses
  the JSONL file, returns parsed messages

routes/export.ts:
- POST /api/export — accepts ExportRequest body, validates required
  fields, generates HTML via the exporter, returns as a downloadable
  attachment with sanitized filename

index.ts:
- Express app factory (createApp) with 50MB JSON body limit, health
  check endpoint, session and export routers, and static file serving
  for the built client
- Dual-bind to localhost and Tailscale IP (100.84.4.113) for local +
  tailnet access, with optional browser-open on startup via
  SESSION_VIEWER_OPEN_BROWSER env var
- Auto-start guard: only calls startServer() when run directly, not
  when imported by tests

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 22:56:10 -05:00
c4e15bf082 Add shared type definitions and sensitive content redactor
Shared module consumed by both the Express server and the React client:

types.ts:
- ParsedMessage: the normalized message unit (uuid, category, content,
  toolName, toolInput, timestamp, rawIndex) that the parser emits and
  every downstream consumer (viewer, filter, export) operates on
- MessageCategory: 9-value union covering user_message, assistant_text,
  thinking, tool_call, tool_result, system_message, hook_progress,
  file_snapshot, and summary
- SessionEntry / SessionListResponse / SessionDetailResponse / ExportRequest:
  API contract types for the sessions list, session detail, and HTML
  export endpoints
- ALL_CATEGORIES, CATEGORY_LABELS, DEFAULT_HIDDEN_CATEGORIES: constants
  for the filter panel UI and presets (thinking + hook_progress hidden
  by default)

sensitive-redactor.ts:
- 34 regex patterns derived from gitleaks production config, organized
  into Tier 1 (known secret formats: AWS, GitHub, GitLab, OpenAI,
  Anthropic, HuggingFace, Perplexity, Stripe, Slack, SendGrid, Twilio,
  GCP, Azure AD, Heroku, npm, PyPI, Sentry, JWT, PEM private keys,
  generic API key assignments) and Tier 2 (PII/system info: home
  directory paths, connection strings, URLs with credentials, email
  addresses, IPv4 addresses, Bearer tokens, env var secret assignments)
- Keyword pre-filtering: each pattern declares keywords that must appear
  in the text before the expensive regex is evaluated, following the
  gitleaks performance optimization approach
- False-positive allowlists: example/test email domains, localhost/
  documentation IPs (RFC 5737), noreply@anthropic.com
- Pure functions: redactSensitiveContent returns {sanitized, count,
  categories}, redactString returns just the string, redactMessage
  returns a new ParsedMessage with content and toolInput redacted

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 22:55:48 -05:00
7e15c36e2f Add project scaffolding and build configuration
Initialize the session-viewer project — a tool for browsing, filtering,
redacting, and exporting Claude Code session logs as self-contained HTML.

Scaffolding includes:
- package.json with Express server + React client dual-stack setup,
  dev/build/test/lint/typecheck scripts, and a CLI bin entry point
- TypeScript configs: base tsconfig.json (ESNext, bundler resolution,
  strict, react-jsx) and tsconfig.server.json extending it for the
  Express server compilation target
- Vite config: React plugin, Tailscale-aware dev server on :3847 with
  API proxy to :3848, client build output to dist/client
- Vitest config: node environment, test discovery from tests/unit and
  src/client/components
- ESLint flat config: typescript-eslint recommended, unused-vars with
  underscore exception
- Tailwind CSS config scoped to src/client, PostCSS with autoprefixer
- Playwright config: Chromium-only E2E against dev server
- bin/session-viewer.js: CLI entry point that re-execs via tsx with
  browser-open flag

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 22:55:31 -05:00