# Claude Code Context Electron app that visualizes Claude Code session execution ## Tech Stack Electron 28.x, React 18.x, TypeScript 5.x, Tailwind CSS 3.x, Zustand 4.x ## Commands Always use pnpm (not npm/yarn) for this project. - `pnpm install` - Install dependencies - `pnpm dev` - Dev server with hot reload - `pnpm build` - Production build - `pnpm typecheck` - Type checking - `pnpm lint:fix` - Lint and auto-fix - `pnpm format` - Format code - `pnpm test` - Run all vitest tests - `pnpm test:watch` - Watch mode - `pnpm test:coverage` - Coverage report - `pnpm test:coverage:critical` - Critical path coverage - `pnpm test:chunks` - Chunk building tests - `pnpm test:semantic` - Semantic step extraction tests - `pnpm test:noise` - Noise filtering tests - `pnpm test:task-filtering` - Task tool filtering tests ## Path Aliases Use path aliases for imports: - `@main/*` → `src/main/*` - `@renderer/*` → `src/renderer/*` - `@shared/*` → `src/shared/*` - `@preload/*` → `src/preload/*` ## Data Sources ~/.claude/projects/{encoded-path}/*.jsonl - Session files ~/.claude/todos/{sessionId}.json - Todo data Path encoding: `/Users/name/project` → `-Users-name-project` ## Critical Concepts ### isMeta Flag - `isMeta: false` = Real user message (creates new chunks) - `isMeta: true` = Internal message (tool results, system-generated) ### Chunk Structure Independent chunk types for timeline visualization: - **UserChunk**: Single user message with metrics - **AIChunk**: All assistant responses with tool executions and spawned subagents - **SystemChunk**: Command output/system messages - **CompactChunk**: System metadata/structural messages Each chunk has: timestamp, duration, metrics (tokens, cost, tools) ### Task/Subagent Filtering Task tool_use blocks are filtered when subagent exists Keep orphaned Task calls (no matching subagent) for visibility. ### Agent Teams Claude Code's "Orchestrate Teams" feature: multiple sessions coordinate as a team. - **Process.team?** `{ teamName, memberName, memberColor }` — enriched by SubagentResolver from Task call inputs and `teammate_spawned` tool results - **Teammate messages** arrive as `content` in user messages (isMeta: false). Detected by `isParsedTeammateMessage()` — excluded from UserChunks, rendered as `TeammateMessageItem` cards - **Session ongoing detection** treats `SendMessage` shutdown_response (approve: true) and its tool_result as ending events, not ongoing activity - **Display summary** counts distinct teammates (by name) separately from regular subagents - **Team tools**: TeamCreate, TaskCreate, TaskUpdate, TaskList, TaskGet, SendMessage, TeamDelete — have readable summaries in `toolSummaryHelpers.ts` ### Visible Context Tracking Tracks what consumes tokens in Claude's context window across 6 categories (discriminated union on `category` field): | Category | Type | Source | |----------|------|--------| | `claude-md` | `ClaudeMdContextInjection` | CLAUDE.md files (global, project, directory) | | `mentioned-file` | `MentionedFileInjection` | User @-mentioned files | | `tool-output` | `ToolOutputInjection` | Tool execution results (Read, Bash, etc.) | | `thinking-text` | `ThinkingTextInjection` | Extended thinking + text output tokens | | `team-coordination` | `TeamCoordinationInjection` | Team tools (SendMessage, TaskCreate, etc.) | | `user-message` | `UserMessageInjection` | User prompt text per turn | - **Types**: `src/renderer/types/contextInjection.ts` — `ContextInjection` union, `ContextStats`, `TokensByCategory` - **Tracker**: `src/renderer/utils/contextTracker.ts` — `computeContextStats()`, `processSessionContextWithPhases()` - **Context Phases**: Compaction events reset accumulated injections, tracked via `ContextPhaseInfo` - **Display surfaces**: `ContextBadge` (per-turn popover), `TokenUsageDisplay` (hover breakdown), `SessionContextPanel` (full panel) ## Error Handling - Main: try/catch, console.error, return safe defaults - Renderer: error state in Zustand store - IPC: parameter validation, graceful degradation ## Performance - LRU Cache: Avoid re-parsing large JSONL files - Streaming JSONL: Line-by-line processing - Virtual Scrolling: For large session/message lists - Debounced File Watching: 100ms debounce ## Troubleshooting ### Build Issues ```bash rm -rf dist dist-electron node_modules pnpm install pnpm build ``` ### Type Errors ```bash pnpm typecheck ``` ### Test Failures Check for changes in message parsing or chunk building logic. ## TypeScript Conventions ### Naming | Category | Convention | Example | |----------|------------|---------| | Services/Components | PascalCase | `ProjectScanner.ts` | | Utilities | camelCase | `pathDecoder.ts` | | Constants | UPPER_SNAKE_CASE | `PARALLEL_WINDOW_MS` | | Type Guards | isXxx | `isRealUserMessage()` | | Builders | buildXxx | `buildChunks()` | | Getters | getXxx | `getResponses()` | ### Type Guards ```typescript // Message type guards (src/main/types/messages.ts) isParsedRealUserMessage(msg) // isMeta: false, string content isParsedInternalUserMessage(msg) // isMeta: true, array content isAssistantMessage(msg) // type: "assistant" // Chunk type guards isUserChunk(chunk) // type: "user" isAIChunk(chunk) // type: "ai" isSystemChunk(chunk) // type: "system" isCompactChunk(chunk) // type: "compact" // Context injection type guards (component-scoped in ContextBadge.tsx, not exported) isClaudeMdInjection(inj) // category: "claude-md" isMentionedFileInjection(inj) // category: "mentioned-file" isToolOutputInjection(inj) // category: "tool-output" isThinkingTextInjection(inj) // category: "thinking-text" isTeamCoordinationInjection(inj) // category: "team-coordination" isUserMessageInjection(inj) // category: "user-message" ``` ### Barrel Exports `src/main/services/` and its domain subdirectories have barrel exports via index.ts: ```typescript // Preferred import { ChunkBuilder, ProjectScanner } from './services'; // Also valid import { ChunkBuilder } from './services/analysis'; ``` Note: renderer utils/hooks/types do NOT have barrel exports — import directly from files. ### Import Order 1. External packages 2. Path aliases (@main, @renderer, @shared) 3. Relative imports