From 50c80596d0e2038add22ae2c917396a37938df8d Mon Sep 17 00:00:00 2001 From: Ryan Malloy Date: Mon, 11 Aug 2025 08:02:09 -0600 Subject: [PATCH] Add comprehensive Docker deployment and file upload functionality MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Features Added: • Docker containerization with multi-stage Python 3.12 build • Caddy reverse proxy integration with automatic SSL • File upload interface for .claude.json imports with preview • Comprehensive hook system with 39+ hook types across 9 categories • Complete documentation system with Docker and import guides Technical Improvements: • Enhanced database models with hook tracking capabilities • Robust file validation and error handling for uploads • Production-ready Docker compose configuration • Health checks and resource limits for containers • Database initialization scripts for containerized deployments Documentation: • Docker Deployment Guide with troubleshooting • Data Import Guide with step-by-step instructions • Updated Getting Started guide with new features • Enhanced documentation index with responsive grid layout 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .dockerignore | 87 +++ .env.example | 34 +- DOCKER.md | 345 ++++++++++ Dockerfile | 53 ++ README.md | 214 +++--- app/api/hooks.py | 619 ++++++++++++++++++ app/api/importer.py | 140 +++- app/dashboard/routes.py | 12 + app/dashboard/static/claude-hooks-basic.json | 9 + .../static/claude-hooks-comprehensive.json | 50 ++ .../static/claude-hooks-developer.json | 25 + .../static/claude-hooks-essential.json | 16 + .../static/claude-hooks-power_user.json | 30 + .../static/claude-hooks-research.json | 29 + app/dashboard/static/claude-hooks-team.json | 29 + app/dashboard/templates/docs/data-import.html | 562 ++++++++++++++++ .../templates/docs/docker-deployment.html | 415 ++++++++++++ .../templates/docs/getting-started.html | 15 +- .../templates/docs/hook-reference.html | 531 +++++++++++++++ app/dashboard/templates/docs/index.html | 91 ++- app/dashboard/templates/import.html | 240 ++++++- app/database/connection.py | 9 +- app/models/__init__.py | 15 + app/models/hooks.py | 225 +++++++ claude-hooks-basic.json | 9 + claude-hooks-comprehensive.json | 50 ++ claude-hooks-developer.json | 25 + claude-hooks-essential.json | 16 + claude-hooks-power_user.json | 30 + claude-hooks-research.json | 29 + claude-hooks-team.json | 29 + docker-compose.yml | 53 ++ docker-deploy.sh | 123 ++++ generate_hook_config.py | 281 ++++++++ init_db.py | 49 ++ main.py | 17 +- 36 files changed, 4334 insertions(+), 172 deletions(-) create mode 100644 .dockerignore create mode 100644 DOCKER.md create mode 100644 Dockerfile create mode 100644 app/api/hooks.py create mode 100644 app/dashboard/static/claude-hooks-basic.json create mode 100644 app/dashboard/static/claude-hooks-comprehensive.json create mode 100644 app/dashboard/static/claude-hooks-developer.json create mode 100644 app/dashboard/static/claude-hooks-essential.json create mode 100644 app/dashboard/static/claude-hooks-power_user.json create mode 100644 app/dashboard/static/claude-hooks-research.json create mode 100644 app/dashboard/static/claude-hooks-team.json create mode 100644 app/dashboard/templates/docs/data-import.html create mode 100644 app/dashboard/templates/docs/docker-deployment.html create mode 100644 app/dashboard/templates/docs/hook-reference.html create mode 100644 app/models/hooks.py create mode 100644 claude-hooks-basic.json create mode 100644 claude-hooks-comprehensive.json create mode 100644 claude-hooks-developer.json create mode 100644 claude-hooks-essential.json create mode 100644 claude-hooks-power_user.json create mode 100644 claude-hooks-research.json create mode 100644 claude-hooks-team.json create mode 100644 docker-compose.yml create mode 100755 docker-deploy.sh create mode 100644 generate_hook_config.py create mode 100644 init_db.py diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..a06a445 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,87 @@ +# Python cache and build artifacts +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg + +# Virtual environments +.venv/ +venv/ +ENV/ +env/ + +# IDE and editor files +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# OS generated files +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db + +# Git +.git/ +.gitignore + +# Docker +Dockerfile* +docker-compose* +.dockerignore + +# Database files (will be created in volume) +*.db +*.sqlite +*.sqlite3 + +# Logs +*.log +logs/ + +# Environment files (handled separately) +.env* + +# Temporary files +tmp/ +temp/ +.tmp/ + +# Hook configuration files (generated) +claude-hooks-*.json + +# Cache +.cache/ +.pytest_cache/ + +# Coverage reports +htmlcov/ +.coverage +.coverage.* + +# Node modules (if any) +node_modules/ + +# Documentation build +docs/_build/ \ No newline at end of file diff --git a/.env.example b/.env.example index 5a8aa25..db16268 100644 --- a/.env.example +++ b/.env.example @@ -1,10 +1,18 @@ -# Database -DATABASE_URL=sqlite+aiosqlite:///./data/tracker.db +# Claude Code Tracker Configuration -# API Configuration +# Domain configuration for Caddy reverse proxy +DOMAIN=claude.l.supported.systems + +# Database configuration +DATABASE_URL=sqlite+aiosqlite:///app/data/tracker.db + +# Application settings +DEBUG=false API_HOST=0.0.0.0 API_PORT=8000 -DEBUG=true + +# Data storage path (host directory to bind mount) +DATA_PATH=./data # Security (generate with: openssl rand -hex 32) SECRET_KEY=your-secret-key-here @@ -16,4 +24,20 @@ ANALYTICS_BATCH_SIZE=1000 # Logging LOG_LEVEL=INFO -LOG_FILE=tracker.log \ No newline at end of file +LOG_FILE=tracker.log + +# Optional: Rate limiting settings +# RATE_LIMIT_ENABLED=true +# RATE_LIMIT_PER_MINUTE=100 + +# Optional: Performance settings +# MAX_WORKERS=4 +# TIMEOUT_SECONDS=60 + +# Optional: Hook settings +# DEFAULT_HOOK_TIMEOUT=10 +# MAX_HOOK_RETRIES=3 + +# Optional: Analytics retention +# ANALYTICS_RETENTION_DAYS=365 +# ENABLE_ANONYMOUS_ANALYTICS=false \ No newline at end of file diff --git a/DOCKER.md b/DOCKER.md new file mode 100644 index 0000000..6fd0b4b --- /dev/null +++ b/DOCKER.md @@ -0,0 +1,345 @@ +# Claude Code Tracker - Docker Deployment + +This guide covers deploying Claude Code Tracker using Docker with Caddy reverse proxy integration. + +## Quick Start + +1. **Clone and configure:** + ```bash + git clone + cd claude-tracker + cp .env.example .env + # Edit .env file to set your domain + ``` + +2. **Deploy with one command:** + ```bash + ./docker-deploy.sh + ``` + +3. **Access your instance:** + - Dashboard: `https://claude.l.supported.systems/dashboard` + - API Docs: `https://claude.l.supported.systems/docs` + +## Prerequisites + +### Required +- Docker Engine 20.10+ +- Docker Compose 2.0+ +- Caddy server with docker-proxy plugin running + +### Caddy Network Setup +The deployment expects an external Docker network named `caddy`: + +```bash +# Create the network if it doesn't exist +docker network create caddy +``` + +### Caddy Server +Ensure Caddy is running with the docker-proxy plugin: + +```bash +# Example Caddy docker-compose.yml +version: '3.8' +services: + caddy: + image: lucaslorentz/caddy-docker-proxy:ci-alpine + ports: + - "80:80" + - "443:443" + environment: + - CADDY_INGRESS_NETWORKS=caddy + networks: + - caddy + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - caddy_data:/data + restart: unless-stopped +``` + +## Configuration + +### Environment Variables + +The `.env` file configures the deployment: + +```bash +# Domain for Caddy reverse proxy +DOMAIN=claude.l.supported.systems + +# Database path (inside container) +DATABASE_URL=sqlite+aiosqlite:///app/data/tracker.db + +# Application settings +DEBUG=false +API_HOST=0.0.0.0 +API_PORT=8000 + +# Data directory path (host) +DATA_PATH=./data +``` + +### Caddy Labels + +The `docker-compose.yml` includes comprehensive Caddy configuration: + +- **Reverse Proxy:** Automatic routing to the container +- **SSL/TLS:** Automatic certificate management +- **Security Headers:** XSS protection, content type sniffing prevention +- **CORS Headers:** API cross-origin support +- **Compression:** Gzip encoding for better performance +- **Caching:** Static asset caching + +## Deployment Options + +### Option 1: Automated Deployment (Recommended) +```bash +./docker-deploy.sh +``` + +### Option 2: Manual Deployment +```bash +# Create network if needed +docker network create caddy + +# Build and start +docker-compose up -d --build + +# Check status +docker-compose ps +``` + +### Option 3: Development Mode +```bash +# Start with logs +docker-compose up --build + +# Rebuild after changes +docker-compose up --build --force-recreate +``` + +## Data Persistence + +### Database Storage +- **Host Path:** `./data/` (configurable via `DATA_PATH`) +- **Container Path:** `/app/data/` +- **Database File:** `tracker.db` + +### Volume Management +```bash +# Backup database +cp ./data/tracker.db ./backups/tracker-$(date +%Y%m%d).db + +# Restore database +cp ./backups/tracker-20240115.db ./data/tracker.db +docker-compose restart claude-tracker +``` + +## Management Commands + +### Service Management +```bash +# View logs +docker-compose logs -f claude-tracker + +# Restart service +docker-compose restart claude-tracker + +# Stop service +docker-compose down + +# Update and restart +docker-compose pull && docker-compose up -d +``` + +### Container Access +```bash +# Shell access +docker-compose exec claude-tracker /bin/bash + +# Run commands in container +docker-compose exec claude-tracker uv run python recalculate_project_stats.py + +# View container stats +docker stats claude-tracker-api +``` + +### Health Monitoring +```bash +# Check health +curl http://localhost:8000/health + +# Container status +docker-compose ps + +# Resource usage +docker-compose exec claude-tracker cat /proc/meminfo +``` + +## Troubleshooting + +### Common Issues + +#### 1. Container Won't Start +```bash +# Check logs +docker-compose logs claude-tracker + +# Common causes: +# - Port 8000 already in use +# - Database permission issues +# - Missing environment variables +``` + +#### 2. Database Errors +```bash +# Check database permissions +ls -la ./data/ + +# Recreate database +rm ./data/tracker.db +docker-compose restart claude-tracker +``` + +#### 3. Caddy Connection Issues +```bash +# Verify Caddy network +docker network ls | grep caddy + +# Check Caddy logs +docker logs caddy + +# Verify labels +docker inspect claude-tracker-api | grep -A 10 Labels +``` + +#### 4. Performance Issues +```bash +# Monitor resources +docker stats claude-tracker-api + +# Increase memory limits in docker-compose.yml +``` + +### Health Checks + +The container includes built-in health checks: + +```bash +# Container health status +docker-compose ps + +# Manual health check +curl -f http://localhost:8000/health + +# Detailed health info +docker inspect --format='{{json .State.Health}}' claude-tracker-api +``` + +## Security Considerations + +### Network Security +- Container only exposes port 8000 internally to Docker network +- External access only through Caddy reverse proxy +- Automatic HTTPS with Let's Encrypt + +### Data Security +- Database stored in dedicated Docker volume +- No sensitive data in container images +- Environment variables for configuration + +### Resource Limits +- Memory limit: 512MB (configurable) +- CPU limit: 1.0 core (configurable) +- Automatic restart on failure + +## Production Recommendations + +### Performance +1. **Use bind mounts for data persistence** +2. **Configure resource limits appropriately** +3. **Monitor container health and logs** +4. **Regular database backups** + +### Security +1. **Use specific image tags (not `latest`)** +2. **Regular security updates** +3. **Network isolation** +4. **Secret management for sensitive data** + +### Monitoring +1. **Set up log aggregation** +2. **Configure health check alerts** +3. **Monitor resource usage** +4. **Database backup automation** + +## Advanced Configuration + +### Custom Caddy Labels +Add additional Caddy configuration in `docker-compose.yml`: + +```yaml +labels: + # Rate limiting + caddy.rate_limit: "100r/m" + + # Basic auth for admin endpoints + caddy.basicauth./admin/*: "admin $2a$14$..." + + # IP restrictions + caddy.@internal: "remote_ip 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16" + caddy.authorize.@internal: "" +``` + +### Multi-Environment Setup +Create environment-specific compose files: + +```bash +# Production +docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d + +# Development +docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d +``` + +## Updating + +### Application Updates +```bash +# Pull latest changes +git pull + +# Rebuild and restart +docker-compose up -d --build + +# Check health +curl https://claude.l.supported.systems/health +``` + +### Database Migrations +```bash +# Backup first +cp ./data/tracker.db ./data/tracker.backup.db + +# Run migration (if needed) +docker-compose exec claude-tracker uv run python migrate.py + +# Verify +docker-compose logs claude-tracker +``` + +## Support + +For issues related to: +- **Docker deployment:** Check this documentation +- **Caddy configuration:** Refer to Caddy documentation +- **Application features:** See main README.md +- **API usage:** Visit `/docs` endpoint + +## Links + +- **Dashboard:** `https://your-domain/dashboard` +- **API Documentation:** `https://your-domain/docs` +- **Hook Reference:** `https://your-domain/dashboard/docs/hook-reference` +- **Health Check:** `https://your-domain/health` \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..d39e618 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,53 @@ +# Use Python 3.12 slim image +FROM python:3.12-slim + +# Set environment variables +ENV PYTHONDONTWRITEBYTECODE=1 \ + PYTHONUNBUFFERED=1 \ + UV_CACHE_DIR=/tmp/uv-cache + +# Install system dependencies +RUN apt-get update && apt-get install -y \ + curl \ + git \ + build-essential \ + && rm -rf /var/lib/apt/lists/* + +# Install uv +COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv + +# Create app directory +WORKDIR /app + +# Copy dependency files and README first for better caching +COPY pyproject.toml uv.lock README.md ./ + +# Install dependencies +RUN uv sync --frozen --no-cache --no-dev + +# Copy application code +COPY . . + +# Create data directory for SQLite database with proper permissions +RUN mkdir -p /app/data && chmod 777 /app/data + +# Expose port +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \ + CMD curl -f http://localhost:8000/health || exit 1 + +# Copy initialization script +COPY init_db.py ./ + +# Create startup script +RUN echo '#!/bin/bash\n\ +echo "Ensuring database is initialized..."\n\ +/app/.venv/bin/python init_db.py\n\ +echo "Starting application..."\n\ +exec /app/.venv/bin/python -m uvicorn main:app --host 0.0.0.0 --port 8000' > start.sh && \ +chmod +x start.sh + +# Run the application +CMD ["./start.sh"] \ No newline at end of file diff --git a/README.md b/README.md index 891e496..3678d07 100644 --- a/README.md +++ b/README.md @@ -1,146 +1,116 @@ -# Claude Code Project Tracker +# Claude Code Hook Configurations -A comprehensive development intelligence system that tracks your Claude Code sessions, providing insights into your coding patterns, productivity, and learning journey. +This directory contains various pre-configured hook setups for different use cases: -## Overview +## Available Configurations -The Claude Code Project Tracker automatically captures your development workflow through Claude Code's hook system, creating a detailed record of: +### basic.json +Essential hooks for basic session and tool tracking. +- Session management +- Tool calls +- File modifications +- Conversations -- **Development Sessions** - When you start/stop working, what projects you focus on -- **Conversations** - Full dialogue history with Claude for context and learning analysis -- **Code Changes** - File modifications, tool usage, and command executions -- **Thinking Patterns** - Wait times between interactions to understand your workflow -- **Git Activity** - Repository changes, commits, and branch operations -- **Productivity Metrics** - Engagement levels, output quality, and learning velocity +### comprehensive.json +Complete hook setup with all available hook types. +- All performance monitoring +- Code quality tracking +- Learning analytics +- Collaboration insights +- Project intelligence -## Architecture +### essential.json +Minimal setup for core functionality. -``` -┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ -│ Claude Code │───▶│ Hook System │───▶│ FastAPI Server │ -│ (your IDE) │ │ │ │ │ -└─────────────────┘ └─────────────────┘ └─────────────────┘ - │ - ▼ -┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ -│ Web Dashboard │◀───│ Analytics │◀───│ SQLite Database │ -│ │ │ Engine │ │ │ -└─────────────────┘ └─────────────────┘ └─────────────────┘ -``` +### developer.json +Focused on development workflow and code quality. +- Essential hooks +- Performance monitoring +- Code quality checks -### Components +### power_user.json +Advanced setup for productivity optimization. +- Essential hooks +- Performance tracking +- Workflow analysis +- Project intelligence -- **FastAPI Server**: REST API that receives hook data and serves analytics -- **SQLite Database**: Local storage for all tracking data -- **Hook Integration**: Claude Code hooks that capture development events -- **Analytics Engine**: Processes raw data into meaningful insights -- **Web Dashboard**: Interactive interface for exploring your development patterns +### research.json +Optimized for learning and exploration. +- Essential hooks +- Learning tracking +- External resource usage +- Knowledge gap analysis -## Key Features +### team.json +Team-focused configuration for collaboration. +- Essential hooks +- Collaboration tracking +- Testing workflows +- Project intelligence -### 🎯 Session Tracking -- Automatic project detection and session management -- Working directory and git branch context -- Session duration and engagement analysis +## Installation -### 💬 Conversation Intelligence -- Full dialogue history with semantic search -- Problem-solving pattern recognition -- Learning topic identification and progress tracking +1. Choose the configuration that matches your needs +2. Copy the JSON content to your Claude Code settings file: + - macOS/Linux: `~/.config/claude/settings.json` + - Windows: `%APPDATA%\claude\settings.json` +3. Ensure Claude Code Tracker is running on port 8000 +4. Start using Claude Code - hooks will automatically track your activity! -### 📊 Development Analytics -- Productivity metrics and engagement scoring -- Tool usage patterns and optimization insights -- Cross-project learning and code reuse analysis +## Available Hook Variables -### 🔍 Advanced Insights -- Think time analysis and flow state detection -- Git activity correlation with conversations -- Skill development velocity tracking -- Workflow optimization recommendations +Each hook can use these variables that Claude Code provides: -## Data Privacy +### Session Variables +- `$SESSION_ID` - Current session identifier +- `$TIMESTAMP` - Current timestamp (ISO format) +- `$PWD` - Current working directory +- `$USER` - System username -- **Local-First**: All data stays on your machine -- **No External Services**: No data transmission to third parties -- **Full Control**: Complete ownership of your development history -- **Selective Tracking**: Configurable hook activation per project +### Tool Variables +- `$TOOL_NAME` - Name of tool being called +- `$TOOL_PARAMS` - Tool parameters (JSON) +- `$RESULT_STATUS` - Success/error status +- `$EXECUTION_TIME` - Tool execution time (ms) +- `$ERROR_TYPE` - Type of error +- `$ERROR_MESSAGE` - Error message +- `$STACK_TRACE` - Error stack trace -## Quick Start +### File Variables +- `$FILE_PATH` - Path to modified file +- `$ACTION` - File action (created/modified/deleted) +- `$FILE_SIZE_MB` - File size in megabytes -1. **Install Dependencies** - ```bash - pip install -r requirements.txt - ``` +### Context Variables +- `$CONTENT` - Conversation content +- `$CONTEXT` - Current context description +- `$SEARCH_QUERY` - What you're searching for +- `$NEW_PROJECT` - Project being switched to +- `$OLD_PROJECT` - Project being switched from -2. **Start the Tracking Server** - ```bash - python main.py - ``` +### Performance Variables +- `$MEMORY_MB` - Memory usage in MB +- `$DURATION_MS` - Duration in milliseconds +- `$THRESHOLD_EXCEEDED` - Boolean for threshold alerts -3. **Configure Claude Code Hooks** - ```bash - # Add hooks to your Claude Code settings - cp config/claude-hooks.json ~/.config/claude-code/ - ``` +And many more! Each hook type has specific variables available. -4. **Access Dashboard** - ``` - Open http://localhost:8000 in your browser - ``` +## Customization -## Project Structure +You can modify any configuration by: +1. Adding/removing specific hooks +2. Changing API endpoints or ports +3. Adjusting timeout and retry settings +4. Adding custom metadata to hook calls -``` -claude-tracker/ -├── README.md # This file -├── requirements.txt # Python dependencies -├── main.py # FastAPI application entry point -├── config/ # Configuration files -│ └── claude-hooks.json # Hook setup for Claude Code -├── app/ # Application code -│ ├── models/ # Database models -│ ├── api/ # API endpoints -│ ├── analytics/ # Insights engine -│ └── dashboard/ # Web interface -├── tests/ # Test suite -├── docs/ # Detailed documentation -└── data/ # SQLite database location -``` +## Troubleshooting -## Documentation +If hooks aren't working: +1. Ensure Claude Code Tracker server is running +2. Check that curl is installed +3. Verify the API endpoints are accessible +4. Check Claude Code logs for hook execution errors +5. Test individual hooks manually with curl -- [API Specification](docs/api-spec.yaml) - Complete endpoint documentation -- [Database Schema](docs/database-schema.md) - Data model details -- [Hook Setup Guide](docs/hook-setup.md) - Claude Code integration -- [Development Guide](docs/development.md) - Local setup and contribution -- [Analytics Guide](docs/analytics.md) - Understanding insights and metrics - -## Development - -See [Development Guide](docs/development.md) for detailed setup instructions. - -```bash -# Install development dependencies -pip install -r requirements-dev.txt - -# Run tests -pytest - -# Start development server with hot reload -uvicorn main:app --reload - -# Generate API documentation -python -m app.generate_docs -``` - -## Contributing - -This project follows test-driven development. Please ensure: -1. All new features have comprehensive tests -2. Documentation is updated for API changes -3. Analytics insights are validated with test data - -## License - -MIT License - See LICENSE file for details \ No newline at end of file +For more help, see the documentation at `/dashboard/docs/hook-setup`. diff --git a/app/api/hooks.py b/app/api/hooks.py new file mode 100644 index 0000000..7018e39 --- /dev/null +++ b/app/api/hooks.py @@ -0,0 +1,619 @@ +""" +Comprehensive hook tracking API endpoints. +""" + +import json +from datetime import datetime +from typing import List, Optional, Dict, Any +from fastapi import APIRouter, Depends, HTTPException, status +from sqlalchemy.ext.asyncio import AsyncSession +from sqlalchemy import select, func, desc, and_ +from sqlalchemy.orm import selectinload +from pydantic import BaseModel, Field + +from app.database.connection import get_db +from app.models.session import Session +from app.models.hooks import ( + HookEvent, ToolError, WaitingPeriodNew, PerformanceMetric, + CodeQualityEvent, WorkflowEvent, LearningEvent, + EnvironmentEvent, CollaborationEvent, ProjectIntelligence +) + +router = APIRouter() + + +# Request/Response Models +class BaseHookRequest(BaseModel): + """Base request schema for hook events.""" + session_id: Optional[str] = Field(None, description="Session ID (auto-detected if not provided)") + timestamp: Optional[datetime] = Field(None, description="Event timestamp") + + +class ToolErrorRequest(BaseHookRequest): + """Request schema for tool error events.""" + tool_name: str + error_type: str + error_message: str + stack_trace: Optional[str] = None + parameters: Optional[dict] = None + + +class WaitingPeriodRequest(BaseHookRequest): + """Request schema for waiting period events.""" + reason: Optional[str] = Field("thinking", description="Reason for waiting") + context: Optional[str] = None + duration_ms: Optional[int] = None + end_time: Optional[datetime] = None + + +class PerformanceMetricRequest(BaseHookRequest): + """Request schema for performance metrics.""" + metric_type: str = Field(..., description="Type of metric: memory, cpu, disk") + value: float + unit: str = Field(..., description="Unit: MB, %, seconds, etc.") + threshold_exceeded: bool = False + + +class CodeQualityRequest(BaseHookRequest): + """Request schema for code quality events.""" + event_type: str = Field(..., description="lint, format, test, build, analysis") + file_path: Optional[str] = None + tool_name: Optional[str] = None + status: str = Field(..., description="success, warning, error") + issues_count: int = 0 + details: Optional[dict] = None + duration_ms: Optional[int] = None + + +class WorkflowRequest(BaseHookRequest): + """Request schema for workflow events.""" + event_type: str = Field(..., description="context_switch, search_query, browser_tab, etc.") + description: Optional[str] = None + metadata: Optional[dict] = None + source: Optional[str] = None + duration_ms: Optional[int] = None + + +class LearningRequest(BaseHookRequest): + """Request schema for learning events.""" + event_type: str = Field(..., description="tutorial, documentation, experimentation") + topic: Optional[str] = None + resource_url: Optional[str] = None + confidence_before: Optional[int] = Field(None, ge=1, le=10) + confidence_after: Optional[int] = Field(None, ge=1, le=10) + notes: Optional[str] = None + duration_ms: Optional[int] = None + + +class EnvironmentRequest(BaseHookRequest): + """Request schema for environment events.""" + event_type: str = Field(..., description="env_change, config_update, security_scan") + environment: Optional[str] = None + config_file: Optional[str] = None + changes: Optional[dict] = None + impact_level: Optional[str] = Field(None, description="low, medium, high, critical") + + +class CollaborationRequest(BaseHookRequest): + """Request schema for collaboration events.""" + event_type: str = Field(..., description="external_resource, ai_question, review_request") + interaction_type: Optional[str] = None + query_or_topic: Optional[str] = None + resource_url: Optional[str] = None + response_quality: Optional[int] = Field(None, ge=1, le=5) + time_to_resolution: Optional[int] = None + metadata: Optional[dict] = None + + +class ProjectIntelligenceRequest(BaseHookRequest): + """Request schema for project intelligence events.""" + event_type: str = Field(..., description="refactor, feature_flag, debugging_session") + scope: Optional[str] = Field(None, description="small, medium, large") + complexity: Optional[str] = Field(None, description="low, medium, high") + end_time: Optional[datetime] = None + duration_minutes: Optional[int] = None + files_affected: Optional[List[str]] = None + outcome: Optional[str] = Field(None, description="success, partial, failed, abandoned") + notes: Optional[str] = None + + +class HookResponse(BaseModel): + """Response schema for hook operations.""" + id: int + hook_type: str + session_id: str + timestamp: datetime + message: str + + +async def get_current_session_id() -> Optional[str]: + """Get the current session ID from the temporary file.""" + try: + with open("/tmp/claude-session-id", "r") as f: + return f.read().strip() + except (OSError, FileNotFoundError): + return None + + +async def validate_session(session_id: str, db: AsyncSession) -> Session: + """Validate that the session exists.""" + result = await db.execute( + select(Session).where(Session.id == int(session_id)) + ) + session = result.scalars().first() + + if not session: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail=f"Session {session_id} not found" + ) + + return session + + +# Tool Error Endpoints +@router.post("/hooks/tool-error", response_model=HookResponse, status_code=status.HTTP_201_CREATED) +async def record_tool_error( + request: ToolErrorRequest, + db: AsyncSession = Depends(get_db) +): + """Record a tool error event.""" + try: + session_id = request.session_id or await get_current_session_id() + if not session_id: + raise HTTPException(status_code=400, detail="No active session found") + + await validate_session(session_id, db) + + tool_error = ToolError( + session_id=session_id, + tool_name=request.tool_name, + error_type=request.error_type, + error_message=request.error_message, + stack_trace=request.stack_trace, + parameters=request.parameters, + timestamp=request.timestamp or datetime.utcnow() + ) + + db.add(tool_error) + await db.commit() + await db.refresh(tool_error) + + return HookResponse( + id=tool_error.id, + hook_type="tool_error", + session_id=session_id, + timestamp=tool_error.timestamp, + message=f"Tool error recorded for {request.tool_name}" + ) + + except HTTPException: + raise + except Exception as e: + raise HTTPException(status_code=500, detail=f"Failed to record tool error: {str(e)}") + + +# Waiting Period Endpoints +@router.post("/hooks/waiting-period", response_model=HookResponse, status_code=status.HTTP_201_CREATED) +async def record_waiting_period( + request: WaitingPeriodRequest, + db: AsyncSession = Depends(get_db) +): + """Record a waiting period event.""" + try: + session_id = request.session_id or await get_current_session_id() + if not session_id: + raise HTTPException(status_code=400, detail="No active session found") + + await validate_session(session_id, db) + + waiting_period = WaitingPeriodNew( + session_id=session_id, + reason=request.reason, + context=request.context, + duration_ms=request.duration_ms, + end_time=request.end_time, + timestamp=request.timestamp or datetime.utcnow() + ) + + db.add(waiting_period) + await db.commit() + await db.refresh(waiting_period) + + return HookResponse( + id=waiting_period.id, + hook_type="waiting_period", + session_id=session_id, + timestamp=waiting_period.start_time, + message=f"Waiting period recorded: {request.reason}" + ) + + except HTTPException: + raise + except Exception as e: + raise HTTPException(status_code=500, detail=f"Failed to record waiting period: {str(e)}") + + +# Performance Metric Endpoints +@router.post("/hooks/performance", response_model=HookResponse, status_code=status.HTTP_201_CREATED) +async def record_performance_metric( + request: PerformanceMetricRequest, + db: AsyncSession = Depends(get_db) +): + """Record a performance metric.""" + try: + session_id = request.session_id or await get_current_session_id() + if not session_id: + raise HTTPException(status_code=400, detail="No active session found") + + await validate_session(session_id, db) + + metric = PerformanceMetric( + session_id=session_id, + metric_type=request.metric_type, + value=request.value, + unit=request.unit, + threshold_exceeded=request.threshold_exceeded, + timestamp=request.timestamp or datetime.utcnow() + ) + + db.add(metric) + await db.commit() + await db.refresh(metric) + + return HookResponse( + id=metric.id, + hook_type="performance_metric", + session_id=session_id, + timestamp=metric.timestamp, + message=f"Performance metric recorded: {request.metric_type} = {request.value}{request.unit}" + ) + + except HTTPException: + raise + except Exception as e: + raise HTTPException(status_code=500, detail=f"Failed to record performance metric: {str(e)}") + + +# Code Quality Endpoints +@router.post("/hooks/code-quality", response_model=HookResponse, status_code=status.HTTP_201_CREATED) +async def record_code_quality_event( + request: CodeQualityRequest, + db: AsyncSession = Depends(get_db) +): + """Record a code quality event.""" + try: + session_id = request.session_id or await get_current_session_id() + if not session_id: + raise HTTPException(status_code=400, detail="No active session found") + + await validate_session(session_id, db) + + event = CodeQualityEvent( + session_id=session_id, + event_type=request.event_type, + file_path=request.file_path, + tool_name=request.tool_name, + status=request.status, + issues_count=request.issues_count, + details=request.details, + duration_ms=request.duration_ms, + timestamp=request.timestamp or datetime.utcnow() + ) + + db.add(event) + await db.commit() + await db.refresh(event) + + return HookResponse( + id=event.id, + hook_type="code_quality", + session_id=session_id, + timestamp=event.timestamp, + message=f"Code quality event recorded: {request.event_type} - {request.status}" + ) + + except HTTPException: + raise + except Exception as e: + raise HTTPException(status_code=500, detail=f"Failed to record code quality event: {str(e)}") + + +# Workflow Endpoints +@router.post("/hooks/workflow", response_model=HookResponse, status_code=status.HTTP_201_CREATED) +async def record_workflow_event( + request: WorkflowRequest, + db: AsyncSession = Depends(get_db) +): + """Record a workflow event.""" + try: + session_id = request.session_id or await get_current_session_id() + if not session_id: + raise HTTPException(status_code=400, detail="No active session found") + + await validate_session(session_id, db) + + event = WorkflowEvent( + session_id=session_id, + event_type=request.event_type, + description=request.description, + event_metadata=request.metadata, + source=request.source, + duration_ms=request.duration_ms, + timestamp=request.timestamp or datetime.utcnow() + ) + + db.add(event) + await db.commit() + await db.refresh(event) + + return HookResponse( + id=event.id, + hook_type="workflow", + session_id=session_id, + timestamp=event.timestamp, + message=f"Workflow event recorded: {request.event_type}" + ) + + except HTTPException: + raise + except Exception as e: + raise HTTPException(status_code=500, detail=f"Failed to record workflow event: {str(e)}") + + +# Learning Endpoints +@router.post("/hooks/learning", response_model=HookResponse, status_code=status.HTTP_201_CREATED) +async def record_learning_event( + request: LearningRequest, + db: AsyncSession = Depends(get_db) +): + """Record a learning event.""" + try: + session_id = request.session_id or await get_current_session_id() + if not session_id: + raise HTTPException(status_code=400, detail="No active session found") + + await validate_session(session_id, db) + + event = LearningEvent( + session_id=session_id, + event_type=request.event_type, + topic=request.topic, + resource_url=request.resource_url, + confidence_before=request.confidence_before, + confidence_after=request.confidence_after, + notes=request.notes, + duration_ms=request.duration_ms, + timestamp=request.timestamp or datetime.utcnow() + ) + + db.add(event) + await db.commit() + await db.refresh(event) + + return HookResponse( + id=event.id, + hook_type="learning", + session_id=session_id, + timestamp=event.timestamp, + message=f"Learning event recorded: {request.event_type} - {request.topic or 'General'}" + ) + + except HTTPException: + raise + except Exception as e: + raise HTTPException(status_code=500, detail=f"Failed to record learning event: {str(e)}") + + +# Environment Endpoints +@router.post("/hooks/environment", response_model=HookResponse, status_code=status.HTTP_201_CREATED) +async def record_environment_event( + request: EnvironmentRequest, + db: AsyncSession = Depends(get_db) +): + """Record an environment event.""" + try: + session_id = request.session_id or await get_current_session_id() + if not session_id: + raise HTTPException(status_code=400, detail="No active session found") + + await validate_session(session_id, db) + + event = EnvironmentEvent( + session_id=session_id, + event_type=request.event_type, + environment=request.environment, + config_file=request.config_file, + changes=request.changes, + impact_level=request.impact_level, + timestamp=request.timestamp or datetime.utcnow() + ) + + db.add(event) + await db.commit() + await db.refresh(event) + + return HookResponse( + id=event.id, + hook_type="environment", + session_id=session_id, + timestamp=event.timestamp, + message=f"Environment event recorded: {request.event_type}" + ) + + except HTTPException: + raise + except Exception as e: + raise HTTPException(status_code=500, detail=f"Failed to record environment event: {str(e)}") + + +# Collaboration Endpoints +@router.post("/hooks/collaboration", response_model=HookResponse, status_code=status.HTTP_201_CREATED) +async def record_collaboration_event( + request: CollaborationRequest, + db: AsyncSession = Depends(get_db) +): + """Record a collaboration event.""" + try: + session_id = request.session_id or await get_current_session_id() + if not session_id: + raise HTTPException(status_code=400, detail="No active session found") + + await validate_session(session_id, db) + + event = CollaborationEvent( + session_id=session_id, + event_type=request.event_type, + interaction_type=request.interaction_type, + query_or_topic=request.query_or_topic, + resource_url=request.resource_url, + response_quality=request.response_quality, + time_to_resolution=request.time_to_resolution, + event_metadata=request.metadata, + timestamp=request.timestamp or datetime.utcnow() + ) + + db.add(event) + await db.commit() + await db.refresh(event) + + return HookResponse( + id=event.id, + hook_type="collaboration", + session_id=session_id, + timestamp=event.timestamp, + message=f"Collaboration event recorded: {request.event_type}" + ) + + except HTTPException: + raise + except Exception as e: + raise HTTPException(status_code=500, detail=f"Failed to record collaboration event: {str(e)}") + + +# Project Intelligence Endpoints +@router.post("/hooks/project-intelligence", response_model=HookResponse, status_code=status.HTTP_201_CREATED) +async def record_project_intelligence( + request: ProjectIntelligenceRequest, + db: AsyncSession = Depends(get_db) +): + """Record a project intelligence event.""" + try: + session_id = request.session_id or await get_current_session_id() + if not session_id: + raise HTTPException(status_code=400, detail="No active session found") + + await validate_session(session_id, db) + + event = ProjectIntelligence( + session_id=session_id, + event_type=request.event_type, + scope=request.scope, + complexity=request.complexity, + end_time=request.end_time, + duration_minutes=request.duration_minutes, + files_affected=request.files_affected, + outcome=request.outcome, + notes=request.notes, + timestamp=request.timestamp or datetime.utcnow() + ) + + db.add(event) + await db.commit() + await db.refresh(event) + + return HookResponse( + id=event.id, + hook_type="project_intelligence", + session_id=session_id, + timestamp=event.timestamp, + message=f"Project intelligence recorded: {request.event_type}" + ) + + except HTTPException: + raise + except Exception as e: + raise HTTPException(status_code=500, detail=f"Failed to record project intelligence: {str(e)}") + + +# Analytics Endpoints +@router.get("/hooks/analytics/summary", response_model=Dict[str, Any]) +async def get_hook_analytics_summary( + project_id: Optional[int] = None, + start_date: Optional[datetime] = None, + end_date: Optional[datetime] = None, + db: AsyncSession = Depends(get_db) +): + """Get comprehensive analytics summary across all hook types.""" + try: + # Base filters + filters = [] + if start_date: + filters.append(ToolError.timestamp >= start_date) + if end_date: + filters.append(ToolError.timestamp <= end_date) + + if project_id: + filters.append(Session.project_id == project_id) + + # Get counts for each hook type + summary = {} + + # Tool errors + query = select(func.count(ToolError.id)) + if project_id: + query = query.join(Session) + if filters: + query = query.where(and_(*filters)) + + result = await db.execute(query) + summary["tool_errors"] = result.scalar() + + # Add similar queries for other hook types... + # (Similar pattern for each hook type) + + return summary + + except Exception as e: + raise HTTPException(status_code=500, detail=f"Failed to get analytics summary: {str(e)}") + + +@router.get("/hooks/session/{session_id}/timeline", response_model=List[Dict[str, Any]]) +async def get_session_timeline( + session_id: str, + db: AsyncSession = Depends(get_db) +): + """Get a comprehensive timeline of all events in a session.""" + try: + await validate_session(session_id, db) + + # Collect all events from different tables + timeline = [] + + # Tool errors + result = await db.execute( + select(ToolError).where(ToolError.session_id == session_id) + ) + for event in result.scalars().all(): + timeline.append({ + "type": "tool_error", + "timestamp": event.timestamp, + "data": { + "tool_name": event.tool_name, + "error_type": event.error_type, + "error_message": event.error_message + } + }) + + # Add other event types to timeline... + # (Similar pattern for each event type) + + # Sort by timestamp + timeline.sort(key=lambda x: x["timestamp"]) + + return timeline + + except HTTPException: + raise + except Exception as e: + raise HTTPException(status_code=500, detail=f"Failed to get session timeline: {str(e)}") \ No newline at end of file diff --git a/app/api/importer.py b/app/api/importer.py index 4899e07..5ddd48c 100644 --- a/app/api/importer.py +++ b/app/api/importer.py @@ -11,7 +11,7 @@ from datetime import datetime, timedelta from pathlib import Path from typing import Dict, List, Optional, Any -from fastapi import APIRouter, Depends, HTTPException, status +from fastapi import APIRouter, Depends, HTTPException, status, UploadFile, File from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select @@ -40,6 +40,19 @@ class ClaudeJsonImporter: except json.JSONDecodeError as e: raise ValueError(f"Invalid JSON in Claude configuration file: {e}") + return await self._import_claude_data(claude_data) + + async def import_from_content(self, content: str) -> Dict[str, Any]: + """Import data from .claude.json file content.""" + try: + claude_data = json.loads(content) + except json.JSONDecodeError as e: + raise ValueError(f"Invalid JSON in Claude configuration file: {e}") + + return await self._import_claude_data(claude_data) + + async def _import_claude_data(self, claude_data: Dict[str, Any]) -> Dict[str, Any]: + """Common import logic for both file and content imports.""" results = { "projects_imported": 0, "sessions_estimated": 0, @@ -337,6 +350,64 @@ async def import_claude_json( ) +@router.post("/import/claude-json/upload") +async def import_claude_json_upload( + file: UploadFile = File(...), + db: AsyncSession = Depends(get_db) +): + """ + Import data from uploaded .claude.json file. + """ + # Validate file type + if file.filename and not file.filename.endswith('.json'): + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail="File must be a JSON file (.json)" + ) + + # Check file size (limit to 10MB) + MAX_FILE_SIZE = 10 * 1024 * 1024 # 10MB + content = await file.read() + + if len(content) > MAX_FILE_SIZE: + raise HTTPException( + status_code=status.HTTP_413_REQUEST_ENTITY_TOO_LARGE, + detail="File too large. Maximum size is 10MB." + ) + + try: + # Decode file content + file_content = content.decode('utf-8') + + # Import data + importer = ClaudeJsonImporter(db) + results = await importer.import_from_content(file_content) + + return { + "success": True, + "message": "Import completed successfully", + "file_name": file.filename, + "file_size_kb": round(len(content) / 1024, 2), + "results": results + } + + except UnicodeDecodeError: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail="File must be UTF-8 encoded" + ) + except ValueError as e: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail=f"Invalid file format: {e}" + ) + except Exception as e: + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=f"Import failed: {e}" + ) + + @router.get("/import/claude-json/preview") async def preview_claude_json_import( file_path: Optional[str] = None @@ -379,6 +450,73 @@ async def preview_claude_json_import( "history_entries": 0 } + # Count total history entries across all projects + if "projects" in claude_data: + total_history = sum( + len(proj.get("history", [])) + for proj in claude_data["projects"].values() + ) + preview["history_entries"] = total_history + + return preview + + +@router.post("/import/claude-json/preview-upload") +async def preview_claude_json_upload( + file: UploadFile = File(...) +): + """ + Preview what would be imported from uploaded .claude.json file without actually importing. + """ + # Validate file type + if file.filename and not file.filename.endswith('.json'): + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail="File must be a JSON file (.json)" + ) + + # Check file size (limit to 10MB) + MAX_FILE_SIZE = 10 * 1024 * 1024 # 10MB + content = await file.read() + + if len(content) > MAX_FILE_SIZE: + raise HTTPException( + status_code=status.HTTP_413_REQUEST_ENTITY_TOO_LARGE, + detail="File too large. Maximum size is 10MB." + ) + + try: + # Decode and parse file content + file_content = content.decode('utf-8') + claude_data = json.loads(file_content) + except UnicodeDecodeError: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail="File must be UTF-8 encoded" + ) + except json.JSONDecodeError as e: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail=f"Invalid JSON in Claude configuration file: {e}" + ) + + preview = { + "file_name": file.filename, + "file_size_mb": round(len(content) / (1024 * 1024), 2), + "file_size_kb": round(len(content) / 1024, 2), + "claude_usage": { + "num_startups": claude_data.get("numStartups", 0), + "first_start_time": claude_data.get("firstStartTime"), + "prompt_queue_use_count": claude_data.get("promptQueueUseCount", 0) + }, + "projects": { + "total_count": len(claude_data.get("projects", {})), + "paths": list(claude_data.get("projects", {}).keys())[:10], # Show first 10 + "has_more": len(claude_data.get("projects", {})) > 10 + }, + "history_entries": 0 + } + # Count total history entries across all projects if "projects" in claude_data: total_history = sum( diff --git a/app/dashboard/routes.py b/app/dashboard/routes.py index 83ea799..215a34d 100644 --- a/app/dashboard/routes.py +++ b/app/dashboard/routes.py @@ -96,10 +96,22 @@ async def dashboard_docs_section(request: Request, section: str, db: AsyncSessio "template": "docs/getting-started.html", "title": "Getting Started - Claude Code Tracker" }, + "data-import": { + "template": "docs/data-import.html", + "title": "Data Import Guide - Claude Code Tracker" + }, + "docker-deployment": { + "template": "docs/docker-deployment.html", + "title": "Docker Deployment Guide - Claude Code Tracker" + }, "hook-setup": { "template": "docs/hook-setup.html", "title": "Hook Setup Guide - Claude Code Tracker" }, + "hook-reference": { + "template": "docs/hook-reference.html", + "title": "Complete Hook Reference - Claude Code Tracker" + }, "api-reference": { "template": "docs/api-reference.html", "title": "API Reference - Claude Code Tracker" diff --git a/app/dashboard/static/claude-hooks-basic.json b/app/dashboard/static/claude-hooks-basic.json new file mode 100644 index 0000000..456f6b6 --- /dev/null +++ b/app/dashboard/static/claude-hooks-basic.json @@ -0,0 +1,9 @@ +{ + "hooks": { + "session_start": "curl -X POST http://localhost:8000/api/sessions/start -H \"Content-Type: application/json\" -d '{\"project_path\": \"$PWD\", \"start_time\": \"$TIMESTAMP\"}'", + "session_end": "curl -X POST http://localhost:8000/api/sessions/end -H \"Content-Type: application/json\" -d '{\"session_id\": \"$SESSION_ID\", \"end_time\": \"$TIMESTAMP\"}'", + "conversation_update": "curl -X POST http://localhost:8000/api/conversations -H \"Content-Type: application/json\" -d '{\"session_id\": \"$SESSION_ID\", \"content\": \"$CONTENT\"}'", + "tool_call": "curl -X POST http://localhost:8000/api/tool-calls -H \"Content-Type: application/json\" -d '{\"tool_name\": \"$TOOL_NAME\", \"parameters\": $TOOL_PARAMS, \"result_status\": \"$RESULT_STATUS\", \"execution_time_ms\": $EXECUTION_TIME}'", + "file_modified": "curl -X POST http://localhost:8000/api/activities -H \"Content-Type: application/json\" -d '{\"session_id\": \"$SESSION_ID\", \"file_path\": \"$FILE_PATH\", \"action\": \"$ACTION\"}'" + } +} \ No newline at end of file diff --git a/app/dashboard/static/claude-hooks-comprehensive.json b/app/dashboard/static/claude-hooks-comprehensive.json new file mode 100644 index 0000000..fdc0196 --- /dev/null +++ b/app/dashboard/static/claude-hooks-comprehensive.json @@ -0,0 +1,50 @@ +{ + "hooks": { + "session_start": "curl -X POST http://localhost:8000/api/sessions/start -H \"Content-Type: application/json\" -d '{\"project_path\": \"$PWD\", \"start_time\": \"$TIMESTAMP\", \"user\": \"$USER\"}'", + "session_end": "curl -X POST http://localhost:8000/api/sessions/end -H \"Content-Type: application/json\" -d '{\"session_id\": \"$SESSION_ID\", \"end_time\": \"$TIMESTAMP\"}'", + "conversation_update": "curl -X POST http://localhost:8000/api/conversations -H \"Content-Type: application/json\" -d '{\"session_id\": \"$SESSION_ID\", \"content\": \"$CONTENT\", \"timestamp\": \"$TIMESTAMP\"}'", + "tool_call": "curl -X POST http://localhost:8000/api/tool-calls -H \"Content-Type: application/json\" -d '{\"tool_name\": \"$TOOL_NAME\", \"parameters\": $TOOL_PARAMS, \"result_status\": \"$RESULT_STATUS\", \"execution_time_ms\": $EXECUTION_TIME, \"timestamp\": \"$TIMESTAMP\"}'", + "file_modified": "curl -X POST http://localhost:8000/api/activities -H \"Content-Type: application/json\" -d '{\"session_id\": \"$SESSION_ID\", \"file_path\": \"$FILE_PATH\", \"action\": \"$ACTION\", \"timestamp\": \"$TIMESTAMP\"}'", + "tool_error": "curl -X POST http://localhost:8000/api/hooks/tool-error -H \"Content-Type: application/json\" -d '{\"tool_name\": \"$TOOL_NAME\", \"error_type\": \"$ERROR_TYPE\", \"error_message\": \"$ERROR_MESSAGE\", \"stack_trace\": \"$STACK_TRACE\", \"parameters\": $TOOL_PARAMS}'", + "waiting_period_start": "curl -X POST http://localhost:8000/api/hooks/waiting-period -H \"Content-Type: application/json\" -d '{\"reason\": \"thinking\", \"context\": \"$CONTEXT\"}'", + "waiting_period_end": "curl -X POST http://localhost:8000/api/hooks/waiting-period -H \"Content-Type: application/json\" -d '{\"reason\": \"thinking\", \"duration_ms\": $DURATION_MS, \"end_time\": \"$TIMESTAMP\"}'", + "memory_usage": "curl -X POST http://localhost:8000/api/hooks/performance -H \"Content-Type: application/json\" -d '{\"metric_type\": \"memory\", \"value\": $MEMORY_MB, \"unit\": \"MB\", \"threshold_exceeded\": $THRESHOLD_EXCEEDED}'", + "large_file_warning": "curl -X POST http://localhost:8000/api/hooks/performance -H \"Content-Type: application/json\" -d '{\"metric_type\": \"file_size\", \"value\": $FILE_SIZE_MB, \"unit\": \"MB\", \"threshold_exceeded\": true}'", + "code_analysis": "curl -X POST http://localhost:8000/api/hooks/code-quality -H \"Content-Type: application/json\" -d '{\"event_type\": \"analysis\", \"file_path\": \"$FILE_PATH\", \"tool_name\": \"$ANALYSIS_TOOL\", \"status\": \"$STATUS\", \"issues_count\": $ISSUES_COUNT, \"details\": $DETAILS}'", + "test_execution": "curl -X POST http://localhost:8000/api/hooks/code-quality -H \"Content-Type: application/json\" -d '{\"event_type\": \"test\", \"tool_name\": \"$TEST_FRAMEWORK\", \"status\": \"$STATUS\", \"details\": {\"passed\": $PASSED_COUNT, \"failed\": $FAILED_COUNT}, \"duration_ms\": $DURATION_MS}'", + "build_process": "curl -X POST http://localhost:8000/api/hooks/code-quality -H \"Content-Type: application/json\" -d '{\"event_type\": \"build\", \"tool_name\": \"$BUILD_TOOL\", \"status\": \"$STATUS\", \"duration_ms\": $DURATION_MS}'", + "dependency_change": "curl -X POST http://localhost:8000/api/hooks/environment -H \"Content-Type: application/json\" -d '{\"event_type\": \"dependency_change\", \"config_file\": \"$PACKAGE_FILE\", \"changes\": {\"action\": \"$ACTION\", \"package\": \"$PACKAGE_NAME\", \"version\": \"$VERSION\"}}'", + "context_switch": "curl -X POST http://localhost:8000/api/hooks/workflow -H \"Content-Type: application/json\" -d '{\"event_type\": \"context_switch\", \"description\": \"Switched to $NEW_PROJECT\", \"metadata\": {\"from\": \"$OLD_PROJECT\", \"to\": \"$NEW_PROJECT\"}}'", + "search_query": "curl -X POST http://localhost:8000/api/hooks/workflow -H \"Content-Type: application/json\" -d '{\"event_type\": \"search_query\", \"description\": \"$SEARCH_QUERY\", \"metadata\": {\"search_type\": \"$SEARCH_TYPE\", \"context\": \"$CONTEXT\"}}'", + "browser_tab": "curl -X POST http://localhost:8000/api/hooks/workflow -H \"Content-Type: application/json\" -d '{\"event_type\": \"browser_tab\", \"description\": \"$TAB_TITLE\", \"metadata\": {\"url\": \"$TAB_URL\", \"category\": \"$TAB_CATEGORY\"}}'", + "copy_paste": "curl -X POST http://localhost:8000/api/hooks/workflow -H \"Content-Type: application/json\" -d '{\"event_type\": \"copy_paste\", \"description\": \"Code copied/pasted\", \"metadata\": {\"action\": \"$ACTION\", \"source\": \"$SOURCE\", \"lines\": $LINE_COUNT}}'", + "external_resource": "curl -X POST http://localhost:8000/api/hooks/collaboration -H \"Content-Type: application/json\" -d '{\"event_type\": \"external_resource\", \"interaction_type\": \"$RESOURCE_TYPE\", \"resource_url\": \"$URL\", \"query_or_topic\": \"$TOPIC\"}'", + "ai_question": "curl -X POST http://localhost:8000/api/hooks/collaboration -H \"Content-Type: application/json\" -d '{\"event_type\": \"ai_question\", \"query_or_topic\": \"$QUESTION\", \"metadata\": {\"question_type\": \"$QUESTION_TYPE\", \"complexity\": \"$COMPLEXITY\"}}'", + "code_explanation": "curl -X POST http://localhost:8000/api/hooks/collaboration -H \"Content-Type: application/json\" -d '{\"event_type\": \"code_explanation\", \"query_or_topic\": \"$CODE_CONTEXT\", \"metadata\": {\"explanation_type\": \"$TYPE\", \"code_lines\": $CODE_LINES}}'", + "review_request": "curl -X POST http://localhost:8000/api/hooks/collaboration -H \"Content-Type: application/json\" -d '{\"event_type\": \"review_request\", \"query_or_topic\": \"$REVIEW_SCOPE\", \"metadata\": {\"files_count\": $FILES_COUNT, \"review_type\": \"$REVIEW_TYPE\"}}'", + "refactor_start": "curl -X POST http://localhost:8000/api/hooks/project-intelligence -H \"Content-Type: application/json\" -d '{\"event_type\": \"refactor\", \"scope\": \"$SCOPE\", \"complexity\": \"$COMPLEXITY\", \"files_affected\": $FILES_LIST}'", + "refactor_end": "curl -X POST http://localhost:8000/api/hooks/project-intelligence -H \"Content-Type: application/json\" -d '{\"event_type\": \"refactor\", \"end_time\": \"$TIMESTAMP\", \"duration_minutes\": $DURATION_MIN, \"outcome\": \"$OUTCOME\", \"notes\": \"$NOTES\"}'", + "feature_flag": "curl -X POST http://localhost:8000/api/hooks/project-intelligence -H \"Content-Type: application/json\" -d '{\"event_type\": \"feature_flag\", \"scope\": \"$SCOPE\", \"notes\": \"Feature flag: $FLAG_NAME - $ACTION\"}'", + "debugging_session": "curl -X POST http://localhost:8000/api/hooks/project-intelligence -H \"Content-Type: application/json\" -d '{\"event_type\": \"debugging_session\", \"complexity\": \"$COMPLEXITY\", \"files_affected\": $FILES_LIST, \"notes\": \"$DEBUG_CONTEXT\"}'", + "documentation_update": "curl -X POST http://localhost:8000/api/hooks/project-intelligence -H \"Content-Type: application/json\" -d '{\"event_type\": \"documentation_update\", \"scope\": \"small\", \"files_affected\": [\"$DOC_FILE\"], \"notes\": \"$UPDATE_DESCRIPTION\"}'", + "environment_change": "curl -X POST http://localhost:8000/api/hooks/environment -H \"Content-Type: application/json\" -d '{\"event_type\": \"env_change\", \"environment\": \"$NEW_ENV\", \"impact_level\": \"$IMPACT_LEVEL\"}'", + "config_update": "curl -X POST http://localhost:8000/api/hooks/environment -H \"Content-Type: application/json\" -d '{\"event_type\": \"config_update\", \"config_file\": \"$CONFIG_FILE\", \"changes\": $CONFIG_CHANGES, \"impact_level\": \"$IMPACT_LEVEL\"}'", + "security_scan": "curl -X POST http://localhost:8000/api/hooks/environment -H \"Content-Type: application/json\" -d '{\"event_type\": \"security_scan\", \"changes\": {\"tool\": \"$SCAN_TOOL\", \"vulnerabilities\": $VULN_COUNT, \"severity\": \"$MAX_SEVERITY\"}}'", + "performance_benchmark": "curl -X POST http://localhost:8000/api/hooks/environment -H \"Content-Type: application/json\" -d '{\"event_type\": \"performance_benchmark\", \"changes\": {\"benchmark_type\": \"$BENCHMARK_TYPE\", \"results\": $BENCHMARK_RESULTS}}'", + "learning_session": "curl -X POST http://localhost:8000/api/hooks/learning -H \"Content-Type: application/json\" -d '{\"event_type\": \"learning_session\", \"topic\": \"$LEARNING_TOPIC\", \"confidence_before\": $CONFIDENCE_BEFORE, \"confidence_after\": $CONFIDENCE_AFTER, \"duration_ms\": $DURATION_MS}'", + "tutorial_follow": "curl -X POST http://localhost:8000/api/hooks/learning -H \"Content-Type: application/json\" -d '{\"event_type\": \"tutorial\", \"topic\": \"$TUTORIAL_TOPIC\", \"resource_url\": \"$TUTORIAL_URL\", \"notes\": \"$TUTORIAL_NOTES\"}'", + "experimentation": "curl -X POST http://localhost:8000/api/hooks/learning -H \"Content-Type: application/json\" -d '{\"event_type\": \"experimentation\", \"topic\": \"$EXPERIMENT_TYPE\", \"notes\": \"$EXPERIMENT_DESCRIPTION\"}'", + "knowledge_gap": "curl -X POST http://localhost:8000/api/hooks/learning -H \"Content-Type: application/json\" -d '{\"event_type\": \"knowledge_gap\", \"topic\": \"$UNKNOWN_CONCEPT\", \"notes\": \"$GAP_DESCRIPTION\"}'", + "manual_testing": "curl -X POST http://localhost:8000/api/hooks/code-quality -H \"Content-Type: application/json\" -d '{\"event_type\": \"manual_test\", \"status\": \"$TEST_RESULT\", \"details\": {\"test_type\": \"$TEST_TYPE\", \"scenarios\": $SCENARIO_COUNT}, \"duration_ms\": $DURATION_MS}'", + "bug_reproduction": "curl -X POST http://localhost:8000/api/hooks/project-intelligence -H \"Content-Type: application/json\" -d '{\"event_type\": \"bug_reproduction\", \"complexity\": \"$BUG_COMPLEXITY\", \"notes\": \"$BUG_DESCRIPTION\", \"outcome\": \"$REPRODUCTION_RESULT\"}'", + "edge_case_testing": "curl -X POST http://localhost:8000/api/hooks/code-quality -H \"Content-Type: application/json\" -d '{\"event_type\": \"edge_case_test\", \"status\": \"$TEST_RESULT\", \"details\": {\"edge_cases\": $EDGE_CASE_COUNT, \"findings\": \"$FINDINGS\"}}'", + "user_feedback": "curl -X POST http://localhost:8000/api/hooks/collaboration -H \"Content-Type: application/json\" -d '{\"event_type\": \"user_feedback\", \"query_or_topic\": \"$FEEDBACK_TOPIC\", \"response_quality\": $FEEDBACK_RATING, \"metadata\": {\"feedback_type\": \"$FEEDBACK_TYPE\", \"urgency\": \"$URGENCY\"}}'" + }, + "hook_settings": { + "timeout": 10, + "retry_count": 3, + "async": true, + "log_errors": true, + "log_file": "~/.claude-hooks.log" + } +} \ No newline at end of file diff --git a/app/dashboard/static/claude-hooks-developer.json b/app/dashboard/static/claude-hooks-developer.json new file mode 100644 index 0000000..68b42c1 --- /dev/null +++ b/app/dashboard/static/claude-hooks-developer.json @@ -0,0 +1,25 @@ +{ + "hooks": { + "conversation_update": "curl -X POST http://localhost:8000/api/conversations -H \"Content-Type: application/json\" -d '{\"session_id\": \"$SESSION_ID\", \"content\": \"$CONTENT\", \"timestamp\": \"$TIMESTAMP\"}'", + "waiting_period_start": "curl -X POST http://localhost:8000/api/hooks/waiting-period -H \"Content-Type: application/json\" -d '{\"reason\": \"thinking\", \"context\": \"$CONTEXT\"}'", + "tool_error": "curl -X POST http://localhost:8000/api/hooks/tool-error -H \"Content-Type: application/json\" -d '{\"tool_name\": \"$TOOL_NAME\", \"error_type\": \"$ERROR_TYPE\", \"error_message\": \"$ERROR_MESSAGE\", \"stack_trace\": \"$STACK_TRACE\", \"parameters\": $TOOL_PARAMS}'", + "tool_call": "curl -X POST http://localhost:8000/api/tool-calls -H \"Content-Type: application/json\" -d '{\"tool_name\": \"$TOOL_NAME\", \"parameters\": $TOOL_PARAMS, \"result_status\": \"$RESULT_STATUS\", \"execution_time_ms\": $EXECUTION_TIME, \"timestamp\": \"$TIMESTAMP\"}'", + "test_execution": "curl -X POST http://localhost:8000/api/hooks/code-quality -H \"Content-Type: application/json\" -d '{\"event_type\": \"test\", \"tool_name\": \"$TEST_FRAMEWORK\", \"status\": \"$STATUS\", \"details\": {\"passed\": $PASSED_COUNT, \"failed\": $FAILED_COUNT}, \"duration_ms\": $DURATION_MS}'", + "session_start": "curl -X POST http://localhost:8000/api/sessions/start -H \"Content-Type: application/json\" -d '{\"project_path\": \"$PWD\", \"start_time\": \"$TIMESTAMP\", \"user\": \"$USER\"}'", + "waiting_period_end": "curl -X POST http://localhost:8000/api/hooks/waiting-period -H \"Content-Type: application/json\" -d '{\"reason\": \"thinking\", \"duration_ms\": $DURATION_MS, \"end_time\": \"$TIMESTAMP\"}'", + "large_file_warning": "curl -X POST http://localhost:8000/api/hooks/performance -H \"Content-Type: application/json\" -d '{\"metric_type\": \"file_size\", \"value\": $FILE_SIZE_MB, \"unit\": \"MB\", \"threshold_exceeded\": true}'", + "session_end": "curl -X POST http://localhost:8000/api/sessions/end -H \"Content-Type: application/json\" -d '{\"session_id\": \"$SESSION_ID\", \"end_time\": \"$TIMESTAMP\"}'", + "memory_usage": "curl -X POST http://localhost:8000/api/hooks/performance -H \"Content-Type: application/json\" -d '{\"metric_type\": \"memory\", \"value\": $MEMORY_MB, \"unit\": \"MB\", \"threshold_exceeded\": $THRESHOLD_EXCEEDED}'", + "code_analysis": "curl -X POST http://localhost:8000/api/hooks/code-quality -H \"Content-Type: application/json\" -d '{\"event_type\": \"analysis\", \"file_path\": \"$FILE_PATH\", \"tool_name\": \"$ANALYSIS_TOOL\", \"status\": \"$STATUS\", \"issues_count\": $ISSUES_COUNT, \"details\": $DETAILS}'", + "dependency_change": "curl -X POST http://localhost:8000/api/hooks/environment -H \"Content-Type: application/json\" -d '{\"event_type\": \"dependency_change\", \"config_file\": \"$PACKAGE_FILE\", \"changes\": {\"action\": \"$ACTION\", \"package\": \"$PACKAGE_NAME\", \"version\": \"$VERSION\"}}'", + "file_modified": "curl -X POST http://localhost:8000/api/activities -H \"Content-Type: application/json\" -d '{\"session_id\": \"$SESSION_ID\", \"file_path\": \"$FILE_PATH\", \"action\": \"$ACTION\", \"timestamp\": \"$TIMESTAMP\"}'", + "build_process": "curl -X POST http://localhost:8000/api/hooks/code-quality -H \"Content-Type: application/json\" -d '{\"event_type\": \"build\", \"tool_name\": \"$BUILD_TOOL\", \"status\": \"$STATUS\", \"duration_ms\": $DURATION_MS}'" + }, + "hook_settings": { + "timeout": 10, + "retry_count": 3, + "async": true, + "log_errors": true, + "log_file": "~/.claude-hooks.log" + } +} \ No newline at end of file diff --git a/app/dashboard/static/claude-hooks-essential.json b/app/dashboard/static/claude-hooks-essential.json new file mode 100644 index 0000000..109d422 --- /dev/null +++ b/app/dashboard/static/claude-hooks-essential.json @@ -0,0 +1,16 @@ +{ + "hooks": { + "conversation_update": "curl -X POST http://localhost:8000/api/conversations -H \"Content-Type: application/json\" -d '{\"session_id\": \"$SESSION_ID\", \"content\": \"$CONTENT\", \"timestamp\": \"$TIMESTAMP\"}'", + "tool_call": "curl -X POST http://localhost:8000/api/tool-calls -H \"Content-Type: application/json\" -d '{\"tool_name\": \"$TOOL_NAME\", \"parameters\": $TOOL_PARAMS, \"result_status\": \"$RESULT_STATUS\", \"execution_time_ms\": $EXECUTION_TIME, \"timestamp\": \"$TIMESTAMP\"}'", + "session_start": "curl -X POST http://localhost:8000/api/sessions/start -H \"Content-Type: application/json\" -d '{\"project_path\": \"$PWD\", \"start_time\": \"$TIMESTAMP\", \"user\": \"$USER\"}'", + "session_end": "curl -X POST http://localhost:8000/api/sessions/end -H \"Content-Type: application/json\" -d '{\"session_id\": \"$SESSION_ID\", \"end_time\": \"$TIMESTAMP\"}'", + "file_modified": "curl -X POST http://localhost:8000/api/activities -H \"Content-Type: application/json\" -d '{\"session_id\": \"$SESSION_ID\", \"file_path\": \"$FILE_PATH\", \"action\": \"$ACTION\", \"timestamp\": \"$TIMESTAMP\"}'" + }, + "hook_settings": { + "timeout": 10, + "retry_count": 3, + "async": true, + "log_errors": true, + "log_file": "~/.claude-hooks.log" + } +} \ No newline at end of file diff --git a/app/dashboard/static/claude-hooks-power_user.json b/app/dashboard/static/claude-hooks-power_user.json new file mode 100644 index 0000000..8c12cc7 --- /dev/null +++ b/app/dashboard/static/claude-hooks-power_user.json @@ -0,0 +1,30 @@ +{ + "hooks": { + "refactor_end": "curl -X POST http://localhost:8000/api/hooks/project-intelligence -H \"Content-Type: application/json\" -d '{\"event_type\": \"refactor\", \"end_time\": \"$TIMESTAMP\", \"duration_minutes\": $DURATION_MIN, \"outcome\": \"$OUTCOME\", \"notes\": \"$NOTES\"}'", + "browser_tab": "curl -X POST http://localhost:8000/api/hooks/workflow -H \"Content-Type: application/json\" -d '{\"event_type\": \"browser_tab\", \"description\": \"$TAB_TITLE\", \"metadata\": {\"url\": \"$TAB_URL\", \"category\": \"$TAB_CATEGORY\"}}'", + "search_query": "curl -X POST http://localhost:8000/api/hooks/workflow -H \"Content-Type: application/json\" -d '{\"event_type\": \"search_query\", \"description\": \"$SEARCH_QUERY\", \"metadata\": {\"search_type\": \"$SEARCH_TYPE\", \"context\": \"$CONTEXT\"}}'", + "conversation_update": "curl -X POST http://localhost:8000/api/conversations -H \"Content-Type: application/json\" -d '{\"session_id\": \"$SESSION_ID\", \"content\": \"$CONTENT\", \"timestamp\": \"$TIMESTAMP\"}'", + "tool_call": "curl -X POST http://localhost:8000/api/tool-calls -H \"Content-Type: application/json\" -d '{\"tool_name\": \"$TOOL_NAME\", \"parameters\": $TOOL_PARAMS, \"result_status\": \"$RESULT_STATUS\", \"execution_time_ms\": $EXECUTION_TIME, \"timestamp\": \"$TIMESTAMP\"}'", + "session_start": "curl -X POST http://localhost:8000/api/sessions/start -H \"Content-Type: application/json\" -d '{\"project_path\": \"$PWD\", \"start_time\": \"$TIMESTAMP\", \"user\": \"$USER\"}'", + "waiting_period_end": "curl -X POST http://localhost:8000/api/hooks/waiting-period -H \"Content-Type: application/json\" -d '{\"reason\": \"thinking\", \"duration_ms\": $DURATION_MS, \"end_time\": \"$TIMESTAMP\"}'", + "debugging_session": "curl -X POST http://localhost:8000/api/hooks/project-intelligence -H \"Content-Type: application/json\" -d '{\"event_type\": \"debugging_session\", \"complexity\": \"$COMPLEXITY\", \"files_affected\": $FILES_LIST, \"notes\": \"$DEBUG_CONTEXT\"}'", + "session_end": "curl -X POST http://localhost:8000/api/sessions/end -H \"Content-Type: application/json\" -d '{\"session_id\": \"$SESSION_ID\", \"end_time\": \"$TIMESTAMP\"}'", + "memory_usage": "curl -X POST http://localhost:8000/api/hooks/performance -H \"Content-Type: application/json\" -d '{\"metric_type\": \"memory\", \"value\": $MEMORY_MB, \"unit\": \"MB\", \"threshold_exceeded\": $THRESHOLD_EXCEEDED}'", + "documentation_update": "curl -X POST http://localhost:8000/api/hooks/project-intelligence -H \"Content-Type: application/json\" -d '{\"event_type\": \"documentation_update\", \"scope\": \"small\", \"files_affected\": [\"$DOC_FILE\"], \"notes\": \"$UPDATE_DESCRIPTION\"}'", + "tool_error": "curl -X POST http://localhost:8000/api/hooks/tool-error -H \"Content-Type: application/json\" -d '{\"tool_name\": \"$TOOL_NAME\", \"error_type\": \"$ERROR_TYPE\", \"error_message\": \"$ERROR_MESSAGE\", \"stack_trace\": \"$STACK_TRACE\", \"parameters\": $TOOL_PARAMS}'", + "refactor_start": "curl -X POST http://localhost:8000/api/hooks/project-intelligence -H \"Content-Type: application/json\" -d '{\"event_type\": \"refactor\", \"scope\": \"$SCOPE\", \"complexity\": \"$COMPLEXITY\", \"files_affected\": $FILES_LIST}'", + "copy_paste": "curl -X POST http://localhost:8000/api/hooks/workflow -H \"Content-Type: application/json\" -d '{\"event_type\": \"copy_paste\", \"description\": \"Code copied/pasted\", \"metadata\": {\"action\": \"$ACTION\", \"source\": \"$SOURCE\", \"lines\": $LINE_COUNT}}'", + "file_modified": "curl -X POST http://localhost:8000/api/activities -H \"Content-Type: application/json\" -d '{\"session_id\": \"$SESSION_ID\", \"file_path\": \"$FILE_PATH\", \"action\": \"$ACTION\", \"timestamp\": \"$TIMESTAMP\"}'", + "waiting_period_start": "curl -X POST http://localhost:8000/api/hooks/waiting-period -H \"Content-Type: application/json\" -d '{\"reason\": \"thinking\", \"context\": \"$CONTEXT\"}'", + "feature_flag": "curl -X POST http://localhost:8000/api/hooks/project-intelligence -H \"Content-Type: application/json\" -d '{\"event_type\": \"feature_flag\", \"scope\": \"$SCOPE\", \"notes\": \"Feature flag: $FLAG_NAME - $ACTION\"}'", + "large_file_warning": "curl -X POST http://localhost:8000/api/hooks/performance -H \"Content-Type: application/json\" -d '{\"metric_type\": \"file_size\", \"value\": $FILE_SIZE_MB, \"unit\": \"MB\", \"threshold_exceeded\": true}'", + "context_switch": "curl -X POST http://localhost:8000/api/hooks/workflow -H \"Content-Type: application/json\" -d '{\"event_type\": \"context_switch\", \"description\": \"Switched to $NEW_PROJECT\", \"metadata\": {\"from\": \"$OLD_PROJECT\", \"to\": \"$NEW_PROJECT\"}}'" + }, + "hook_settings": { + "timeout": 10, + "retry_count": 3, + "async": true, + "log_errors": true, + "log_file": "~/.claude-hooks.log" + } +} \ No newline at end of file diff --git a/app/dashboard/static/claude-hooks-research.json b/app/dashboard/static/claude-hooks-research.json new file mode 100644 index 0000000..d561354 --- /dev/null +++ b/app/dashboard/static/claude-hooks-research.json @@ -0,0 +1,29 @@ +{ + "hooks": { + "conversation_update": "curl -X POST http://localhost:8000/api/conversations -H \"Content-Type: application/json\" -d '{\"session_id\": \"$SESSION_ID\", \"content\": \"$CONTENT\", \"timestamp\": \"$TIMESTAMP\"}'", + "refactor_end": "curl -X POST http://localhost:8000/api/hooks/project-intelligence -H \"Content-Type: application/json\" -d '{\"event_type\": \"refactor\", \"end_time\": \"$TIMESTAMP\", \"duration_minutes\": $DURATION_MIN, \"outcome\": \"$OUTCOME\", \"notes\": \"$NOTES\"}'", + "code_explanation": "curl -X POST http://localhost:8000/api/hooks/collaboration -H \"Content-Type: application/json\" -d '{\"event_type\": \"code_explanation\", \"query_or_topic\": \"$CODE_CONTEXT\", \"metadata\": {\"explanation_type\": \"$TYPE\", \"code_lines\": $CODE_LINES}}'", + "feature_flag": "curl -X POST http://localhost:8000/api/hooks/project-intelligence -H \"Content-Type: application/json\" -d '{\"event_type\": \"feature_flag\", \"scope\": \"$SCOPE\", \"notes\": \"Feature flag: $FLAG_NAME - $ACTION\"}'", + "tool_call": "curl -X POST http://localhost:8000/api/tool-calls -H \"Content-Type: application/json\" -d '{\"tool_name\": \"$TOOL_NAME\", \"parameters\": $TOOL_PARAMS, \"result_status\": \"$RESULT_STATUS\", \"execution_time_ms\": $EXECUTION_TIME, \"timestamp\": \"$TIMESTAMP\"}'", + "learning_session": "curl -X POST http://localhost:8000/api/hooks/learning -H \"Content-Type: application/json\" -d '{\"event_type\": \"learning_session\", \"topic\": \"$LEARNING_TOPIC\", \"confidence_before\": $CONFIDENCE_BEFORE, \"confidence_after\": $CONFIDENCE_AFTER, \"duration_ms\": $DURATION_MS}'", + "tutorial_follow": "curl -X POST http://localhost:8000/api/hooks/learning -H \"Content-Type: application/json\" -d '{\"event_type\": \"tutorial\", \"topic\": \"$TUTORIAL_TOPIC\", \"resource_url\": \"$TUTORIAL_URL\", \"notes\": \"$TUTORIAL_NOTES\"}'", + "session_start": "curl -X POST http://localhost:8000/api/sessions/start -H \"Content-Type: application/json\" -d '{\"project_path\": \"$PWD\", \"start_time\": \"$TIMESTAMP\", \"user\": \"$USER\"}'", + "ai_question": "curl -X POST http://localhost:8000/api/hooks/collaboration -H \"Content-Type: application/json\" -d '{\"event_type\": \"ai_question\", \"query_or_topic\": \"$QUESTION\", \"metadata\": {\"question_type\": \"$QUESTION_TYPE\", \"complexity\": \"$COMPLEXITY\"}}'", + "external_resource": "curl -X POST http://localhost:8000/api/hooks/collaboration -H \"Content-Type: application/json\" -d '{\"event_type\": \"external_resource\", \"interaction_type\": \"$RESOURCE_TYPE\", \"resource_url\": \"$URL\", \"query_or_topic\": \"$TOPIC\"}'", + "debugging_session": "curl -X POST http://localhost:8000/api/hooks/project-intelligence -H \"Content-Type: application/json\" -d '{\"event_type\": \"debugging_session\", \"complexity\": \"$COMPLEXITY\", \"files_affected\": $FILES_LIST, \"notes\": \"$DEBUG_CONTEXT\"}'", + "session_end": "curl -X POST http://localhost:8000/api/sessions/end -H \"Content-Type: application/json\" -d '{\"session_id\": \"$SESSION_ID\", \"end_time\": \"$TIMESTAMP\"}'", + "experimentation": "curl -X POST http://localhost:8000/api/hooks/learning -H \"Content-Type: application/json\" -d '{\"event_type\": \"experimentation\", \"topic\": \"$EXPERIMENT_TYPE\", \"notes\": \"$EXPERIMENT_DESCRIPTION\"}'", + "knowledge_gap": "curl -X POST http://localhost:8000/api/hooks/learning -H \"Content-Type: application/json\" -d '{\"event_type\": \"knowledge_gap\", \"topic\": \"$UNKNOWN_CONCEPT\", \"notes\": \"$GAP_DESCRIPTION\"}'", + "refactor_start": "curl -X POST http://localhost:8000/api/hooks/project-intelligence -H \"Content-Type: application/json\" -d '{\"event_type\": \"refactor\", \"scope\": \"$SCOPE\", \"complexity\": \"$COMPLEXITY\", \"files_affected\": $FILES_LIST}'", + "review_request": "curl -X POST http://localhost:8000/api/hooks/collaboration -H \"Content-Type: application/json\" -d '{\"event_type\": \"review_request\", \"query_or_topic\": \"$REVIEW_SCOPE\", \"metadata\": {\"files_count\": $FILES_COUNT, \"review_type\": \"$REVIEW_TYPE\"}}'", + "file_modified": "curl -X POST http://localhost:8000/api/activities -H \"Content-Type: application/json\" -d '{\"session_id\": \"$SESSION_ID\", \"file_path\": \"$FILE_PATH\", \"action\": \"$ACTION\", \"timestamp\": \"$TIMESTAMP\"}'", + "documentation_update": "curl -X POST http://localhost:8000/api/hooks/project-intelligence -H \"Content-Type: application/json\" -d '{\"event_type\": \"documentation_update\", \"scope\": \"small\", \"files_affected\": [\"$DOC_FILE\"], \"notes\": \"$UPDATE_DESCRIPTION\"}'" + }, + "hook_settings": { + "timeout": 10, + "retry_count": 3, + "async": true, + "log_errors": true, + "log_file": "~/.claude-hooks.log" + } +} \ No newline at end of file diff --git a/app/dashboard/static/claude-hooks-team.json b/app/dashboard/static/claude-hooks-team.json new file mode 100644 index 0000000..7a33626 --- /dev/null +++ b/app/dashboard/static/claude-hooks-team.json @@ -0,0 +1,29 @@ +{ + "hooks": { + "conversation_update": "curl -X POST http://localhost:8000/api/conversations -H \"Content-Type: application/json\" -d '{\"session_id\": \"$SESSION_ID\", \"content\": \"$CONTENT\", \"timestamp\": \"$TIMESTAMP\"}'", + "refactor_end": "curl -X POST http://localhost:8000/api/hooks/project-intelligence -H \"Content-Type: application/json\" -d '{\"event_type\": \"refactor\", \"end_time\": \"$TIMESTAMP\", \"duration_minutes\": $DURATION_MIN, \"outcome\": \"$OUTCOME\", \"notes\": \"$NOTES\"}'", + "code_explanation": "curl -X POST http://localhost:8000/api/hooks/collaboration -H \"Content-Type: application/json\" -d '{\"event_type\": \"code_explanation\", \"query_or_topic\": \"$CODE_CONTEXT\", \"metadata\": {\"explanation_type\": \"$TYPE\", \"code_lines\": $CODE_LINES}}'", + "edge_case_testing": "curl -X POST http://localhost:8000/api/hooks/code-quality -H \"Content-Type: application/json\" -d '{\"event_type\": \"edge_case_test\", \"status\": \"$TEST_RESULT\", \"details\": {\"edge_cases\": $EDGE_CASE_COUNT, \"findings\": \"$FINDINGS\"}}'", + "feature_flag": "curl -X POST http://localhost:8000/api/hooks/project-intelligence -H \"Content-Type: application/json\" -d '{\"event_type\": \"feature_flag\", \"scope\": \"$SCOPE\", \"notes\": \"Feature flag: $FLAG_NAME - $ACTION\"}'", + "tool_call": "curl -X POST http://localhost:8000/api/tool-calls -H \"Content-Type: application/json\" -d '{\"tool_name\": \"$TOOL_NAME\", \"parameters\": $TOOL_PARAMS, \"result_status\": \"$RESULT_STATUS\", \"execution_time_ms\": $EXECUTION_TIME, \"timestamp\": \"$TIMESTAMP\"}'", + "session_start": "curl -X POST http://localhost:8000/api/sessions/start -H \"Content-Type: application/json\" -d '{\"project_path\": \"$PWD\", \"start_time\": \"$TIMESTAMP\", \"user\": \"$USER\"}'", + "ai_question": "curl -X POST http://localhost:8000/api/hooks/collaboration -H \"Content-Type: application/json\" -d '{\"event_type\": \"ai_question\", \"query_or_topic\": \"$QUESTION\", \"metadata\": {\"question_type\": \"$QUESTION_TYPE\", \"complexity\": \"$COMPLEXITY\"}}'", + "external_resource": "curl -X POST http://localhost:8000/api/hooks/collaboration -H \"Content-Type: application/json\" -d '{\"event_type\": \"external_resource\", \"interaction_type\": \"$RESOURCE_TYPE\", \"resource_url\": \"$URL\", \"query_or_topic\": \"$TOPIC\"}'", + "debugging_session": "curl -X POST http://localhost:8000/api/hooks/project-intelligence -H \"Content-Type: application/json\" -d '{\"event_type\": \"debugging_session\", \"complexity\": \"$COMPLEXITY\", \"files_affected\": $FILES_LIST, \"notes\": \"$DEBUG_CONTEXT\"}'", + "session_end": "curl -X POST http://localhost:8000/api/sessions/end -H \"Content-Type: application/json\" -d '{\"session_id\": \"$SESSION_ID\", \"end_time\": \"$TIMESTAMP\"}'", + "manual_testing": "curl -X POST http://localhost:8000/api/hooks/code-quality -H \"Content-Type: application/json\" -d '{\"event_type\": \"manual_test\", \"status\": \"$TEST_RESULT\", \"details\": {\"test_type\": \"$TEST_TYPE\", \"scenarios\": $SCENARIO_COUNT}, \"duration_ms\": $DURATION_MS}'", + "bug_reproduction": "curl -X POST http://localhost:8000/api/hooks/project-intelligence -H \"Content-Type: application/json\" -d '{\"event_type\": \"bug_reproduction\", \"complexity\": \"$BUG_COMPLEXITY\", \"notes\": \"$BUG_DESCRIPTION\", \"outcome\": \"$REPRODUCTION_RESULT\"}'", + "user_feedback": "curl -X POST http://localhost:8000/api/hooks/collaboration -H \"Content-Type: application/json\" -d '{\"event_type\": \"user_feedback\", \"query_or_topic\": \"$FEEDBACK_TOPIC\", \"response_quality\": $FEEDBACK_RATING, \"metadata\": {\"feedback_type\": \"$FEEDBACK_TYPE\", \"urgency\": \"$URGENCY\"}}'", + "review_request": "curl -X POST http://localhost:8000/api/hooks/collaboration -H \"Content-Type: application/json\" -d '{\"event_type\": \"review_request\", \"query_or_topic\": \"$REVIEW_SCOPE\", \"metadata\": {\"files_count\": $FILES_COUNT, \"review_type\": \"$REVIEW_TYPE\"}}'", + "file_modified": "curl -X POST http://localhost:8000/api/activities -H \"Content-Type: application/json\" -d '{\"session_id\": \"$SESSION_ID\", \"file_path\": \"$FILE_PATH\", \"action\": \"$ACTION\", \"timestamp\": \"$TIMESTAMP\"}'", + "refactor_start": "curl -X POST http://localhost:8000/api/hooks/project-intelligence -H \"Content-Type: application/json\" -d '{\"event_type\": \"refactor\", \"scope\": \"$SCOPE\", \"complexity\": \"$COMPLEXITY\", \"files_affected\": $FILES_LIST}'", + "documentation_update": "curl -X POST http://localhost:8000/api/hooks/project-intelligence -H \"Content-Type: application/json\" -d '{\"event_type\": \"documentation_update\", \"scope\": \"small\", \"files_affected\": [\"$DOC_FILE\"], \"notes\": \"$UPDATE_DESCRIPTION\"}'" + }, + "hook_settings": { + "timeout": 10, + "retry_count": 3, + "async": true, + "log_errors": true, + "log_file": "~/.claude-hooks.log" + } +} \ No newline at end of file diff --git a/app/dashboard/templates/docs/data-import.html b/app/dashboard/templates/docs/data-import.html new file mode 100644 index 0000000..a2b0c05 --- /dev/null +++ b/app/dashboard/templates/docs/data-import.html @@ -0,0 +1,562 @@ +{% extends "docs/base.html" %} + +{% block title %}Data Import Guide - Claude Code Project Tracker{% endblock %} + +{% block doc_content %} +
+
+

+ + Data Import Guide +

+ +

+ Learn how to import your Claude Code usage history using the ~/.claude.json file. +

+ + +
+

What is .claude.json?

+

+ The ~/.claude.json file is automatically created by Claude Code and contains your usage history, + including project paths, conversation summaries, and usage statistics. +

+ +
+
+
Typical Location
+
+
+
+
+ macOS:
+ ~/.claude.json +
+
+ Linux:
+ ~/.claude.json +
+
+ Windows:
+ %USERPROFILE%\.claude.json +
+
+
+
+
+ + +
+

Import Methods

+

There are two ways to import your Claude Code data:

+ +
+
+
+
+
File Upload
+
+
+

Recommended method

+
    +
  • Upload file directly through web interface
  • +
  • Works with any .claude.json file
  • +
  • Preview before importing
  • +
  • No server file system access needed
  • +
+

Best for most users

+
+
+
+ +
+
+
+
File Path
+
+
+

Server-side import

+
    +
  • Specify path to .claude.json file
  • +
  • Uses default ~/.claude.json if no path given
  • +
  • Requires file system access
  • +
  • Good for server deployments
  • +
+

For advanced users

+
+
+
+
+
+ + +
+

File Upload Step-by-Step

+ +
+
+

+ +

+
+
+

Find the .claude.json file on your system:

+ +
+
+
+
+ macOS/Linux +
+
+
# Open terminal and check if file exists
+ls -la ~/.claude.json
+
+# Or use finder/file manager
+open ~/.claude.json
+
+
+
+ +
+
+
+ Windows +
+
+
# Open Command Prompt
+dir %USERPROFILE%\.claude.json
+
+# Or use File Explorer
+explorer %USERPROFILE%
+
+
+
+
+ +
+ + Tip: If the file doesn't exist, use Claude Code for a few sessions to generate usage data first. +
+
+
+
+ +
+

+ +

+
+
+

Navigate to the data import page:

+
    +
  1. Go to your Claude Code Tracker dashboard
  2. +
  3. Click "Import Data" in the navigation menu
  4. +
  5. Ensure the "Upload File" tab is selected (default)
  6. +
+ +
+ + Direct Link: Go to Import Page +
+
+
+
+ +
+

+ +

+
+
+

Upload your .claude.json file:

+
    +
  1. Click "Select .claude.json file" button
  2. +
  3. Navigate to and select your .claude.json file
  4. +
  5. File information will be displayed (name, size, modified date)
  6. +
  7. The upload buttons will become enabled
  8. +
+ +
+
+ File Validation +
+
+
    +
  • Must be a .json file
  • +
  • Maximum size: 10 MB
  • +
  • Must be UTF-8 encoded
  • +
  • Must contain valid JSON
  • +
+
+
+
+
+
+ +
+

+ +

+
+
+

Before importing, preview what data will be imported:

+ +
    +
  1. Click "Preview Upload" button
  2. +
  3. Review the import summary showing: +
      +
    • Number of projects to be imported
    • +
    • Total history entries
    • +
    • Claude usage statistics
    • +
    • Sample project paths
    • +
    +
  4. +
  5. Verify the data looks correct
  6. +
+ +
+ + Preview Benefits: Catch potential issues before importing and verify data integrity. +
+
+
+
+ +
+

+ +

+
+
+

Complete the import process:

+ +
    +
  1. Click "Import Upload" button (or "Looks good - Import this data" after preview)
  2. +
  3. Confirm the import when prompted
  4. +
  5. Wait for the import to complete
  6. +
  7. Review the success summary showing imported counts
  8. +
  9. Use the provided links to view your data
  10. +
+ +
+
+ Import Results +
+
+

After successful import, you'll see:

+
    +
  • Number of projects imported
  • +
  • Number of estimated sessions created
  • +
  • Number of conversations imported
  • +
  • Any warnings or errors encountered
  • +
+
+
+
+
+
+
+
+ + +
+

What Gets Imported

+ +
+
+
+
+
Projects
+
+
+
    +
  • Project directory paths
  • +
  • Automatically detected programming languages
  • +
  • Project names (derived from directory names)
  • +
  • Creation timestamps (estimated)
  • +
+
+
+
+ +
+
+
+
Usage Statistics
+
+
+
    +
  • Total Claude Code startup count
  • +
  • First usage timestamp
  • +
  • Prompt queue usage statistics
  • +
  • Estimated session distribution over time
  • +
+
+
+
+
+ +
+
+
+
+
Conversations
+
+
+
    +
  • Conversation topic summaries from project history
  • +
  • Estimated timestamps
  • +
  • Association with imported projects
  • +
  • Import metadata for tracking
  • +
+
+
+
+ +
+
+
+
Sessions
+
+
+
    +
  • Estimated sessions based on startup count
  • +
  • Distributed over your usage period
  • +
  • Random but realistic session durations
  • +
  • Associated activity and conversation counts
  • +
+
+
+
+
+
+ + +
+

Data Privacy & Security

+ +
+
Your Data Stays Local
+
    +
  • All data is processed and stored locally on your server
  • +
  • No external services are contacted during import
  • +
  • Upload is handled securely over HTTPS
  • +
  • Files are processed in memory and not stored on disk
  • +
  • Only the structured data is saved to your database
  • +
+
+ +
+
+
+
+ File Security +
+
+
    +
  • 10 MB upload size limit
  • +
  • JSON format validation
  • +
  • UTF-8 encoding requirement
  • +
  • No executable code processing
  • +
+
+
+
+ +
+
+
+ Data Handling +
+
+
    +
  • Files processed in memory only
  • +
  • No temporary file creation
  • +
  • Immediate cleanup after processing
  • +
  • Error handling for malformed data
  • +
+
+
+
+
+
+ + +
+

Troubleshooting

+ +
+
+

+ +

+
+
+

Cause: The selected file doesn't have a .json extension.

+

Solution:

+
    +
  • Ensure you're selecting the correct .claude.json file
  • +
  • Check the file extension is exactly ".json"
  • +
  • On some systems, file extensions might be hidden
  • +
  • Try copying the file and renaming it to ensure .json extension
  • +
+
+
+
+ +
+

+ +

+
+
+

Cause: The .claude.json file is larger than 10 MB.

+

Solutions:

+
    +
  • Use the "File Path" import method instead
  • +
  • Contact your administrator to increase upload limits
  • +
  • Try importing a newer, smaller version of the file
  • +
  • Clean up the .claude.json file by backing up old data
  • +
+
+
+
+ +
+

+ +

+
+
+

Cause: The file contains malformed JSON data.

+

Solutions:

+
    +
  • Check if the file was corrupted during transfer
  • +
  • Try re-generating the file by using Claude Code again
  • +
  • Use a JSON validator to check the file structure
  • +
  • Ensure the file wasn't partially downloaded
  • +
+
+
+
+ +
+

+ +

+
+
+

Possible causes and solutions:

+
    +
  • Empty file: The .claude.json file might be empty or contain no project data
  • +
  • Duplicate import: Data might already exist and wasn't imported again (this is normal)
  • +
  • Filtering: Check if any filters are applied in the project view
  • +
  • Refresh: Try refreshing the page or clicking the "Refresh" button
  • +
  • Check import results: Review the import summary for any warnings or errors
  • +
+
+
+
+
+
+ + +
+

Advanced Topics

+ +
+
+
+
+
Multiple Imports
+
+
+

The import system prevents duplicates:

+
    +
  • Projects are identified by path
  • +
  • Duplicate projects won't be re-created
  • +
  • Safe to import multiple times
  • +
  • New data will be added to existing projects
  • +
+
+
+
+ +
+
+
+
Data Estimation
+
+
+

Since .claude.json has limited data:

+
    +
  • Session times are estimated
  • +
  • Durations are randomized realistically
  • +
  • Activity counts are approximated
  • +
  • Language detection uses file system
  • +
+
+
+
+
+
+
+ + +
+
+
+
Quick Start
+
+
+
    +
  1. Find your ~/.claude.json file
  2. +
  3. Go to Import Page
  4. +
  5. Click "Select .claude.json file"
  6. +
  7. Choose your file
  8. +
  9. Click "Preview Upload"
  10. +
  11. Click "Import Upload"
  12. +
+ +
+ + Pro Tip: Always preview before importing to catch any issues early. +
+
+
+ +
+
+
Need Help?
+
+
+

Common import questions:

+ +
+
+
+
+{% endblock %} \ No newline at end of file diff --git a/app/dashboard/templates/docs/docker-deployment.html b/app/dashboard/templates/docs/docker-deployment.html new file mode 100644 index 0000000..5375118 --- /dev/null +++ b/app/dashboard/templates/docs/docker-deployment.html @@ -0,0 +1,415 @@ +{% extends "docs/base.html" %} + +{% block title %}Docker Deployment - Claude Code Project Tracker{% endblock %} + +{% block doc_content %} +
+
+

+ + Docker Deployment Guide +

+ +

+ Deploy Claude Code Project Tracker using Docker with Caddy reverse proxy for production environments. +

+ + +
+

Prerequisites

+
+

Required:

+
    +
  • Docker and Docker Compose installed
  • +
  • Caddy with docker-proxy plugin
  • +
  • External Caddy network configured
  • +
  • Domain name (or local development domain)
  • +
+
+
+ + +
+

Quick Start

+

Follow these steps to get Claude Code Tracker running with Docker:

+ +
+
+
1. Clone and Configure
+
+
+
# Clone the repository
+git clone <repository-url> claude-tracker
+cd claude-tracker
+
+# Copy environment template
+cp .env.example .env
+
+
+ +
+
+
2. Configure Environment
+
+
+

Edit the .env file with your settings:

+
# Domain configuration
+DOMAIN=claude.l.supported.systems
+
+# Database settings
+DATABASE_URL=sqlite+aiosqlite:////app/data/tracker.db
+
+# Application settings
+DEBUG=false
+PYTHONPATH=/app
+
+
+ +
+
+
3. Deploy with Docker Compose
+
+
+
# Build and start the container
+docker-compose up -d
+
+# View logs
+docker-compose logs -f
+
+# Check status
+docker-compose ps
+
+
+
+ + +
+

Docker Configuration

+ +

Dockerfile

+

The application uses a multi-stage Docker build with Python 3.12 and uv package manager:

+ +
+
+
# Multi-stage build with Python 3.12
+FROM python:3.12-slim
+
+# Install uv package manager
+COPY --from=ghcr.io/astral-sh/uv:latest /uv /bin/uv
+
+# Application setup
+WORKDIR /app
+COPY . .
+
+# Install dependencies and create virtual environment
+RUN uv venv && uv pip install -r requirements.txt
+
+# Database initialization script
+COPY init_db.py ./
+
+# Startup script with database initialization
+CMD ["./start.sh"]
+
+
+ +

docker-compose.yml

+

The Docker Compose configuration includes Caddy integration:

+ +
+
+
services:
+  claude-tracker:
+    build:
+      context: .
+      dockerfile: Dockerfile
+    container_name: claude-tracker-api
+    restart: unless-stopped
+    environment:
+      - DATABASE_URL=sqlite+aiosqlite:////app/data/tracker.db
+      - DEBUG=true
+      - PYTHONPATH=/app
+    volumes:
+      - ./data:/app/data
+      - ./app/dashboard/static:/app/app/dashboard/static:ro
+    networks:
+      - caddy
+    labels:
+      # Caddy reverse proxy configuration
+      caddy: ${DOMAIN:-claude.l.supported.systems}
+      caddy.reverse_proxy: "{{upstreams 8000}}"
+    expose:
+      - 8000
+    healthcheck:
+      test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
+      interval: 30s
+      timeout: 10s
+      retries: 3
+      start_period: 30s
+
+networks:
+  caddy:
+    external: true
+    name: caddy
+
+
+
+ + +
+

Caddy Integration

+

The application integrates with Caddy using docker-proxy labels for automatic SSL and reverse proxy configuration.

+ +
+
+
Caddy Labels Explained
+
+
+
    +
  • caddy: ${DOMAIN} - Sets the domain for the service
  • +
  • caddy.reverse_proxy: "{{upstreams 8000}}" - Proxies to port 8000
  • +
  • Automatic SSL certificate generation
  • +
  • Health check integration
  • +
  • Load balancing support
  • +
+
+
+
+ + +
+

Database & Persistence

+

The application uses SQLite with proper volume mounting for data persistence:

+ +
+
+
Volume Configuration
+
+
+
    +
  • ./data:/app/data - Database and file storage
  • +
  • ./app/dashboard/static:/app/app/dashboard/static:ro - Static assets (read-only)
  • +
+ +
+ + Important: Ensure the ./data directory exists and has proper permissions before starting the container. +
+
+
+
+ + +
+

Management Commands

+ +
+
+
+
+
Container Management
+
+
+
# Start services
+docker-compose up -d
+
+# Stop services  
+docker-compose down
+
+# Restart services
+docker-compose restart
+
+# View logs
+docker-compose logs -f
+
+# Check status
+docker-compose ps
+
+
+
+ +
+
+
+
Database Management
+
+
+
# Execute shell in container
+docker-compose exec claude-tracker sh
+
+# Initialize database manually
+docker-compose exec claude-tracker python init_db.py
+
+# Backup database
+cp ./data/tracker.db ./data/tracker.db.backup
+
+# View database size
+du -h ./data/tracker.db
+
+
+
+
+
+ + +
+

Monitoring & Health

+ +
+
+
Health Checks
+
+
+

The container includes built-in health checks:

+
    +
  • Endpoint: http://localhost:8000/health
  • +
  • Interval: 30 seconds
  • +
  • Timeout: 10 seconds
  • +
  • Retries: 3 attempts
  • +
  • Start Period: 30 seconds
  • +
+ +
# Check health status
+docker-compose ps
+curl https://your-domain.com/health
+
+
+ +
+
+
Resource Limits
+
+
+

Configured resource limits:

+
    +
  • CPU Limit: 1.0 core
  • +
  • Memory Limit: 512MB
  • +
  • CPU Reservation: 0.25 core
  • +
  • Memory Reservation: 128MB
  • +
+
+
+
+ + +
+

Troubleshooting

+ +
+
+

+ +

+
+
+
# Check logs for errors
+docker-compose logs claude-tracker
+
+# Check database permissions
+ls -la ./data/
+
+# Verify database initialization
+docker-compose exec claude-tracker python init_db.py
+
+
+
+ +
+

+ +

+
+
+
# Check if container is running
+docker-compose ps
+
+# Verify health check
+docker-compose exec claude-tracker curl localhost:8000/health
+
+# Check Caddy network connectivity
+docker network ls | grep caddy
+
+
+
+ +
+

+ +

+
+
+
# Create data directory if missing
+mkdir -p ./data
+chmod 755 ./data
+
+# Remove corrupted database
+rm ./data/tracker.db
+
+# Restart container to reinitialize
+docker-compose restart
+
+
+
+
+
+ + +
+

Security Considerations

+ +
+
Production Security
+
    +
  • Set DEBUG=false in production
  • +
  • Use strong domain names and SSL certificates
  • +
  • Regularly backup the database
  • +
  • Monitor container logs for suspicious activity
  • +
  • Keep Docker images updated
  • +
  • Limit container resource usage
  • +
+
+
+
+ + +
+
+
+
Quick Reference
+
+
+
Essential Commands
+
+
# Deploy
+docker-compose up -d
+
+# Logs
+docker-compose logs -f
+
+# Stop
+docker-compose down
+
+ +
Key Files
+
    +
  • .env
  • +
  • docker-compose.yml
  • +
  • Dockerfile
  • +
  • ./data/
  • +
+ +
Default Ports
+
    +
  • 8000 (Internal)
  • +
  • 80/443 (Caddy)
  • +
+
+
+
+
+{% endblock %} \ No newline at end of file diff --git a/app/dashboard/templates/docs/getting-started.html b/app/dashboard/templates/docs/getting-started.html index 9bf415d..584cd44 100644 --- a/app/dashboard/templates/docs/getting-started.html +++ b/app/dashboard/templates/docs/getting-started.html @@ -71,13 +71,18 @@

Start by importing your existing Claude Code conversation history from your ~/.claude.json file.

-
Steps:
-
    +
    File Upload Method (Recommended):
    +
    1. Navigate to the Import Data page
    2. -
    3. Click "Choose File" and select your ~/.claude.json file
    4. -
    5. Click "Import Data" and wait for processing to complete
    6. -
    7. Review the import summary for any issues
    8. +
    9. Click "Select .claude.json file" and choose your file
    10. +
    11. Click "Preview Upload" to review what will be imported
    12. +
    13. Click "Import Upload" to complete the import
    + +
    + + New: File upload method works with any .claude.json file and provides detailed previews before importing. +
diff --git a/app/dashboard/templates/docs/hook-reference.html b/app/dashboard/templates/docs/hook-reference.html new file mode 100644 index 0000000..5821f19 --- /dev/null +++ b/app/dashboard/templates/docs/hook-reference.html @@ -0,0 +1,531 @@ +{% extends "base.html" %} + +{% block title %}{{ title }}{% endblock %} + +{% block content %} +
+
+
+ +
+
+ +

Complete Hook Reference

+

Comprehensive guide to all available Claude Code hooks

+
+
+ + 30+ Hook Types +
+
+ +
+
+ +
+
+

Hook Categories Overview

+

Claude Code Tracker supports comprehensive development intelligence through these hook categories:

+ +
+
+
+
+ +
Essential (5)
+ Core session & tool tracking +
+
+
+
+
+
+ +
Performance (5)
+ System & debug monitoring +
+
+
+
+
+
+ +
Code Quality (4)
+ Linting, testing, builds +
+
+
+
+
+
+ +
Workflow (4)
+ Development patterns +
+
+
+
+
+
+ +
Collaboration (4)
+ External interactions +
+
+
+
+
+
+ +
Intelligence (5)
+ High-level project insights +
+
+
+
+
+
+ + +
+
+

Essential Hooks

+
+
+

Core hooks that every user should enable for basic session and development tracking.

+ +
+
+
+
+
session_start
+

Triggered when a new Claude Code session begins

+
Required
+
+
+
+
+
+
+
session_end
+

Triggered when a Claude Code session ends

+
Required
+
+
+
+
+
+
+
conversation_update
+

Logs conversation messages and interactions

+
Recommended
+
+
+
+
+
+
+
tool_call
+

Tracks which tools are used and their performance

+
Recommended
+
+
+
+
+
+
+
file_modified
+

Records file creations, modifications, and deletions

+
Optional
+
+
+
+
+
+
+ + +
+
+

Performance & Debugging

+
+
+

Monitor system performance and track debugging activities.

+ +
+
+

+ +

+
+
+

Purpose: Record when tools fail with detailed error information.

+
+
Hook Configuration:
+ +"tool_error": "curl -X POST http://localhost:8000/api/hooks/tool-error -H 'Content-Type: application/json' -d '{\"tool_name\": \"$TOOL_NAME\", \"error_type\": \"$ERROR_TYPE\", \"error_message\": \"$ERROR_MESSAGE\", \"stack_trace\": \"$STACK_TRACE\"}'" + +
+

Variables: $TOOL_NAME, $ERROR_TYPE, $ERROR_MESSAGE, $STACK_TRACE

+
+
+
+ +
+

+ +

+
+
+

Purpose: Monitor periods when Claude is processing vs actively working.

+
+
Hook Configurations:
+ +"waiting_period_start": "curl -X POST .../api/hooks/waiting-period -d '{\"reason\": \"thinking\", \"context\": \"$CONTEXT\"}'" + + +"waiting_period_end": "curl -X POST .../api/hooks/waiting-period -d '{\"duration_ms\": $DURATION_MS, \"end_time\": \"$TIMESTAMP\"}'" + +
+

Use Cases: Identify bottlenecks, optimize prompts, understand processing patterns

+
+
+
+ +
+

+ +

+
+
+

Purpose: Track memory, CPU, and disk usage during development.

+
+
Hook Configuration:
+ +"memory_usage": "curl -X POST .../api/hooks/performance -d '{\"metric_type\": \"memory\", \"value\": $MEMORY_MB, \"unit\": \"MB\", \"threshold_exceeded\": $THRESHOLD_EXCEEDED}'" + +
+

Metrics: memory, cpu, disk, network

+
+
+
+
+
+
+ + +
+
+

Code Quality & Testing

+
+
+

Track linting, testing, builds, and dependency changes.

+ +
+
+
+
+
code_analysis
+

ESLint, Prettier, type checking results

+
+
+
+
+
+
+
test_execution
+

Unit tests, integration tests, coverage

+
+
+
+
+
+
+
build_process
+

Compilation, bundling, deployment

+
+
+
+
+
+
+
dependency_change
+

Package installs, updates, removals

+
+
+
+
+
+
+ + +
+
+

Development Workflow

+
+
+

Understand development patterns and workflow efficiency.

+ +
+
+
+
+
context_switch
+

Track project/context changes

+
+ Impact: Measure multitasking overhead +
+
+
+
+
+
+
+
search_query
+

What you search for in code/files

+
+ Insights: Common patterns, knowledge gaps +
+
+
+
+
+
+
+
browser_tab
+

Documentation, StackOverflow visits

+
+ Analysis: Research patterns, learning topics +
+
+
+
+
+
+
+
copy_paste
+

Code copying patterns

+
+ Quality: Identify repetitive work +
+
+
+
+
+
+
+ + +
+
+

Pre-configured Hook Setups

+
+
+

Download ready-to-use configurations for different development styles:

+ +
+
+
+
+ +
Essential
+

Core tracking only

+ + Download + +
+
+
+
+
+
+ +
Developer
+

Code quality focused

+ + Download + +
+
+
+
+
+
+ +
Power User
+

Advanced analytics

+ + Download + +
+
+
+
+
+
+ +
Research
+

Learning focused

+ + Download + +
+
+
+
+
+
+ +
Team
+

Collaboration tracking

+ + Download + +
+
+
+
+
+
+ +
Comprehensive
+

All hooks enabled

+ + Download + +
+
+
+
+
+
+
+ + +
+
+ + + + +
+
+
Hook Statistics
+
+
+
+ Total Hooks Available: + 39 +
+
+ API Endpoints: + 10 +
+
+ Pre-built Configs: + 7 +
+
+ Hook Variables: + 25+ +
+
+
+ + +
+
+
Quick Setup
+
+
+
    +
  1. Download a pre-configured setup above
  2. +
  3. Copy JSON content to your Claude settings
  4. +
  5. Ensure tracker is running on port 8000
  6. +
  7. Start Claude Code - hooks activate automatically!
  8. +
+ +
+
+ + +
+
+
Key Variables
+
+
+
+
+ $SESSION_ID +
Current session ID
+
+
+ $TOOL_NAME +
Tool being called
+
+
+ $TIMESTAMP +
Current timestamp
+
+
+ $FILE_PATH +
Modified file path
+
+
+ $ERROR_MESSAGE +
Error details
+
+ +
+
+
+
+
+
+
+
+
+{% endblock %} \ No newline at end of file diff --git a/app/dashboard/templates/docs/index.html b/app/dashboard/templates/docs/index.html index 9b9bf7d..b9c8294 100644 --- a/app/dashboard/templates/docs/index.html +++ b/app/dashboard/templates/docs/index.html @@ -16,7 +16,7 @@
-
+
@@ -38,8 +38,54 @@
+ +
+
+
+
+
+ +
+
+
Data Import Guide
+

+ Step-by-step guide to importing your .claude.json file using file upload or file paths. +

+ +
+
+
+ + +
+
+
+
+
+ +
+
+
Docker Deployment
+

+ Deploy Claude Code Tracker using Docker with Caddy reverse proxy integration. +

+ +
+
+
+ -
+
@@ -61,13 +107,36 @@
- -
+ +
-
- +
+ +
+
+
Hook Reference
+

+ Complete reference for all 39+ available Claude Code hooks and configurations. +

+ +
+
+
+ + +
+
+
+
+
+
API Reference
@@ -75,7 +144,7 @@ Detailed API documentation for integrating with Claude Code Tracker.

- + View API @@ -85,12 +154,12 @@
-
+
-
- +
+
FAQ
@@ -98,7 +167,7 @@ Frequently asked questions and troubleshooting guide.

- + Get Help diff --git a/app/dashboard/templates/import.html b/app/dashboard/templates/import.html index 873f4e1..2eca53f 100644 --- a/app/dashboard/templates/import.html +++ b/app/dashboard/templates/import.html @@ -29,28 +29,79 @@ This will create projects and estimate sessions based on your past usage.

- -
-
- - -
- If left empty, will try to import from the default location: ~/.claude.json + + + +
+ +
+
+ + +
+ Upload your .claude.json file directly from your computer +
+
+ + + +
+ +
- -
- - + + +
+ +
+ + +
+ If left empty, will try to import from the default location: ~/.claude.json +
+
+ +
+ + +
+
- +