This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Claude Code Karma is a full-stack application for monitoring and analyzing Claude Code sessions. It parses Claude Code's local storage (~/.claude/) and visualizes session data through a web dashboard.
# Clone (no submodule init needed — this is a monorepo)
git clone https://github.com/JayantDevkar/claude-code-karma.git
cd claude-code-karma
# Start API (terminal 1)
cd api
pip install -e ".[dev]" && pip install -r requirements.txt
uvicorn main:app --reload --port 8000
# Start frontend (terminal 2)
cd frontend
npm install && npm run devOpen http://localhost:5173 to view the dashboard.
This is a monorepo with all components in a single repository:
claude-code-karma/
├── api/ # FastAPI backend (Python) - port 8000
├── frontend/ # SvelteKit frontend (Svelte 5) - port 5173
├── captain-hook/ # Claude Code hooks Pydantic library
└── hooks/ # Hook scripts (symlinked from ~/.claude/hooks/)
├── live_session_tracker.py # Tracks live session state across hook events
├── session_title_generator.py # Generates session titles via Haiku on SessionEnd
└── plan_approval.py # Handles ExitPlanMode permission requests
Each directory has its own CLAUDE.md with module-specific guidance.
cd api
# Run server
uvicorn main:app --reload --port 8000
# Run all tests
pytest
# Run specific test file
pytest tests/test_session.py -v
# Run API endpoint tests
pytest tests/api/ -v
# Run with coverage
pytest --cov=models --cov=routers
# Lint & format
ruff check models/ tests/ routers/
ruff format models/ tests/ routers/cd frontend
npm install # Install dependencies
npm run dev # Dev server (port 5173)
npm run check # Type check
npm run lint # Lint
npm run format # Format
npm run build # Production buildcd captain-hook
pytest tests/test_models.py -v~/.claude/projects/{encoded-path}/{uuid}.jsonl
↓
API (models/ parses JSONL → Pydantic models)
↓
FastAPI endpoints (routers/) on port 8000
↓
SvelteKit frontend (src/routes/) on port 5173
| Data | Location |
|---|---|
| Session JSONL | ~/.claude/projects/{encoded-path}/{uuid}.jsonl |
| Subagents | ~/.claude/projects/{encoded-path}/{uuid}/subagents/agent-*.jsonl |
| Tool Results | ~/.claude/projects/{encoded-path}/{uuid}/tool-results/toolu_*.txt |
| Debug Logs | ~/.claude/debug/{uuid}.txt |
| Todos | ~/.claude/todos/{uuid}-*.json |
| Live Sessions | ~/.claude_karma/live-sessions/{slug}.json |
Project paths are encoded: leading / becomes -, all / become -
/Users/me/repo→-Users-me-repo
Project (entry point)
├── Session ({uuid}.jsonl)
│ ├── Message (UserMessage, AssistantMessage, FileHistorySnapshot, SummaryMessage)
│ ├── Agent (subagents/)
│ ├── ToolResult (tool-results/)
│ └── TodoItem
└── Agent (standalone: agent-{id}.jsonl)
API:
- Lazy Loading: Messages loaded via
iter_messages()for large sessions - Frozen Models: All Pydantic models use
ConfigDict(frozen=True) - Session Chains: Related sessions detected via
leaf_uuidor slug matching - Compaction Detection: Sessions with
SummaryMessageare compacted
Frontend:
- Svelte 5 Runes:
$state(),$derived(),$effect(),$props() - URL State: Filters persisted via URL search params
- Design Tokens: CSS custom properties in
app.css - Component Library:
bits-uifor accessible primitives
| Method | Endpoint | Description |
|---|---|---|
| GET | /projects |
List all projects |
| GET | /projects/{encoded_name} |
Project details with sessions |
| GET | /sessions/{uuid} |
Session details |
| GET | /sessions/{uuid}/timeline |
Event timeline |
| GET | /sessions/{uuid}/tools |
Tool usage |
| GET | /sessions/{uuid}/file-activity |
File operations |
| GET | /sessions/{uuid}/subagents |
Subagent activity |
| GET | /analytics/projects/{encoded_name} |
Project analytics |
| GET | /live-sessions |
Real-time session state |
| GET | /agents |
Agent listing |
| GET | /skills |
Skill usage |
| GET | /history |
File history |
| GET | /settings |
User preferences |
| Route | Description |
|---|---|
/ |
Home page |
/projects |
Project listing |
/projects/[encoded_name] |
Project detail |
/projects/[encoded_name]/agents |
Project agents |
/projects/[encoded_name]/skills |
Project skills |
/agents |
Global agents view |
/analytics |
Global analytics |
/history |
File history |
/hooks |
Hooks browser |
/plugins |
Plugins browser |
/tools |
Tools browser |
/sessions |
Global sessions browser |
/archived |
Archived sessions |
/about |
About page |
/settings |
User settings |
/skills |
Global skills view |
Type-safe Pydantic models for Claude Code's 10 hook types:
| Hook | Fires | Can Block? |
|---|---|---|
| PreToolUse | Before tool | Yes |
| PostToolUse | After tool | No |
| UserPromptSubmit | User message | Yes |
| SessionStart/End | Session lifecycle | No |
| Stop/SubagentStop | Agent completion | No |
| PreCompact | Context compaction | No |
| PermissionRequest | Permission dialog | Yes |
| Notification | System notification | No |
from captain_hook import parse_hook_event, PreToolUseHook
hook = parse_hook_event(json_data)- Python 3.9+
- FastAPI - Web framework
- Pydantic 2.x - Data validation
- aiofiles - Async file I/O
- pytest - Testing
- ruff - Linting/formatting
- SvelteKit 2 with adapter-node
- Svelte 5 with runes
- Tailwind CSS 4
- Chart.js 4 - Visualizations
- bits-ui - UI primitives
- lucide-svelte - Icons
- TypeScript
Plane MCP tools for project management:
mcp__plane-project-task-manager__list_projectsmcp__plane-project-task-manager__list_work_itemsmcp__plane-project-task-manager__retrieve_work_itemmcp__plane-project-task-manager__update_work_item
Use agent-browser CLI (Vercel) for browser automation instead of Playwright MCP. It's more token-efficient and optimized for LLM usage.
agent-browser open <url> # Navigate to page
agent-browser snapshot -i # Get interactive elements with refs (@e1, @e2)
agent-browser click @e1 # Click element by ref
agent-browser fill @e2 "text" # Fill input field
agent-browser close # Close browserWorkflow: open → snapshot -i → interact via refs → re-snapshot after changes → close
- API changes: Modify
api/models/orapi/routers/, run tests withpytest - Frontend changes: Modify
frontend/src/, type-check withnpm run check - Hook changes: Modify
captain-hook/, test withpytest tests/test_models.py - Commit changes: All changes committed directly in this monorepo
classifyHandoffIfNeeded is not defined— open bug in Claude Code. Task agents (subagents) may fail with this runtime error. Ignore it and proceed; the work is typically completed before the failure. Don't retry agents solely because of this error.