6.2 KiB
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 dependenciespnpm dev- Dev server with hot reloadpnpm build- Production buildpnpm typecheck- Type checkingpnpm lint:fix- Lint and auto-fixpnpm format- Format codepnpm test- Run all vitest testspnpm test:watch- Watch modepnpm test:coverage- Coverage reportpnpm test:coverage:critical- Critical path coveragepnpm test:chunks- Chunk building testspnpm test:semantic- Semantic step extraction testspnpm test:noise- Noise filtering testspnpm 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 andteammate_spawnedtool results - Teammate messages arrive as
<teammate-message teammate_id="..." color="..." summary="...">content</teammate-message>in user messages (isMeta: false). Detected byisParsedTeammateMessage()— excluded from UserChunks, rendered asTeammateMessageItemcards - Session ongoing detection treats
SendMessageshutdown_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—ContextInjectionunion,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
rm -rf dist dist-electron node_modules
pnpm install
pnpm build
Type Errors
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
// 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:
// 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
- External packages
- Path aliases (@main, @renderer, @shared)
- Relative imports