# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

peon-mcp is an MCP (Model Context Protocol) server for tracking software project tasks, features, and work logs in SQLite. It's designed for AI-agent-driven development workflows. Includes a Python backend (FastMCP + Starlette) and a React/TypeScript frontend.

## Common Commands

```bash
# Python dependencies
uv sync

# UI dependencies
cd ui && npm install

# Run the MCP server (stdio transport for Claude integration)
uv run python -m peon_mcp.server

# Run the web UI + REST API (http://127.0.0.1:8420)
uv run python -m peon_mcp.web

# Run UI dev server with hot reload (proxies /api to :8420)
cd ui && npm run dev

# Build UI (outputs to peon_mcp/static/)
cd ui && npm run build

# Build Python wheel
uv build

# Build + publish
./deploy.sh              # PyPI
./deploy.sh testpypi     # TestPyPI

# Run agent loop
peon-loop PROJECT_ID /path/to/repo [--once] [--model sonnet] [--timeout 1800]
```

## Architecture

**Three entry points** (defined in pyproject.toml):
- `peon-mcp` → `peon_mcp.server:main` — MCP server exposing 24 tools + 2 prompts via stdio
- `peon-ui` → `peon_mcp.web:main` — Starlette REST API + SPA serving on port 8420
- `peon-loop` → `peon_mcp.loop:main` — CLI that repeatedly spawns Claude to work through the task queue

**Backend (`peon_mcp/`)**:
- `server.py` — FastMCP server with `@mcp.tool()` decorated functions for CRUD on projects, features, tasks, and work logs. Key tools: `next_task()` (claims highest-priority todo task), `log_work()` (records completion). Two prompts: `start_work` and `execute_task`.
- `db.py` — SQLite schema init via aiosqlite. Tables: `projects`, `features`, `tasks`, `work_logs`, `loop_heartbeats`. DB location: `PEON_DB_PATH` env var or `~/.peon/peon_tasks.db`. Uses WAL mode and foreign keys.
- `web.py` — Starlette REST API mirroring MCP tools as HTTP endpoints under `/api/`. Includes `/api/projects/{id}/stats` for dashboard aggregation. Falls back to serving `static/index.html` for SPA routing.
- `loop.py` — Agent loop: checks for todo tasks → spawns `claude` CLI with MCP config → writes heartbeat to DB → sleeps → repeats. Logs to `.peon-logs/`. Handles SIGINT for graceful cleanup.

**Frontend (`ui/`)**:
- React 19 + React Router v7 + Tailwind CSS v4 + Vite 6 + TypeScript 5.7
- `api.ts` — Typed fetch wrapper for all REST endpoints
- `types.ts` — Shared interfaces (Project, Feature, Task, WorkLog, SystemInfo)
- Routes: `/` (project list), `/projects/:id` (dashboard), `/projects/:id/features`, `/projects/:id/tasks`, `/projects/:id/logs`
- Built assets output to `peon_mcp/static/` and are included in the Python wheel
- Vite dev server proxies `/api` to `http://127.0.0.1:8420`

## Data Model

- **Projects** have features, tasks, and work logs (FK relationships)
- **Tasks** have priority (critical > high > medium > low) and status (todo → in_progress → done/cancelled)
- **Tasks** track `commit_base` and `commit_head` git SHAs for audit trails
- **Work logs** record summary, files_changed, and test_result (pass/fail/skip)
- `next_task()` returns highest-priority oldest todo task

## Environment Variables

| Variable | Default | Purpose |
|---|---|---|
| `PEON_DB_PATH` | `~/.peon/peon_tasks.db` | SQLite database path |
| `PEON_UI_HOST` | `127.0.0.1` | Web UI bind address |
| `PEON_UI_PORT` | `8420` | Web UI port (auto-fallback if taken) |

## Key Patterns

- All DB access is async via aiosqlite; MCP server maintains one connection via `app_lifespan` context manager
- Adding an MCP tool: add `@mcp.tool()` function in `server.py`
- Adding a REST endpoint: add route handler in `web.py` and register in `routes` list
- Adding a UI page: create component in `ui/src/components/`, add route in `App.tsx`, add nav item in `Sidebar.tsx`
- Schema changes in `db.py` require recreating the database (no migrations)
- The UI uses a dark Warcraft-inspired theme with green accent colors
