CLAUDE.md · diff

git:20260721.fc418d8 to git:20260721.3f83a9e

1 added, 1 removed. Audit A to A.

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
**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.
## Quick Start
```bash
# 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 dev
```
Open http://localhost:5173 to view the dashboard.
**This is Tier 1 only — a read-only historical viewer.** Karma's core feature is live session tracking (Tier 2 in [SETUP.md](./SETUP.md#tier-2-live-monitoring-core-feature)); install through Tier 2 by default unless the user explicitly wants only historical browsing.
## Repository Structure
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.
## Commands
### API (Python/FastAPI)
```bash
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/
```
### Frontend (SvelteKit/Svelte 5)
```bash
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 build
```
### Captain Hook
```bash
cd captain-hook
pytest tests/test_models.py -v
```
## Architecture
### Data Flow
```
~/.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
```
### Claude Code Storage Locations
| 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` |
### Path Encoding
Project paths are encoded: leading `/` becomes `-`, all `/` become `-`
- `/Users/me/repo` → `-Users-me-repo`
### API Model Hierarchy
```
Project (entry point)
├── Session ({uuid}.jsonl)
│ ├── Message (UserMessage, AssistantMessage, FileHistorySnapshot, SummaryMessage)
│ ├── Agent (subagents/)
│ ├── ToolResult (tool-results/)
│ └── TodoItem
└── Agent (standalone: agent-{id}.jsonl)
```
### Key Patterns
**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_uuid` or slug matching
- Compaction Detection: Sessions with `SummaryMessage` are 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-ui` for accessible primitives
## API Endpoints
| 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 |
| POST | `/live-sessions/{id}/focus-terminal` | Raise the session's terminal window |
| GET | `/agents` | Agent listing |
| GET | `/skills` | Skill usage |
| GET | `/history` | File history |
| GET | `/settings` | User preferences |
## Frontend Routes
| 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 |
## Captain Hook
Type-safe Pydantic models for Claude Code's 24 hook types (see `captain-hook/CLAUDE.md` for the full list). Karma's own hooks only use 8 of them:
| 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 |
```python
from captain_hook import parse_hook_event, PreToolUseHook
hook = parse_hook_event(json_data)
```
## Tech Stack
### Backend
- - **Python 3.9+**
+ - **Python 3.10+** (hook scripts alone run on 3.9+)
- **FastAPI** - Web framework
- **Pydantic 2.x** - Data validation
- **aiofiles** - Async file I/O
- **pytest** - Testing
- **ruff** - Linting/formatting
### Frontend
- **SvelteKit 2** with **adapter-node**
- **Svelte 5** with runes
- **Tailwind CSS 4**
- **Chart.js 4** - Visualizations
- **bits-ui** - UI primitives
- **lucide-svelte** - Icons
- **TypeScript**
## MCP Integration
Plane MCP tools for project management:
- `mcp__plane-project-task-manager__list_projects`
- `mcp__plane-project-task-manager__list_work_items`
- `mcp__plane-project-task-manager__retrieve_work_item`
- `mcp__plane-project-task-manager__update_work_item`
## Browser Automation
Use `agent-browser` CLI (Vercel) for browser automation instead of Playwright MCP. It's more token-efficient and optimized for LLM usage.
```bash
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 browser
```
Workflow: `open` → `snapshot -i` → interact via refs → re-snapshot after changes → `close`
## Development Workflow
1. **API changes**: Modify `api/models/` or `api/routers/`, run tests with `pytest`
2. **Frontend changes**: Modify `frontend/src/`, type-check with `npm run check`
3. **Hook changes**: Modify `captain-hook/`, test with `pytest tests/test_models.py`
4. **Commit changes**: All changes committed directly in this monorepo
## Known Claude Code Bugs
- `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.