Add comprehensive Docker deployment and file upload functionality

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 <noreply@anthropic.com>
This commit is contained in:
Ryan Malloy 2025-08-11 08:02:09 -06:00
parent bec1606c86
commit 50c80596d0
36 changed files with 4334 additions and 172 deletions

87
.dockerignore Normal file
View File

@ -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/

View File

@ -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
@ -17,3 +25,19 @@ ANALYTICS_BATCH_SIZE=1000
# Logging
LOG_LEVEL=INFO
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

345
DOCKER.md Normal file
View File

@ -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 <repository>
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`

53
Dockerfile Normal file
View File

@ -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"]

214
README.md
View File

@ -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
For more help, see the documentation at `/dashboard/docs/hook-setup`.

619
app/api/hooks.py Normal file
View File

@ -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)}")

View File

@ -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
@ -388,3 +459,70 @@ async def preview_claude_json_import(
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(
len(proj.get("history", []))
for proj in claude_data["projects"].values()
)
preview["history_entries"] = total_history
return preview

View File

@ -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"

View File

@ -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\"}'"
}
}

View File

@ -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"
}
}

View File

@ -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"
}
}

View File

@ -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"
}
}

View File

@ -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"
}
}

View File

@ -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"
}
}

View File

@ -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"
}
}

View File

@ -0,0 +1,562 @@
{% extends "docs/base.html" %}
{% block title %}Data Import Guide - Claude Code Project Tracker{% endblock %}
{% block doc_content %}
<div class="row">
<div class="col-lg-8">
<h1 class="mb-4">
<i class="fas fa-cloud-upload-alt text-primary me-2"></i>
Data Import Guide
</h1>
<p class="lead">
Learn how to import your Claude Code usage history using the <code>~/.claude.json</code> file.
</p>
<!-- Overview -->
<section class="mb-5">
<h2><i class="fas fa-info-circle me-2"></i>What is .claude.json?</h2>
<p>
The <code>~/.claude.json</code> file is automatically created by Claude Code and contains your usage history,
including project paths, conversation summaries, and usage statistics.
</p>
<div class="card mb-3">
<div class="card-header bg-light">
<h5 class="mb-0">Typical Location</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-4">
<strong>macOS:</strong><br>
<code>~/.claude.json</code>
</div>
<div class="col-md-4">
<strong>Linux:</strong><br>
<code>~/.claude.json</code>
</div>
<div class="col-md-4">
<strong>Windows:</strong><br>
<code>%USERPROFILE%\.claude.json</code>
</div>
</div>
</div>
</div>
</section>
<!-- Import Methods -->
<section class="mb-5">
<h2><i class="fas fa-upload me-2"></i>Import Methods</h2>
<p>There are two ways to import your Claude Code data:</p>
<div class="row">
<div class="col-md-6">
<div class="card h-100">
<div class="card-header bg-primary text-white">
<h5 class="mb-0"><i class="fas fa-cloud-upload-alt me-1"></i>File Upload</h5>
</div>
<div class="card-body">
<p><strong>Recommended method</strong></p>
<ul>
<li>Upload file directly through web interface</li>
<li>Works with any .claude.json file</li>
<li>Preview before importing</li>
<li>No server file system access needed</li>
</ul>
<p class="text-success mb-0"><i class="fas fa-check me-1"></i>Best for most users</p>
</div>
</div>
</div>
<div class="col-md-6">
<div class="card h-100">
<div class="card-header bg-secondary text-white">
<h5 class="mb-0"><i class="fas fa-folder-open me-1"></i>File Path</h5>
</div>
<div class="card-body">
<p><strong>Server-side import</strong></p>
<ul>
<li>Specify path to .claude.json file</li>
<li>Uses default ~/.claude.json if no path given</li>
<li>Requires file system access</li>
<li>Good for server deployments</li>
</ul>
<p class="text-info mb-0"><i class="fas fa-info me-1"></i>For advanced users</p>
</div>
</div>
</div>
</div>
</section>
<!-- File Upload Guide -->
<section class="mb-5">
<h2><i class="fas fa-step-forward me-2"></i>File Upload Step-by-Step</h2>
<div class="accordion" id="uploadStepsAccordion">
<div class="accordion-item">
<h2 class="accordion-header" id="step1">
<button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#collapseStep1">
Step 1: Locate your .claude.json file
</button>
</h2>
<div id="collapseStep1" class="accordion-collapse collapse show" data-bs-parent="#uploadStepsAccordion">
<div class="accordion-body">
<p>Find the .claude.json file on your system:</p>
<div class="row">
<div class="col-md-6">
<div class="card">
<div class="card-header">
<strong>macOS/Linux</strong>
</div>
<div class="card-body">
<pre><code class="language-bash"># Open terminal and check if file exists
ls -la ~/.claude.json
# Or use finder/file manager
open ~/.claude.json</code></pre>
</div>
</div>
</div>
<div class="col-md-6">
<div class="card">
<div class="card-header">
<strong>Windows</strong>
</div>
<div class="card-body">
<pre><code class="language-cmd"># Open Command Prompt
dir %USERPROFILE%\.claude.json
# Or use File Explorer
explorer %USERPROFILE%</code></pre>
</div>
</div>
</div>
</div>
<div class="alert alert-info mt-3">
<i class="fas fa-lightbulb me-1"></i>
<strong>Tip:</strong> If the file doesn't exist, use Claude Code for a few sessions to generate usage data first.
</div>
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header" id="step2">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseStep2">
Step 2: Access the Import Page
</button>
</h2>
<div id="collapseStep2" class="accordion-collapse collapse" data-bs-parent="#uploadStepsAccordion">
<div class="accordion-body">
<p>Navigate to the data import page:</p>
<ol>
<li>Go to your Claude Code Tracker dashboard</li>
<li>Click <strong>"Import Data"</strong> in the navigation menu</li>
<li>Ensure the <strong>"Upload File"</strong> tab is selected (default)</li>
</ol>
<div class="alert alert-success">
<i class="fas fa-link me-1"></i>
<strong>Direct Link:</strong> <a href="/dashboard/import" class="alert-link">Go to Import Page</a>
</div>
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header" id="step3">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseStep3">
Step 3: Select and Upload File
</button>
</h2>
<div id="collapseStep3" class="accordion-collapse collapse" data-bs-parent="#uploadStepsAccordion">
<div class="accordion-body">
<p>Upload your .claude.json file:</p>
<ol>
<li>Click <strong>"Select .claude.json file"</strong> button</li>
<li>Navigate to and select your .claude.json file</li>
<li>File information will be displayed (name, size, modified date)</li>
<li>The upload buttons will become enabled</li>
</ol>
<div class="card mt-3">
<div class="card-header">
<strong>File Validation</strong>
</div>
<div class="card-body">
<ul class="mb-0">
<li>Must be a .json file</li>
<li>Maximum size: 10 MB</li>
<li>Must be UTF-8 encoded</li>
<li>Must contain valid JSON</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header" id="step4">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseStep4">
Step 4: Preview Import (Recommended)
</button>
</h2>
<div id="collapseStep4" class="accordion-collapse collapse" data-bs-parent="#uploadStepsAccordion">
<div class="accordion-body">
<p>Before importing, preview what data will be imported:</p>
<ol>
<li>Click <strong>"Preview Upload"</strong> button</li>
<li>Review the import summary showing:
<ul>
<li>Number of projects to be imported</li>
<li>Total history entries</li>
<li>Claude usage statistics</li>
<li>Sample project paths</li>
</ul>
</li>
<li>Verify the data looks correct</li>
</ol>
<div class="alert alert-warning">
<i class="fas fa-eye me-1"></i>
<strong>Preview Benefits:</strong> Catch potential issues before importing and verify data integrity.
</div>
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header" id="step5">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseStep5">
Step 5: Import Data
</button>
</h2>
<div id="collapseStep5" class="accordion-collapse collapse" data-bs-parent="#uploadStepsAccordion">
<div class="accordion-body">
<p>Complete the import process:</p>
<ol>
<li>Click <strong>"Import Upload"</strong> button (or "Looks good - Import this data" after preview)</li>
<li>Confirm the import when prompted</li>
<li>Wait for the import to complete</li>
<li>Review the success summary showing imported counts</li>
<li>Use the provided links to view your data</li>
</ol>
<div class="card mt-3">
<div class="card-header">
<strong>Import Results</strong>
</div>
<div class="card-body">
<p>After successful import, you'll see:</p>
<ul class="mb-0">
<li>Number of projects imported</li>
<li>Number of estimated sessions created</li>
<li>Number of conversations imported</li>
<li>Any warnings or errors encountered</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- What Gets Imported -->
<section class="mb-5">
<h2><i class="fas fa-database me-2"></i>What Gets Imported</h2>
<div class="row">
<div class="col-md-6">
<div class="card h-100">
<div class="card-header bg-primary text-white">
<h5 class="mb-0"><i class="fas fa-folder me-1"></i>Projects</h5>
</div>
<div class="card-body">
<ul class="mb-0">
<li>Project directory paths</li>
<li>Automatically detected programming languages</li>
<li>Project names (derived from directory names)</li>
<li>Creation timestamps (estimated)</li>
</ul>
</div>
</div>
</div>
<div class="col-md-6">
<div class="card h-100">
<div class="card-header bg-success text-white">
<h5 class="mb-0"><i class="fas fa-chart-line me-1"></i>Usage Statistics</h5>
</div>
<div class="card-body">
<ul class="mb-0">
<li>Total Claude Code startup count</li>
<li>First usage timestamp</li>
<li>Prompt queue usage statistics</li>
<li>Estimated session distribution over time</li>
</ul>
</div>
</div>
</div>
</div>
<div class="row mt-3">
<div class="col-md-6">
<div class="card h-100">
<div class="card-header bg-info text-white">
<h5 class="mb-0"><i class="fas fa-comments me-1"></i>Conversations</h5>
</div>
<div class="card-body">
<ul class="mb-0">
<li>Conversation topic summaries from project history</li>
<li>Estimated timestamps</li>
<li>Association with imported projects</li>
<li>Import metadata for tracking</li>
</ul>
</div>
</div>
</div>
<div class="col-md-6">
<div class="card h-100">
<div class="card-header bg-warning text-dark">
<h5 class="mb-0"><i class="fas fa-clock me-1"></i>Sessions</h5>
</div>
<div class="card-body">
<ul class="mb-0">
<li>Estimated sessions based on startup count</li>
<li>Distributed over your usage period</li>
<li>Random but realistic session durations</li>
<li>Associated activity and conversation counts</li>
</ul>
</div>
</div>
</div>
</div>
</section>
<!-- Data Privacy & Security -->
<section class="mb-5">
<h2><i class="fas fa-shield-alt me-2"></i>Data Privacy & Security</h2>
<div class="alert alert-success">
<h5><i class="fas fa-lock me-1"></i>Your Data Stays Local</h5>
<ul class="mb-0">
<li>All data is processed and stored locally on your server</li>
<li>No external services are contacted during import</li>
<li>Upload is handled securely over HTTPS</li>
<li>Files are processed in memory and not stored on disk</li>
<li>Only the structured data is saved to your database</li>
</ul>
</div>
<div class="row mt-3">
<div class="col-md-6">
<div class="card">
<div class="card-header">
<strong>File Security</strong>
</div>
<div class="card-body">
<ul class="mb-0">
<li>10 MB upload size limit</li>
<li>JSON format validation</li>
<li>UTF-8 encoding requirement</li>
<li>No executable code processing</li>
</ul>
</div>
</div>
</div>
<div class="col-md-6">
<div class="card">
<div class="card-header">
<strong>Data Handling</strong>
</div>
<div class="card-body">
<ul class="mb-0">
<li>Files processed in memory only</li>
<li>No temporary file creation</li>
<li>Immediate cleanup after processing</li>
<li>Error handling for malformed data</li>
</ul>
</div>
</div>
</div>
</div>
</section>
<!-- Troubleshooting -->
<section class="mb-5">
<h2><i class="fas fa-tools me-2"></i>Troubleshooting</h2>
<div class="accordion" id="troubleshootingAccordion">
<div class="accordion-item">
<h2 class="accordion-header" id="troubleFile">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseTroubleFile">
"File must be a JSON file" error
</button>
</h2>
<div id="collapseTroubleFile" class="accordion-collapse collapse" data-bs-parent="#troubleshootingAccordion">
<div class="accordion-body">
<p><strong>Cause:</strong> The selected file doesn't have a .json extension.</p>
<p><strong>Solution:</strong></p>
<ul>
<li>Ensure you're selecting the correct .claude.json file</li>
<li>Check the file extension is exactly ".json"</li>
<li>On some systems, file extensions might be hidden</li>
<li>Try copying the file and renaming it to ensure .json extension</li>
</ul>
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header" id="troubleSize">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseTroubleSize">
"File too large" error
</button>
</h2>
<div id="collapseTroubleSize" class="accordion-collapse collapse" data-bs-parent="#troubleshootingAccordion">
<div class="accordion-body">
<p><strong>Cause:</strong> The .claude.json file is larger than 10 MB.</p>
<p><strong>Solutions:</strong></p>
<ul>
<li>Use the "File Path" import method instead</li>
<li>Contact your administrator to increase upload limits</li>
<li>Try importing a newer, smaller version of the file</li>
<li>Clean up the .claude.json file by backing up old data</li>
</ul>
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header" id="troubleJson">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseTroubleJson">
"Invalid JSON" error
</button>
</h2>
<div id="collapseTroubleJson" class="accordion-collapse collapse" data-bs-parent="#troubleshootingAccordion">
<div class="accordion-body">
<p><strong>Cause:</strong> The file contains malformed JSON data.</p>
<p><strong>Solutions:</strong></p>
<ul>
<li>Check if the file was corrupted during transfer</li>
<li>Try re-generating the file by using Claude Code again</li>
<li>Use a JSON validator to check the file structure</li>
<li>Ensure the file wasn't partially downloaded</li>
</ul>
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header" id="troubleImport">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseTroubleImport">
Import completed but no data appears
</button>
</h2>
<div id="collapseTroubleImport" class="accordion-collapse collapse" data-bs-parent="#troubleshootingAccordion">
<div class="accordion-body">
<p><strong>Possible causes and solutions:</strong></p>
<ul>
<li><strong>Empty file:</strong> The .claude.json file might be empty or contain no project data</li>
<li><strong>Duplicate import:</strong> Data might already exist and wasn't imported again (this is normal)</li>
<li><strong>Filtering:</strong> Check if any filters are applied in the project view</li>
<li><strong>Refresh:</strong> Try refreshing the page or clicking the "Refresh" button</li>
<li><strong>Check import results:</strong> Review the import summary for any warnings or errors</li>
</ul>
</div>
</div>
</div>
</div>
</section>
<!-- Advanced Topics -->
<section class="mb-5">
<h2><i class="fas fa-cogs me-2"></i>Advanced Topics</h2>
<div class="row">
<div class="col-md-6">
<div class="card h-100">
<div class="card-header">
<h5 class="mb-0">Multiple Imports</h5>
</div>
<div class="card-body">
<p>The import system prevents duplicates:</p>
<ul>
<li>Projects are identified by path</li>
<li>Duplicate projects won't be re-created</li>
<li>Safe to import multiple times</li>
<li>New data will be added to existing projects</li>
</ul>
</div>
</div>
</div>
<div class="col-md-6">
<div class="card h-100">
<div class="card-header">
<h5 class="mb-0">Data Estimation</h5>
</div>
<div class="card-body">
<p>Since .claude.json has limited data:</p>
<ul>
<li>Session times are estimated</li>
<li>Durations are randomized realistically</li>
<li>Activity counts are approximated</li>
<li>Language detection uses file system</li>
</ul>
</div>
</div>
</div>
</div>
</section>
</div>
<!-- Sidebar -->
<div class="col-lg-4">
<div class="card sticky-top" style="top: 1rem;">
<div class="card-header">
<h5 class="mb-0"><i class="fas fa-rocket me-1"></i>Quick Start</h5>
</div>
<div class="card-body">
<ol class="mb-3">
<li>Find your <code>~/.claude.json</code> file</li>
<li><a href="/dashboard/import">Go to Import Page</a></li>
<li>Click "Select .claude.json file"</li>
<li>Choose your file</li>
<li>Click "Preview Upload"</li>
<li>Click "Import Upload"</li>
</ol>
<div class="alert alert-success">
<i class="fas fa-lightbulb me-1"></i>
<strong>Pro Tip:</strong> Always preview before importing to catch any issues early.
</div>
</div>
</div>
<div class="card mt-3">
<div class="card-header">
<h5 class="mb-0"><i class="fas fa-question-circle me-1"></i>Need Help?</h5>
</div>
<div class="card-body">
<p>Common import questions:</p>
<ul class="mb-0">
<li><a href="#troubleshootingAccordion">Troubleshooting Guide</a></li>
<li><a href="/dashboard/docs/faq">FAQ Page</a></li>
<li><a href="/dashboard/docs/api-reference">API Documentation</a></li>
</ul>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,415 @@
{% extends "docs/base.html" %}
{% block title %}Docker Deployment - Claude Code Project Tracker{% endblock %}
{% block doc_content %}
<div class="row">
<div class="col-lg-8">
<h1 class="mb-4">
<i class="fab fa-docker text-primary me-2"></i>
Docker Deployment Guide
</h1>
<p class="lead">
Deploy Claude Code Project Tracker using Docker with Caddy reverse proxy for production environments.
</p>
<!-- Prerequisites -->
<section class="mb-5">
<h2><i class="fas fa-check-circle me-2"></i>Prerequisites</h2>
<div class="alert alert-info">
<p class="mb-2"><strong>Required:</strong></p>
<ul class="mb-0">
<li>Docker and Docker Compose installed</li>
<li>Caddy with docker-proxy plugin</li>
<li>External Caddy network configured</li>
<li>Domain name (or local development domain)</li>
</ul>
</div>
</section>
<!-- Quick Start -->
<section class="mb-5">
<h2><i class="fas fa-rocket me-2"></i>Quick Start</h2>
<p>Follow these steps to get Claude Code Tracker running with Docker:</p>
<div class="card mb-3">
<div class="card-header bg-light">
<h5 class="mb-0">1. Clone and Configure</h5>
</div>
<div class="card-body">
<pre><code class="language-bash"># Clone the repository
git clone &lt;repository-url&gt; claude-tracker
cd claude-tracker
# Copy environment template
cp .env.example .env</code></pre>
</div>
</div>
<div class="card mb-3">
<div class="card-header bg-light">
<h5 class="mb-0">2. Configure Environment</h5>
</div>
<div class="card-body">
<p>Edit the <code>.env</code> file with your settings:</p>
<pre><code class="language-bash"># Domain configuration
DOMAIN=claude.l.supported.systems
# Database settings
DATABASE_URL=sqlite+aiosqlite:////app/data/tracker.db
# Application settings
DEBUG=false
PYTHONPATH=/app</code></pre>
</div>
</div>
<div class="card mb-3">
<div class="card-header bg-light">
<h5 class="mb-0">3. Deploy with Docker Compose</h5>
</div>
<div class="card-body">
<pre><code class="language-bash"># Build and start the container
docker-compose up -d
# View logs
docker-compose logs -f
# Check status
docker-compose ps</code></pre>
</div>
</div>
</section>
<!-- Docker Configuration -->
<section class="mb-5">
<h2><i class="fas fa-cog me-2"></i>Docker Configuration</h2>
<h4 class="mt-4">Dockerfile</h4>
<p>The application uses a multi-stage Docker build with Python 3.12 and uv package manager:</p>
<div class="card mb-3">
<div class="card-body">
<pre><code class="language-dockerfile"># 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"]</code></pre>
</div>
</div>
<h4 class="mt-4">docker-compose.yml</h4>
<p>The Docker Compose configuration includes Caddy integration:</p>
<div class="card mb-3">
<div class="card-body">
<pre><code class="language-yaml">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</code></pre>
</div>
</div>
</section>
<!-- Caddy Integration -->
<section class="mb-5">
<h2><i class="fas fa-globe me-2"></i>Caddy Integration</h2>
<p>The application integrates with Caddy using docker-proxy labels for automatic SSL and reverse proxy configuration.</p>
<div class="card mb-3">
<div class="card-header bg-light">
<h5 class="mb-0">Caddy Labels Explained</h5>
</div>
<div class="card-body">
<ul>
<li><code>caddy: ${DOMAIN}</code> - Sets the domain for the service</li>
<li><code>caddy.reverse_proxy: "{{upstreams 8000}}"</code> - Proxies to port 8000</li>
<li>Automatic SSL certificate generation</li>
<li>Health check integration</li>
<li>Load balancing support</li>
</ul>
</div>
</div>
</section>
<!-- Database & Persistence -->
<section class="mb-5">
<h2><i class="fas fa-database me-2"></i>Database & Persistence</h2>
<p>The application uses SQLite with proper volume mounting for data persistence:</p>
<div class="card mb-3">
<div class="card-header bg-light">
<h5 class="mb-0">Volume Configuration</h5>
</div>
<div class="card-body">
<ul>
<li><code>./data:/app/data</code> - Database and file storage</li>
<li><code>./app/dashboard/static:/app/app/dashboard/static:ro</code> - Static assets (read-only)</li>
</ul>
<div class="alert alert-warning mt-3">
<i class="fas fa-exclamation-triangle me-1"></i>
<strong>Important:</strong> Ensure the <code>./data</code> directory exists and has proper permissions before starting the container.
</div>
</div>
</div>
</section>
<!-- Management Commands -->
<section class="mb-5">
<h2><i class="fas fa-terminal me-2"></i>Management Commands</h2>
<div class="row">
<div class="col-md-6">
<div class="card h-100">
<div class="card-header">
<h5 class="mb-0">Container Management</h5>
</div>
<div class="card-body">
<pre><code class="language-bash"># 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</code></pre>
</div>
</div>
</div>
<div class="col-md-6">
<div class="card h-100">
<div class="card-header">
<h5 class="mb-0">Database Management</h5>
</div>
<div class="card-body">
<pre><code class="language-bash"># 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</code></pre>
</div>
</div>
</div>
</div>
</section>
<!-- Monitoring & Health -->
<section class="mb-5">
<h2><i class="fas fa-heartbeat me-2"></i>Monitoring & Health</h2>
<div class="card mb-3">
<div class="card-header bg-light">
<h5 class="mb-0">Health Checks</h5>
</div>
<div class="card-body">
<p>The container includes built-in health checks:</p>
<ul>
<li><strong>Endpoint:</strong> <code>http://localhost:8000/health</code></li>
<li><strong>Interval:</strong> 30 seconds</li>
<li><strong>Timeout:</strong> 10 seconds</li>
<li><strong>Retries:</strong> 3 attempts</li>
<li><strong>Start Period:</strong> 30 seconds</li>
</ul>
<pre><code class="language-bash"># Check health status
docker-compose ps
curl https://your-domain.com/health</code></pre>
</div>
</div>
<div class="card mb-3">
<div class="card-header bg-light">
<h5 class="mb-0">Resource Limits</h5>
</div>
<div class="card-body">
<p>Configured resource limits:</p>
<ul>
<li><strong>CPU Limit:</strong> 1.0 core</li>
<li><strong>Memory Limit:</strong> 512MB</li>
<li><strong>CPU Reservation:</strong> 0.25 core</li>
<li><strong>Memory Reservation:</strong> 128MB</li>
</ul>
</div>
</div>
</section>
<!-- Troubleshooting -->
<section class="mb-5">
<h2><i class="fas fa-tools me-2"></i>Troubleshooting</h2>
<div class="accordion" id="troubleshootingAccordion">
<div class="accordion-item">
<h2 class="accordion-header" id="headingOne">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseOne">
Container keeps restarting
</button>
</h2>
<div id="collapseOne" class="accordion-collapse collapse" data-bs-parent="#troubleshootingAccordion">
<div class="accordion-body">
<pre><code class="language-bash"># 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</code></pre>
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header" id="headingTwo">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseTwo">
502 Bad Gateway errors
</button>
</h2>
<div id="collapseTwo" class="accordion-collapse collapse" data-bs-parent="#troubleshootingAccordion">
<div class="accordion-body">
<pre><code class="language-bash"># 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</code></pre>
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header" id="headingThree">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseThree">
Database connection issues
</button>
</h2>
<div id="collapseThree" class="accordion-collapse collapse" data-bs-parent="#troubleshootingAccordion">
<div class="accordion-body">
<pre><code class="language-bash"># 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</code></pre>
</div>
</div>
</div>
</div>
</section>
<!-- Security Considerations -->
<section class="mb-5">
<h2><i class="fas fa-shield-alt me-2"></i>Security Considerations</h2>
<div class="alert alert-warning">
<h5><i class="fas fa-exclamation-triangle me-1"></i>Production Security</h5>
<ul class="mb-0">
<li>Set <code>DEBUG=false</code> in production</li>
<li>Use strong domain names and SSL certificates</li>
<li>Regularly backup the database</li>
<li>Monitor container logs for suspicious activity</li>
<li>Keep Docker images updated</li>
<li>Limit container resource usage</li>
</ul>
</div>
</section>
</div>
<!-- Sidebar -->
<div class="col-lg-4">
<div class="card sticky-top" style="top: 1rem;">
<div class="card-header">
<h5 class="mb-0"><i class="fas fa-list me-1"></i>Quick Reference</h5>
</div>
<div class="card-body">
<h6>Essential Commands</h6>
<div class="code-block mb-3">
<pre><code># Deploy
docker-compose up -d
# Logs
docker-compose logs -f
# Stop
docker-compose down</code></pre>
</div>
<h6>Key Files</h6>
<ul class="list-unstyled">
<li><i class="fas fa-file me-1"></i><code>.env</code></li>
<li><i class="fas fa-file me-1"></i><code>docker-compose.yml</code></li>
<li><i class="fas fa-file me-1"></i><code>Dockerfile</code></li>
<li><i class="fas fa-folder me-1"></i><code>./data/</code></li>
</ul>
<h6>Default Ports</h6>
<ul class="list-unstyled">
<li><i class="fas fa-network-wired me-1"></i>8000 (Internal)</li>
<li><i class="fas fa-globe me-1"></i>80/443 (Caddy)</li>
</ul>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -71,13 +71,18 @@
<p class="text-muted mb-3">Start by importing your existing Claude Code conversation history from your <code>~/.claude.json</code> file.</p>
<div class="bg-light p-3 rounded mb-3">
<h6><i class="fas fa-terminal me-2"></i>Steps:</h6>
<ol class="mb-0">
<h6><i class="fas fa-cloud-upload-alt me-2"></i>File Upload Method (Recommended):</h6>
<ol class="mb-2">
<li>Navigate to the <a href="/dashboard/import">Import Data</a> page</li>
<li>Click "Choose File" and select your <code>~/.claude.json</code> file</li>
<li>Click "Import Data" and wait for processing to complete</li>
<li>Review the import summary for any issues</li>
<li>Click "Select .claude.json file" and choose your file</li>
<li>Click "Preview Upload" to review what will be imported</li>
<li>Click "Import Upload" to complete the import</li>
</ol>
<div class="alert alert-success mt-2 mb-0">
<i class="fas fa-lightbulb me-1"></i>
<strong>New:</strong> File upload method works with any .claude.json file and provides detailed previews before importing.
</div>
</div>
<div class="alert alert-info mb-0">

View File

@ -0,0 +1,531 @@
{% extends "base.html" %}
{% block title %}{{ title }}{% endblock %}
{% block content %}
<div class="container-fluid">
<div class="row">
<div class="col-md-12">
<!-- Header -->
<div class="d-flex justify-content-between align-items-center mb-4">
<div>
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="/dashboard/docs">Documentation</a></li>
<li class="breadcrumb-item active" aria-current="page">Complete Hook Reference</li>
</ol>
</nav>
<h2><i class="fas fa-book-open me-3"></i>Complete Hook Reference</h2>
<p class="lead text-muted">Comprehensive guide to all available Claude Code hooks</p>
</div>
<div class="text-muted">
<i class="fas fa-info-circle me-1"></i>
30+ Hook Types
</div>
</div>
<div class="row">
<div class="col-lg-8">
<!-- Quick Overview -->
<div class="card border-0 shadow-sm mb-4">
<div class="card-body">
<h3><i class="fas fa-lightning-bolt me-2 text-primary"></i>Hook Categories Overview</h3>
<p>Claude Code Tracker supports comprehensive development intelligence through these hook categories:</p>
<div class="row">
<div class="col-md-6 col-lg-4 mb-3">
<div class="card border-0 bg-primary bg-opacity-10">
<div class="card-body p-3 text-center">
<i class="fas fa-play-circle fa-2x text-primary mb-2"></i>
<h6>Essential (5)</h6>
<small class="text-muted">Core session & tool tracking</small>
</div>
</div>
</div>
<div class="col-md-6 col-lg-4 mb-3">
<div class="card border-0 bg-warning bg-opacity-10">
<div class="card-body p-3 text-center">
<i class="fas fa-tachometer-alt fa-2x text-warning mb-2"></i>
<h6>Performance (5)</h6>
<small class="text-muted">System & debug monitoring</small>
</div>
</div>
</div>
<div class="col-md-6 col-lg-4 mb-3">
<div class="card border-0 bg-success bg-opacity-10">
<div class="card-body p-3 text-center">
<i class="fas fa-code-branch fa-2x text-success mb-2"></i>
<h6>Code Quality (4)</h6>
<small class="text-muted">Linting, testing, builds</small>
</div>
</div>
</div>
<div class="col-md-6 col-lg-4 mb-3">
<div class="card border-0 bg-info bg-opacity-10">
<div class="card-body p-3 text-center">
<i class="fas fa-project-diagram fa-2x text-info mb-2"></i>
<h6>Workflow (4)</h6>
<small class="text-muted">Development patterns</small>
</div>
</div>
</div>
<div class="col-md-6 col-lg-4 mb-3">
<div class="card border-0 bg-secondary bg-opacity-10">
<div class="card-body p-3 text-center">
<i class="fas fa-users fa-2x text-secondary mb-2"></i>
<h6>Collaboration (4)</h6>
<small class="text-muted">External interactions</small>
</div>
</div>
</div>
<div class="col-md-6 col-lg-4 mb-3">
<div class="card border-0 bg-dark bg-opacity-10">
<div class="card-body p-3 text-center">
<i class="fas fa-brain fa-2x text-dark mb-2"></i>
<h6>Intelligence (5)</h6>
<small class="text-muted">High-level project insights</small>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Essential Hooks -->
<div class="card border-0 shadow-sm mb-4">
<div class="card-header bg-primary text-white">
<h3 class="mb-0"><i class="fas fa-play-circle me-2"></i>Essential Hooks</h3>
</div>
<div class="card-body">
<p class="text-muted mb-4">Core hooks that every user should enable for basic session and development tracking.</p>
<div class="row">
<div class="col-md-6 mb-3">
<div class="card border-0 bg-light">
<div class="card-body">
<h6><code>session_start</code></h6>
<p class="small text-muted mb-2">Triggered when a new Claude Code session begins</p>
<div class="badge bg-success">Required</div>
</div>
</div>
</div>
<div class="col-md-6 mb-3">
<div class="card border-0 bg-light">
<div class="card-body">
<h6><code>session_end</code></h6>
<p class="small text-muted mb-2">Triggered when a Claude Code session ends</p>
<div class="badge bg-success">Required</div>
</div>
</div>
</div>
<div class="col-md-6 mb-3">
<div class="card border-0 bg-light">
<div class="card-body">
<h6><code>conversation_update</code></h6>
<p class="small text-muted mb-2">Logs conversation messages and interactions</p>
<div class="badge bg-warning">Recommended</div>
</div>
</div>
</div>
<div class="col-md-6 mb-3">
<div class="card border-0 bg-light">
<div class="card-body">
<h6><code>tool_call</code></h6>
<p class="small text-muted mb-2">Tracks which tools are used and their performance</p>
<div class="badge bg-warning">Recommended</div>
</div>
</div>
</div>
<div class="col-md-6 mb-3">
<div class="card border-0 bg-light">
<div class="card-body">
<h6><code>file_modified</code></h6>
<p class="small text-muted mb-2">Records file creations, modifications, and deletions</p>
<div class="badge bg-info">Optional</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Performance & Debugging Hooks -->
<div class="card border-0 shadow-sm mb-4">
<div class="card-header bg-warning text-dark">
<h3 class="mb-0"><i class="fas fa-tachometer-alt me-2"></i>Performance & Debugging</h3>
</div>
<div class="card-body">
<p class="text-muted mb-4">Monitor system performance and track debugging activities.</p>
<div class="accordion" id="performanceAccordion">
<div class="accordion-item border-0">
<h2 class="accordion-header">
<button class="accordion-button bg-light" type="button" data-bs-toggle="collapse" data-bs-target="#perf1">
<i class="fas fa-exclamation-triangle me-2 text-danger"></i>
<code>tool_error</code> - Track failed tool calls
</button>
</h2>
<div id="perf1" class="accordion-collapse collapse show" data-bs-parent="#performanceAccordion">
<div class="accordion-body">
<p><strong>Purpose:</strong> Record when tools fail with detailed error information.</p>
<div class="bg-dark text-light p-3 rounded mb-3">
<h6 class="text-light">Hook Configuration:</h6>
<code class="small">
"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\"}'"
</code>
</div>
<p><strong>Variables:</strong> <code>$TOOL_NAME</code>, <code>$ERROR_TYPE</code>, <code>$ERROR_MESSAGE</code>, <code>$STACK_TRACE</code></p>
</div>
</div>
</div>
<div class="accordion-item border-0">
<h2 class="accordion-header">
<button class="accordion-button collapsed bg-light" type="button" data-bs-toggle="collapse" data-bs-target="#perf2">
<i class="fas fa-clock me-2 text-primary"></i>
<code>waiting_period_start/end</code> - Track thinking time
</button>
</h2>
<div id="perf2" class="accordion-collapse collapse" data-bs-parent="#performanceAccordion">
<div class="accordion-body">
<p><strong>Purpose:</strong> Monitor periods when Claude is processing vs actively working.</p>
<div class="bg-dark text-light p-3 rounded mb-3">
<h6 class="text-light">Hook Configurations:</h6>
<code class="small d-block mb-2">
"waiting_period_start": "curl -X POST .../api/hooks/waiting-period -d '{\"reason\": \"thinking\", \"context\": \"$CONTEXT\"}'"
</code>
<code class="small d-block">
"waiting_period_end": "curl -X POST .../api/hooks/waiting-period -d '{\"duration_ms\": $DURATION_MS, \"end_time\": \"$TIMESTAMP\"}'"
</code>
</div>
<p><strong>Use Cases:</strong> Identify bottlenecks, optimize prompts, understand processing patterns</p>
</div>
</div>
</div>
<div class="accordion-item border-0">
<h2 class="accordion-header">
<button class="accordion-button collapsed bg-light" type="button" data-bs-toggle="collapse" data-bs-target="#perf3">
<i class="fas fa-memory me-2 text-info"></i>
<code>memory_usage</code> - Monitor system resources
</button>
</h2>
<div id="perf3" class="accordion-collapse collapse" data-bs-parent="#performanceAccordion">
<div class="accordion-body">
<p><strong>Purpose:</strong> Track memory, CPU, and disk usage during development.</p>
<div class="bg-dark text-light p-3 rounded mb-3">
<h6 class="text-light">Hook Configuration:</h6>
<code class="small">
"memory_usage": "curl -X POST .../api/hooks/performance -d '{\"metric_type\": \"memory\", \"value\": $MEMORY_MB, \"unit\": \"MB\", \"threshold_exceeded\": $THRESHOLD_EXCEEDED}'"
</code>
</div>
<p><strong>Metrics:</strong> memory, cpu, disk, network</p>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Code Quality Hooks -->
<div class="card border-0 shadow-sm mb-4">
<div class="card-header bg-success text-white">
<h3 class="mb-0"><i class="fas fa-code-branch me-2"></i>Code Quality & Testing</h3>
</div>
<div class="card-body">
<p class="text-muted mb-4">Track linting, testing, builds, and dependency changes.</p>
<div class="row">
<div class="col-md-6 mb-3">
<div class="card border-0 bg-light">
<div class="card-body">
<h6><i class="fas fa-search me-2 text-primary"></i><code>code_analysis</code></h6>
<p class="small text-muted">ESLint, Prettier, type checking results</p>
</div>
</div>
</div>
<div class="col-md-6 mb-3">
<div class="card border-0 bg-light">
<div class="card-body">
<h6><i class="fas fa-vial me-2 text-success"></i><code>test_execution</code></h6>
<p class="small text-muted">Unit tests, integration tests, coverage</p>
</div>
</div>
</div>
<div class="col-md-6 mb-3">
<div class="card border-0 bg-light">
<div class="card-body">
<h6><i class="fas fa-hammer me-2 text-warning"></i><code>build_process</code></h6>
<p class="small text-muted">Compilation, bundling, deployment</p>
</div>
</div>
</div>
<div class="col-md-6 mb-3">
<div class="card border-0 bg-light">
<div class="card-body">
<h6><i class="fas fa-boxes me-2 text-info"></i><code>dependency_change</code></h6>
<p class="small text-muted">Package installs, updates, removals</p>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Workflow Hooks -->
<div class="card border-0 shadow-sm mb-4">
<div class="card-header bg-info text-white">
<h3 class="mb-0"><i class="fas fa-project-diagram me-2"></i>Development Workflow</h3>
</div>
<div class="card-body">
<p class="text-muted mb-4">Understand development patterns and workflow efficiency.</p>
<div class="row">
<div class="col-md-6 mb-3">
<div class="card border-0 bg-light">
<div class="card-body">
<h6><i class="fas fa-exchange-alt me-2 text-primary"></i><code>context_switch</code></h6>
<p class="small text-muted">Track project/context changes</p>
<div class="small">
<strong>Impact:</strong> Measure multitasking overhead
</div>
</div>
</div>
</div>
<div class="col-md-6 mb-3">
<div class="card border-0 bg-light">
<div class="card-body">
<h6><i class="fas fa-search me-2 text-success"></i><code>search_query</code></h6>
<p class="small text-muted">What you search for in code/files</p>
<div class="small">
<strong>Insights:</strong> Common patterns, knowledge gaps
</div>
</div>
</div>
</div>
<div class="col-md-6 mb-3">
<div class="card border-0 bg-light">
<div class="card-body">
<h6><i class="fas fa-globe me-2 text-warning"></i><code>browser_tab</code></h6>
<p class="small text-muted">Documentation, StackOverflow visits</p>
<div class="small">
<strong>Analysis:</strong> Research patterns, learning topics
</div>
</div>
</div>
</div>
<div class="col-md-6 mb-3">
<div class="card border-0 bg-light">
<div class="card-body">
<h6><i class="fas fa-copy me-2 text-info"></i><code>copy_paste</code></h6>
<p class="small text-muted">Code copying patterns</p>
<div class="small">
<strong>Quality:</strong> Identify repetitive work
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Pre-configured Setups -->
<div class="card border-0 shadow-sm mb-4">
<div class="card-header bg-dark text-white">
<h3 class="mb-0"><i class="fas fa-download me-2"></i>Pre-configured Hook Setups</h3>
</div>
<div class="card-body">
<p class="text-muted mb-4">Download ready-to-use configurations for different development styles:</p>
<div class="row">
<div class="col-md-6 col-lg-4 mb-3">
<div class="card border-0 bg-primary bg-opacity-10">
<div class="card-body text-center">
<i class="fas fa-rocket fa-2x text-primary mb-2"></i>
<h6>Essential</h6>
<p class="small text-muted">Core tracking only</p>
<a href="/static/claude-hooks-essential.json" download class="btn btn-sm btn-primary">
<i class="fas fa-download me-1"></i>Download
</a>
</div>
</div>
</div>
<div class="col-md-6 col-lg-4 mb-3">
<div class="card border-0 bg-success bg-opacity-10">
<div class="card-body text-center">
<i class="fas fa-code fa-2x text-success mb-2"></i>
<h6>Developer</h6>
<p class="small text-muted">Code quality focused</p>
<a href="/static/claude-hooks-developer.json" download class="btn btn-sm btn-success">
<i class="fas fa-download me-1"></i>Download
</a>
</div>
</div>
</div>
<div class="col-md-6 col-lg-4 mb-3">
<div class="card border-0 bg-warning bg-opacity-10">
<div class="card-body text-center">
<i class="fas fa-bolt fa-2x text-warning mb-2"></i>
<h6>Power User</h6>
<p class="small text-muted">Advanced analytics</p>
<a href="/static/claude-hooks-power_user.json" download class="btn btn-sm btn-warning">
<i class="fas fa-download me-1"></i>Download
</a>
</div>
</div>
</div>
<div class="col-md-6 col-lg-4 mb-3">
<div class="card border-0 bg-info bg-opacity-10">
<div class="card-body text-center">
<i class="fas fa-graduation-cap fa-2x text-info mb-2"></i>
<h6>Research</h6>
<p class="small text-muted">Learning focused</p>
<a href="/static/claude-hooks-research.json" download class="btn btn-sm btn-info">
<i class="fas fa-download me-1"></i>Download
</a>
</div>
</div>
</div>
<div class="col-md-6 col-lg-4 mb-3">
<div class="card border-0 bg-secondary bg-opacity-10">
<div class="card-body text-center">
<i class="fas fa-users fa-2x text-secondary mb-2"></i>
<h6>Team</h6>
<p class="small text-muted">Collaboration tracking</p>
<a href="/static/claude-hooks-team.json" download class="btn btn-sm btn-secondary">
<i class="fas fa-download me-1"></i>Download
</a>
</div>
</div>
</div>
<div class="col-md-6 col-lg-4 mb-3">
<div class="card border-0 bg-dark bg-opacity-10">
<div class="card-body text-center">
<i class="fas fa-cogs fa-2x text-dark mb-2"></i>
<h6>Comprehensive</h6>
<p class="small text-muted">All hooks enabled</p>
<a href="/static/claude-hooks-comprehensive.json" download class="btn btn-sm btn-dark">
<i class="fas fa-download me-1"></i>Download
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Sidebar -->
<div class="col-lg-4">
<div class="sticky-top" style="top: 2rem;">
<!-- Quick Navigation -->
<div class="card border-0 shadow-sm mb-4">
<div class="card-header bg-primary text-white">
<h5 class="mb-0"><i class="fas fa-list me-2"></i>Hook Categories</h5>
</div>
<div class="card-body">
<nav class="nav nav-pills flex-column">
<a class="nav-link py-1 px-2 text-sm" href="#essential">Essential (5)</a>
<a class="nav-link py-1 px-2 text-sm" href="#performance">Performance (5)</a>
<a class="nav-link py-1 px-2 text-sm" href="#code-quality">Code Quality (4)</a>
<a class="nav-link py-1 px-2 text-sm" href="#workflow">Workflow (4)</a>
<a class="nav-link py-1 px-2 text-sm" href="#collaboration">Collaboration (4)</a>
<a class="nav-link py-1 px-2 text-sm" href="#intelligence">Intelligence (5)</a>
<a class="nav-link py-1 px-2 text-sm" href="#environment">Environment (4)</a>
<a class="nav-link py-1 px-2 text-sm" href="#learning">Learning (4)</a>
<a class="nav-link py-1 px-2 text-sm" href="#testing">Testing (4)</a>
</nav>
</div>
</div>
<!-- Hook Statistics -->
<div class="card border-0 shadow-sm mb-4">
<div class="card-header bg-success text-white">
<h6 class="mb-0"><i class="fas fa-chart-bar me-2"></i>Hook Statistics</h6>
</div>
<div class="card-body">
<div class="d-flex justify-content-between align-items-center mb-2">
<span class="small">Total Hooks Available:</span>
<span class="badge bg-primary">39</span>
</div>
<div class="d-flex justify-content-between align-items-center mb-2">
<span class="small">API Endpoints:</span>
<span class="badge bg-success">10</span>
</div>
<div class="d-flex justify-content-between align-items-center mb-2">
<span class="small">Pre-built Configs:</span>
<span class="badge bg-info">7</span>
</div>
<div class="d-flex justify-content-between align-items-center">
<span class="small">Hook Variables:</span>
<span class="badge bg-warning">25+</span>
</div>
</div>
</div>
<!-- Quick Setup -->
<div class="card border-0 shadow-sm mb-4">
<div class="card-header bg-warning text-dark">
<h6 class="mb-0"><i class="fas fa-zap me-2"></i>Quick Setup</h6>
</div>
<div class="card-body">
<ol class="small">
<li>Download a pre-configured setup above</li>
<li>Copy JSON content to your Claude settings</li>
<li>Ensure tracker is running on port 8000</li>
<li>Start Claude Code - hooks activate automatically!</li>
</ol>
<div class="d-grid gap-2 mt-3">
<a href="/dashboard/docs/hook-setup" class="btn btn-sm btn-primary">
<i class="fas fa-cogs me-1"></i>Setup Guide
</a>
<a href="/dashboard/docs/api-reference" class="btn btn-sm btn-outline-info">
<i class="fas fa-code me-1"></i>API Reference
</a>
</div>
</div>
</div>
<!-- Variable Reference -->
<div class="card border-0 shadow-sm">
<div class="card-header bg-info text-white">
<h6 class="mb-0"><i class="fas fa-dollar-sign me-2"></i>Key Variables</h6>
</div>
<div class="card-body">
<div class="small">
<div class="mb-2">
<code>$SESSION_ID</code>
<div class="text-muted">Current session ID</div>
</div>
<div class="mb-2">
<code>$TOOL_NAME</code>
<div class="text-muted">Tool being called</div>
</div>
<div class="mb-2">
<code>$TIMESTAMP</code>
<div class="text-muted">Current timestamp</div>
</div>
<div class="mb-2">
<code>$FILE_PATH</code>
<div class="text-muted">Modified file path</div>
</div>
<div class="mb-2">
<code>$ERROR_MESSAGE</code>
<div class="text-muted">Error details</div>
</div>
<div>
<a href="/dashboard/docs/hook-setup#variables" class="text-decoration-none small">
<i class="fas fa-external-link-alt me-1"></i>
View all variables
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -16,7 +16,7 @@
<div class="row">
<!-- Getting Started -->
<div class="col-md-6 col-lg-3 mb-4">
<div class="col-md-6 col-lg-4 col-xl-3 mb-4">
<div class="card h-100 border-0 shadow-sm">
<div class="card-body d-flex flex-column">
<div class="text-center mb-3">
@ -38,8 +38,54 @@
</div>
</div>
<!-- Data Import -->
<div class="col-md-6 col-lg-4 col-xl-3 mb-4">
<div class="card h-100 border-0 shadow-sm">
<div class="card-body d-flex flex-column">
<div class="text-center mb-3">
<div class="bg-secondary bg-opacity-10 rounded-circle mx-auto d-flex align-items-center justify-content-center" style="width: 60px; height: 60px;">
<i class="fas fa-cloud-upload-alt fa-lg text-secondary"></i>
</div>
</div>
<h5 class="card-title text-center">Data Import Guide</h5>
<p class="card-text text-center text-muted flex-grow-1">
Step-by-step guide to importing your .claude.json file using file upload or file paths.
</p>
<div class="text-center">
<a href="/dashboard/docs/data-import" class="btn btn-secondary">
<i class="fas fa-arrow-right me-1"></i>
Import Data
</a>
</div>
</div>
</div>
</div>
<!-- Docker Deployment -->
<div class="col-md-6 col-lg-4 col-xl-3 mb-4">
<div class="card h-100 border-0 shadow-sm">
<div class="card-body d-flex flex-column">
<div class="text-center mb-3">
<div class="bg-info bg-opacity-10 rounded-circle mx-auto d-flex align-items-center justify-content-center" style="width: 60px; height: 60px;">
<i class="fab fa-docker fa-lg text-info"></i>
</div>
</div>
<h5 class="card-title text-center">Docker Deployment</h5>
<p class="card-text text-center text-muted flex-grow-1">
Deploy Claude Code Tracker using Docker with Caddy reverse proxy integration.
</p>
<div class="text-center">
<a href="/dashboard/docs/docker-deployment" class="btn btn-info">
<i class="fas fa-arrow-right me-1"></i>
Deploy
</a>
</div>
</div>
</div>
</div>
<!-- Hook Setup -->
<div class="col-md-6 col-lg-3 mb-4">
<div class="col-md-6 col-lg-4 col-xl-3 mb-4">
<div class="card h-100 border-0 shadow-sm">
<div class="card-body d-flex flex-column">
<div class="text-center mb-3">
@ -61,13 +107,36 @@
</div>
</div>
<!-- API Reference -->
<div class="col-md-6 col-lg-3 mb-4">
<!-- Hook Reference -->
<div class="col-md-6 col-lg-4 col-xl-3 mb-4">
<div class="card h-100 border-0 shadow-sm">
<div class="card-body d-flex flex-column">
<div class="text-center mb-3">
<div class="bg-info bg-opacity-10 rounded-circle mx-auto d-flex align-items-center justify-content-center" style="width: 60px; height: 60px;">
<i class="fas fa-code fa-lg text-info"></i>
<div class="bg-dark bg-opacity-10 rounded-circle mx-auto d-flex align-items-center justify-content-center" style="width: 60px; height: 60px;">
<i class="fas fa-book-open fa-lg text-dark"></i>
</div>
</div>
<h5 class="card-title text-center">Hook Reference</h5>
<p class="card-text text-center text-muted flex-grow-1">
Complete reference for all 39+ available Claude Code hooks and configurations.
</p>
<div class="text-center">
<a href="/dashboard/docs/hook-reference" class="btn btn-dark">
<i class="fas fa-arrow-right me-1"></i>
Browse Hooks
</a>
</div>
</div>
</div>
</div>
<!-- API Reference -->
<div class="col-md-6 col-lg-4 col-xl-3 mb-4">
<div class="card h-100 border-0 shadow-sm">
<div class="card-body d-flex flex-column">
<div class="text-center mb-3">
<div class="bg-warning bg-opacity-10 rounded-circle mx-auto d-flex align-items-center justify-content-center" style="width: 60px; height: 60px;">
<i class="fas fa-code fa-lg text-warning"></i>
</div>
</div>
<h5 class="card-title text-center">API Reference</h5>
@ -75,7 +144,7 @@
Detailed API documentation for integrating with Claude Code Tracker.
</p>
<div class="text-center">
<a href="/dashboard/docs/api-reference" class="btn btn-info">
<a href="/dashboard/docs/api-reference" class="btn btn-warning">
<i class="fas fa-arrow-right me-1"></i>
View API
</a>
@ -85,12 +154,12 @@
</div>
<!-- FAQ -->
<div class="col-md-6 col-lg-3 mb-4">
<div class="col-md-6 col-lg-4 col-xl-3 mb-4">
<div class="card h-100 border-0 shadow-sm">
<div class="card-body d-flex flex-column">
<div class="text-center mb-3">
<div class="bg-warning bg-opacity-10 rounded-circle mx-auto d-flex align-items-center justify-content-center" style="width: 60px; height: 60px;">
<i class="fas fa-question-circle fa-lg text-warning"></i>
<div class="bg-danger bg-opacity-10 rounded-circle mx-auto d-flex align-items-center justify-content-center" style="width: 60px; height: 60px;">
<i class="fas fa-question-circle fa-lg text-danger"></i>
</div>
</div>
<h5 class="card-title text-center">FAQ</h5>
@ -98,7 +167,7 @@
Frequently asked questions and troubleshooting guide.
</p>
<div class="text-center">
<a href="/dashboard/docs/faq" class="btn btn-warning">
<a href="/dashboard/docs/faq" class="btn btn-danger">
<i class="fas fa-arrow-right me-1"></i>
Get Help
</a>

View File

@ -29,7 +29,56 @@
This will create projects and estimate sessions based on your past usage.
</p>
<!-- Import Form -->
<!-- Import Method Tabs -->
<ul class="nav nav-pills mb-3" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active" id="upload-tab" data-bs-toggle="pill"
data-bs-target="#upload-panel" type="button" role="tab">
<i class="fas fa-cloud-upload-alt me-1"></i>
Upload File
</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="path-tab" data-bs-toggle="pill"
data-bs-target="#path-panel" type="button" role="tab">
<i class="fas fa-folder-open me-1"></i>
File Path
</button>
</li>
</ul>
<div class="tab-content">
<!-- Upload File Panel -->
<div class="tab-pane fade show active" id="upload-panel" role="tabpanel">
<div class="mb-3">
<label for="file-upload" class="form-label">Select .claude.json file</label>
<input type="file" class="form-control" id="file-upload"
accept=".json" onchange="handleFileSelect(event)">
<div class="form-text">
Upload your <code>.claude.json</code> file directly from your computer
</div>
</div>
<div id="file-info" class="alert alert-info" style="display: none;">
<div id="file-details"></div>
</div>
<div class="d-flex gap-2">
<button type="button" class="btn btn-outline-primary" onclick="previewUpload()"
id="preview-upload-btn" disabled>
<i class="fas fa-eye me-1"></i>
Preview Upload
</button>
<button type="button" class="btn btn-primary" onclick="runUpload()"
id="import-upload-btn" disabled>
<i class="fas fa-cloud-upload-alt me-1"></i>
Import Upload
</button>
</div>
</div>
<!-- File Path Panel -->
<div class="tab-pane fade" id="path-panel" role="tabpanel">
<form id="import-form">
<div class="mb-3">
<label for="file-path" class="form-label">File Path (optional)</label>
@ -51,6 +100,8 @@
</button>
</div>
</form>
</div>
</div>
<!-- Results -->
<div id="import-results" class="mt-4" style="display: none;">
@ -122,6 +173,142 @@
{% block scripts %}
<script>
let selectedFile = null;
function handleFileSelect(event) {
const file = event.target.files[0];
selectedFile = file;
if (file) {
// Validate file type
if (!file.name.endsWith('.json')) {
showError('Please select a JSON file (.json)');
resetFileUpload();
return;
}
// Check file size (10MB limit)
const maxSize = 10 * 1024 * 1024; // 10MB
if (file.size > maxSize) {
showError('File too large. Maximum size is 10MB.');
resetFileUpload();
return;
}
// Show file info
const fileInfo = document.getElementById('file-info');
const fileDetails = document.getElementById('file-details');
fileDetails.innerHTML = `
<strong>Selected file:</strong> ${file.name}<br>
<strong>Size:</strong> ${(file.size / 1024).toFixed(1)} KB<br>
<strong>Modified:</strong> ${new Date(file.lastModified).toLocaleString()}
`;
fileInfo.style.display = 'block';
// Enable buttons
document.getElementById('preview-upload-btn').disabled = false;
document.getElementById('import-upload-btn').disabled = false;
} else {
resetFileUpload();
}
}
function resetFileUpload() {
selectedFile = null;
document.getElementById('file-info').style.display = 'none';
document.getElementById('preview-upload-btn').disabled = true;
document.getElementById('import-upload-btn').disabled = true;
}
async function previewUpload() {
if (!selectedFile) {
showError('Please select a file first');
return;
}
const resultsDiv = document.getElementById('import-results');
const resultsContent = document.getElementById('results-content');
// Show loading
resultsContent.innerHTML = `
<div class="text-center py-3">
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Previewing...</span>
</div>
<p class="mt-2 text-muted">Analyzing uploaded file...</p>
</div>
`;
resultsDiv.style.display = 'block';
try {
const formData = new FormData();
formData.append('file', selectedFile);
const response = await fetch('/api/import/claude-json/preview-upload', {
method: 'POST',
body: formData
});
const data = await response.json();
if (response.ok) {
showPreviewResults(data, true); // Pass true to indicate this is an upload
} else {
showError(data.detail || 'Preview failed');
}
} catch (error) {
showError('Network error: ' + error.message);
}
}
async function runUpload() {
if (!selectedFile) {
showError('Please select a file first');
return;
}
// Confirm import
if (!confirm('This will import data into your tracker database. Continue?')) {
return;
}
const resultsDiv = document.getElementById('import-results');
const resultsContent = document.getElementById('results-content');
// Show loading
resultsContent.innerHTML = `
<div class="text-center py-3">
<div class="spinner-border text-success" role="status">
<span class="visually-hidden">Importing...</span>
</div>
<p class="mt-2 text-muted">Importing uploaded file...</p>
</div>
`;
resultsDiv.style.display = 'block';
try {
const formData = new FormData();
formData.append('file', selectedFile);
const response = await fetch('/api/import/claude-json/upload', {
method: 'POST',
body: formData
});
const data = await response.json();
if (response.ok) {
showImportResults(data, true); // Pass true to indicate this is an upload
} else {
showError(data.detail || 'Import failed');
}
} catch (error) {
showError('Network error: ' + error.message);
}
}
async function previewImport() {
const filePath = document.getElementById('file-path').value.trim();
const resultsDiv = document.getElementById('import-results');
@ -204,14 +391,14 @@ async function runImport() {
}
}
function showPreviewResults(data) {
function showPreviewResults(data, isUpload = false) {
const html = `
<div class="alert alert-info">
<h6><i class="fas fa-eye me-1"></i> Import Preview</h6>
<hr>
<div class="row">
<div class="col-md-6">
<p><strong>File:</strong> <code>${data.file_path}</code></p>
<p><strong>File:</strong> <code>${isUpload ? data.file_name : data.file_path}</code></p>
<p><strong>Size:</strong> ${data.file_size_mb} MB</p>
</div>
<div class="col-md-6">
@ -241,7 +428,7 @@ function showPreviewResults(data) {
</div>
<div class="text-center">
<button class="btn btn-success" onclick="runImport()">
<button class="btn btn-success" onclick="${isUpload ? 'runUpload()' : 'runImport()'}">
<i class="fas fa-check me-1"></i>
Looks good - Import this data
</button>
@ -251,13 +438,18 @@ function showPreviewResults(data) {
document.getElementById('results-content').innerHTML = html;
}
function showImportResults(data) {
function showImportResults(data, isUpload = false) {
const results = data.results;
const hasErrors = results.errors && results.errors.length > 0;
let successMessage = '<h6><i class="fas fa-check me-1"></i> Import Completed Successfully!</h6>';
if (isUpload) {
successMessage += `<p class="mb-0"><strong>File:</strong> ${data.file_name} (${data.file_size_kb} KB)</p>`;
}
const html = `
<div class="alert alert-success">
<h6><i class="fas fa-check me-1"></i> Import Completed Successfully!</h6>
${successMessage}
<hr>
<div class="row">
<div class="col-md-4 text-center">

View File

@ -56,9 +56,16 @@ async def init_database():
# Import all models to ensure they're registered
from app.models import (
Project, Session, Conversation, Activity,
WaitingPeriod, GitOperation, ToolCall
WaitingPeriod, GitOperation, ToolCall,
HookEvent, ToolError, WaitingPeriodNew, PerformanceMetric,
CodeQualityEvent, WorkflowEvent, LearningEvent,
EnvironmentEvent, CollaborationEvent, ProjectIntelligence
)
# Initialize hook relationships
from app.models.hooks import add_hook_relationships
add_hook_relationships()
# Create all tables
await conn.run_sync(Base.metadata.create_all)

View File

@ -10,6 +10,11 @@ from .activity import Activity
from .waiting_period import WaitingPeriod
from .git_operation import GitOperation
from .tool_call import ToolCall
from .hooks import (
HookEvent, ToolError, WaitingPeriodNew, PerformanceMetric,
CodeQualityEvent, WorkflowEvent, LearningEvent,
EnvironmentEvent, CollaborationEvent, ProjectIntelligence
)
__all__ = [
"Base",
@ -20,4 +25,14 @@ __all__ = [
"WaitingPeriod",
"GitOperation",
"ToolCall",
"HookEvent",
"ToolError",
"WaitingPeriodNew",
"PerformanceMetric",
"CodeQualityEvent",
"WorkflowEvent",
"LearningEvent",
"EnvironmentEvent",
"CollaborationEvent",
"ProjectIntelligence",
]

225
app/models/hooks.py Normal file
View File

@ -0,0 +1,225 @@
"""
Comprehensive hook tracking models for Claude Code sessions.
"""
from datetime import datetime
from typing import Optional, Dict, Any
from sqlalchemy import Column, Integer, String, Text, DateTime, ForeignKey, Boolean, Float, JSON
from sqlalchemy.orm import relationship
from app.models.base import Base
class HookEvent(Base):
"""
Base model for all hook events with common fields.
"""
__tablename__ = "hook_events"
id = Column(Integer, primary_key=True, index=True)
session_id = Column(String, ForeignKey("sessions.id"), nullable=False, index=True)
hook_type = Column(String(50), nullable=False, index=True)
timestamp = Column(DateTime, nullable=False, default=datetime.utcnow, index=True)
data = Column(JSON, nullable=True) # Flexible JSON data for hook-specific information
# Relationships
session = relationship("Session", back_populates="hook_events")
def __repr__(self):
return f"<HookEvent(id={self.id}, type={self.hook_type}, session={self.session_id})>"
class ToolError(Base):
"""Track failed tool calls with error details."""
__tablename__ = "tool_errors"
id = Column(Integer, primary_key=True, index=True)
session_id = Column(String, ForeignKey("sessions.id"), nullable=False, index=True)
tool_name = Column(String(100), nullable=False, index=True)
error_type = Column(String(100), nullable=False, index=True)
error_message = Column(Text, nullable=False)
stack_trace = Column(Text, nullable=True)
parameters = Column(JSON, nullable=True)
timestamp = Column(DateTime, nullable=False, default=datetime.utcnow, index=True)
session = relationship("Session")
def __repr__(self):
return f"<ToolError(id={self.id}, tool={self.tool_name}, error={self.error_type})>"
class WaitingPeriodNew(Base):
"""Track periods when Claude is thinking vs actively working."""
__tablename__ = "waiting_periods_new"
id = Column(Integer, primary_key=True, index=True)
session_id = Column(String, ForeignKey("sessions.id"), nullable=False, index=True)
start_time = Column(DateTime, nullable=False, default=datetime.utcnow, index=True)
end_time = Column(DateTime, nullable=True)
duration_ms = Column(Integer, nullable=True)
reason = Column(String(100), nullable=True, index=True) # thinking, processing, waiting_for_input
context = Column(Text, nullable=True) # What was happening when waiting started
session = relationship("Session")
def __repr__(self):
return f"<WaitingPeriodNew(id={self.id}, reason={self.reason}, duration={self.duration_ms}ms)>"
class PerformanceMetric(Base):
"""Monitor system performance during development."""
__tablename__ = "performance_metrics"
id = Column(Integer, primary_key=True, index=True)
session_id = Column(String, ForeignKey("sessions.id"), nullable=False, index=True)
metric_type = Column(String(50), nullable=False, index=True) # memory, cpu, disk
value = Column(Float, nullable=False)
unit = Column(String(20), nullable=False) # MB, %, seconds
threshold_exceeded = Column(Boolean, default=False)
timestamp = Column(DateTime, nullable=False, default=datetime.utcnow, index=True)
session = relationship("Session")
def __repr__(self):
return f"<PerformanceMetric(id={self.id}, type={self.metric_type}, value={self.value}{self.unit})>"
class CodeQualityEvent(Base):
"""Track code quality analysis, linting, and testing."""
__tablename__ = "code_quality_events"
id = Column(Integer, primary_key=True, index=True)
session_id = Column(String, ForeignKey("sessions.id"), nullable=False, index=True)
event_type = Column(String(50), nullable=False, index=True) # lint, format, test, build, analysis
file_path = Column(Text, nullable=True)
tool_name = Column(String(100), nullable=True) # eslint, prettier, pytest, etc.
status = Column(String(20), nullable=False, index=True) # success, warning, error
issues_count = Column(Integer, default=0)
details = Column(JSON, nullable=True) # Specific issues, test results, etc.
duration_ms = Column(Integer, nullable=True)
timestamp = Column(DateTime, nullable=False, default=datetime.utcnow, index=True)
session = relationship("Session")
def __repr__(self):
return f"<CodeQualityEvent(id={self.id}, type={self.event_type}, status={self.status})>"
class WorkflowEvent(Base):
"""Track development workflow patterns."""
__tablename__ = "workflow_events"
id = Column(Integer, primary_key=True, index=True)
session_id = Column(String, ForeignKey("sessions.id"), nullable=False, index=True)
event_type = Column(String(50), nullable=False, index=True) # context_switch, search_query, browser_tab, etc.
description = Column(Text, nullable=True)
event_metadata = Column(JSON, nullable=True) # Event-specific data
source = Column(String(100), nullable=True) # Where the event came from
duration_ms = Column(Integer, nullable=True) # For events with duration
timestamp = Column(DateTime, nullable=False, default=datetime.utcnow, index=True)
session = relationship("Session")
def __repr__(self):
return f"<WorkflowEvent(id={self.id}, type={self.event_type})>"
class LearningEvent(Base):
"""Track learning sessions and knowledge acquisition."""
__tablename__ = "learning_events"
id = Column(Integer, primary_key=True, index=True)
session_id = Column(String, ForeignKey("sessions.id"), nullable=False, index=True)
event_type = Column(String(50), nullable=False, index=True) # tutorial, documentation, experimentation
topic = Column(String(200), nullable=True, index=True) # What was being learned
resource_url = Column(Text, nullable=True) # Documentation URL, tutorial link
confidence_before = Column(Integer, nullable=True) # 1-10 scale
confidence_after = Column(Integer, nullable=True) # 1-10 scale
notes = Column(Text, nullable=True)
duration_ms = Column(Integer, nullable=True)
timestamp = Column(DateTime, nullable=False, default=datetime.utcnow, index=True)
session = relationship("Session")
def __repr__(self):
return f"<LearningEvent(id={self.id}, topic={self.topic})>"
class EnvironmentEvent(Base):
"""Track environment and configuration changes."""
__tablename__ = "environment_events"
id = Column(Integer, primary_key=True, index=True)
session_id = Column(String, ForeignKey("sessions.id"), nullable=False, index=True)
event_type = Column(String(50), nullable=False, index=True) # env_change, config_update, security_scan
environment = Column(String(50), nullable=True, index=True) # dev, staging, prod
config_file = Column(Text, nullable=True)
changes = Column(JSON, nullable=True) # What changed
impact_level = Column(String(20), nullable=True) # low, medium, high, critical
timestamp = Column(DateTime, nullable=False, default=datetime.utcnow, index=True)
session = relationship("Session")
def __repr__(self):
return f"<EnvironmentEvent(id={self.id}, type={self.event_type}, env={self.environment})>"
class CollaborationEvent(Base):
"""Track collaboration and external interactions."""
__tablename__ = "collaboration_events"
id = Column(Integer, primary_key=True, index=True)
session_id = Column(String, ForeignKey("sessions.id"), nullable=False, index=True)
event_type = Column(String(50), nullable=False, index=True) # external_resource, ai_question, review_request
interaction_type = Column(String(50), nullable=True) # documentation, stackoverflow, api_docs
query_or_topic = Column(Text, nullable=True)
resource_url = Column(Text, nullable=True)
response_quality = Column(Integer, nullable=True) # 1-5 rating
time_to_resolution = Column(Integer, nullable=True) # minutes
event_metadata = Column(JSON, nullable=True)
timestamp = Column(DateTime, nullable=False, default=datetime.utcnow, index=True)
session = relationship("Session")
def __repr__(self):
return f"<CollaborationEvent(id={self.id}, type={self.event_type})>"
class ProjectIntelligence(Base):
"""Track high-level project development patterns."""
__tablename__ = "project_intelligence"
id = Column(Integer, primary_key=True, index=True)
session_id = Column(String, ForeignKey("sessions.id"), nullable=False, index=True)
event_type = Column(String(50), nullable=False, index=True) # refactor, feature_flag, debugging_session
scope = Column(String(20), nullable=True, index=True) # small, medium, large
complexity = Column(String(20), nullable=True, index=True) # low, medium, high
start_time = Column(DateTime, nullable=False, default=datetime.utcnow)
end_time = Column(DateTime, nullable=True)
duration_minutes = Column(Integer, nullable=True)
files_affected = Column(JSON, nullable=True) # List of file paths
outcome = Column(String(20), nullable=True) # success, partial, failed, abandoned
notes = Column(Text, nullable=True)
timestamp = Column(DateTime, nullable=False, default=datetime.utcnow, index=True)
session = relationship("Session")
def __repr__(self):
return f"<ProjectIntelligence(id={self.id}, type={self.event_type}, scope={self.scope})>"
# Add hook_events relationship to Session model
def add_hook_relationships():
"""Add hook event relationships to the Session model."""
from app.models.session import Session
Session.hook_events = relationship("HookEvent", back_populates="session", cascade="all, delete-orphan")
Session.tool_errors = relationship("ToolError", cascade="all, delete-orphan")
Session.waiting_periods_new = relationship("WaitingPeriodNew", cascade="all, delete-orphan")
Session.performance_metrics = relationship("PerformanceMetric", cascade="all, delete-orphan")
Session.code_quality_events = relationship("CodeQualityEvent", cascade="all, delete-orphan")
Session.workflow_events = relationship("WorkflowEvent", cascade="all, delete-orphan")
Session.learning_events = relationship("LearningEvent", cascade="all, delete-orphan")
Session.environment_events = relationship("EnvironmentEvent", cascade="all, delete-orphan")
Session.collaboration_events = relationship("CollaborationEvent", cascade="all, delete-orphan")
Session.project_intelligence = relationship("ProjectIntelligence", cascade="all, delete-orphan")

9
claude-hooks-basic.json Normal file
View File

@ -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\"}'"
}
}

View File

@ -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"
}
}

View File

@ -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"
}
}

View File

@ -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"
}
}

View File

@ -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"
}
}

View File

@ -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"
}
}

29
claude-hooks-team.json Normal file
View File

@ -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"
}
}

53
docker-compose.yml Normal file
View File

@ -0,0 +1,53 @@
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}}"
# Security and CORS headers for API
# caddy.header./api/*: |
# X-Content-Type-Options nosniff
# X-Frame-Options DENY
# X-XSS-Protection "1; mode=block"
# Referrer-Policy strict-origin-when-cross-origin
# Access-Control-Allow-Origin *
# Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
# Access-Control-Allow-Headers "Content-Type, Authorization, X-Requested-With"
ports:
- "8000:8000"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
deploy:
resources:
limits:
cpus: '1.0'
memory: 512M
reservations:
cpus: '0.25'
memory: 128M
networks:
caddy:
external: true
name: caddy

123
docker-deploy.sh Executable file
View File

@ -0,0 +1,123 @@
#!/bin/bash
# Claude Code Tracker Docker Deployment Script
set -e
echo "🚀 Deploying Claude Code Tracker with Docker..."
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Function to print colored output
print_status() {
echo -e "${BLUE}[INFO]${NC} $1"
}
print_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# Check if .env file exists
if [ ! -f ".env" ]; then
print_warning ".env file not found. Creating from .env.example..."
cp .env.example .env
print_status "Please edit .env file to configure your domain and other settings"
fi
# Check if Caddy network exists
if ! docker network ls | grep -q "caddy"; then
print_warning "Caddy network not found. Creating external network..."
docker network create caddy
print_success "Created 'caddy' external network"
else
print_status "Caddy network already exists"
fi
# Create data directory if it doesn't exist
if [ ! -d "./data" ]; then
print_status "Creating data directory..."
mkdir -p ./data
fi
# Set permissions for data directory
chmod 755 ./data
print_status "Building and starting containers..."
# Build and start the containers
docker-compose up -d --build
# Wait for the service to be ready
print_status "Waiting for service to be ready..."
sleep 10
# Check if the service is healthy
if docker-compose ps | grep -q "Up (healthy)"; then
print_success "Claude Code Tracker is running and healthy!"
else
print_warning "Service is starting up. Checking logs..."
docker-compose logs --tail=20 claude-tracker
fi
# Display useful information
echo ""
echo "📋 Deployment Information:"
echo "=========================="
print_status "Container name: claude-tracker-api"
print_status "Internal port: 8000"
# Read domain from .env file
if [ -f ".env" ]; then
DOMAIN=$(grep "^DOMAIN=" .env | cut -d'=' -f2)
if [ -n "$DOMAIN" ]; then
print_status "External URL: https://$DOMAIN"
else
print_status "External URL: Configure DOMAIN in .env file"
fi
fi
echo ""
echo "🔧 Management Commands:"
echo "======================"
echo "View logs: docker-compose logs -f claude-tracker"
echo "Restart service: docker-compose restart claude-tracker"
echo "Stop service: docker-compose down"
echo "Update service: docker-compose pull && docker-compose up -d"
echo "Shell access: docker-compose exec claude-tracker /bin/bash"
echo ""
echo "📊 Health Check:"
echo "================"
echo "Container status: docker-compose ps"
echo "Health endpoint: curl http://localhost:8000/health"
echo "API documentation: https://$DOMAIN/docs"
echo "Dashboard: https://$DOMAIN/dashboard"
echo ""
echo "🎯 Hook Configuration:"
echo "====================="
echo "Download pre-built hook configs from:"
echo "https://$DOMAIN/dashboard/docs/hook-reference"
echo ""
print_success "Deployment completed! 🎉"
# Check if Caddy is running
if docker ps | grep -q caddy; then
print_success "Caddy reverse proxy detected"
else
print_warning "Caddy reverse proxy not running. Start it to access via domain."
fi

281
generate_hook_config.py Normal file
View File

@ -0,0 +1,281 @@
#!/usr/bin/env python3
"""
Generate comprehensive Claude Code hook configurations.
"""
import json
from typing import Dict, Any
def generate_basic_config() -> Dict[str, Any]:
"""Generate basic hook configuration."""
return {
"hooks": {
# Session Management
"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"}\'',
# Core Interactions
"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 Operations
"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"}\'',
}
}
def generate_comprehensive_config() -> Dict[str, Any]:
"""Generate comprehensive hook configuration with all hook types."""
return {
"hooks": {
# Session Management
"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"}\'',
# Core Interactions
"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 Operations
"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"}\'',
# Performance & Debugging
"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 Quality & Analysis
"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"}}\'',
# Development Workflow
"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}}\'',
# Collaboration & Communication
"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"}}\'',
# Project Intelligence
"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 & Setup
"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 & Knowledge
"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"}\'',
# Quality Assurance
"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"
}
}
def generate_selective_config(categories: list) -> Dict[str, Any]:
"""Generate selective hook configuration based on categories."""
full_config = generate_comprehensive_config()
category_hooks = {
"essential": ["session_start", "session_end", "conversation_update", "tool_call", "file_modified"],
"performance": ["tool_error", "waiting_period_start", "waiting_period_end", "memory_usage", "large_file_warning"],
"code_quality": ["code_analysis", "test_execution", "build_process", "dependency_change"],
"workflow": ["context_switch", "search_query", "browser_tab", "copy_paste"],
"collaboration": ["external_resource", "ai_question", "code_explanation", "review_request"],
"intelligence": ["refactor_start", "refactor_end", "feature_flag", "debugging_session", "documentation_update"],
"environment": ["environment_change", "config_update", "security_scan", "performance_benchmark"],
"learning": ["learning_session", "tutorial_follow", "experimentation", "knowledge_gap"],
"testing": ["manual_testing", "bug_reproduction", "edge_case_testing", "user_feedback"]
}
selected_hooks = set()
for category in categories:
if category in category_hooks:
selected_hooks.update(category_hooks[category])
return {
"hooks": {
hook: full_config["hooks"][hook]
for hook in selected_hooks
if hook in full_config["hooks"]
},
"hook_settings": full_config["hook_settings"]
}
def main():
"""Generate all hook configurations."""
configs = {
"basic": generate_basic_config(),
"comprehensive": generate_comprehensive_config(),
"essential": generate_selective_config(["essential"]),
"developer": generate_selective_config(["essential", "performance", "code_quality"]),
"power_user": generate_selective_config(["essential", "performance", "workflow", "intelligence"]),
"research": generate_selective_config(["essential", "learning", "collaboration", "intelligence"]),
"team": generate_selective_config(["essential", "collaboration", "testing", "intelligence"])
}
# Generate configuration files
for config_name, config_data in configs.items():
filename = f"claude-hooks-{config_name}.json"
with open(filename, "w") as f:
json.dump(config_data, f, indent=2)
print(f"Generated {filename}")
# Generate README for configurations
readme_content = """# Claude Code Hook Configurations
This directory contains various pre-configured hook setups for different use cases:
## Available Configurations
### basic.json
Essential hooks for basic session and tool tracking.
- Session management
- Tool calls
- File modifications
- Conversations
### comprehensive.json
Complete hook setup with all available hook types.
- All performance monitoring
- Code quality tracking
- Learning analytics
- Collaboration insights
- Project intelligence
### essential.json
Minimal setup for core functionality.
### developer.json
Focused on development workflow and code quality.
- Essential hooks
- Performance monitoring
- Code quality checks
### power_user.json
Advanced setup for productivity optimization.
- Essential hooks
- Performance tracking
- Workflow analysis
- Project intelligence
### research.json
Optimized for learning and exploration.
- Essential hooks
- Learning tracking
- External resource usage
- Knowledge gap analysis
### team.json
Team-focused configuration for collaboration.
- Essential hooks
- Collaboration tracking
- Testing workflows
- Project intelligence
## Installation
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!
## Available Hook Variables
Each hook can use these variables that Claude Code provides:
### Session Variables
- `$SESSION_ID` - Current session identifier
- `$TIMESTAMP` - Current timestamp (ISO format)
- `$PWD` - Current working directory
- `$USER` - System username
### 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
### File Variables
- `$FILE_PATH` - Path to modified file
- `$ACTION` - File action (created/modified/deleted)
- `$FILE_SIZE_MB` - File size in megabytes
### 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
### Performance Variables
- `$MEMORY_MB` - Memory usage in MB
- `$DURATION_MS` - Duration in milliseconds
- `$THRESHOLD_EXCEEDED` - Boolean for threshold alerts
And many more! Each hook type has specific variables available.
## Customization
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
## Troubleshooting
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
For more help, see the documentation at `/dashboard/docs/hook-setup`.
"""
with open("README.md", "w") as f:
f.write(readme_content)
print("Generated README.md with configuration guide")
print(f"\\nGenerated {len(configs)} hook configurations:")
for name in configs.keys():
print(f" - claude-hooks-{name}.json")
if __name__ == "__main__":
main()

49
init_db.py Normal file
View File

@ -0,0 +1,49 @@
#!/usr/bin/env python3
"""
Database initialization script for Claude Code Tracker.
This script ensures the database is properly initialized before the application starts.
"""
import asyncio
import os
import sys
from pathlib import Path
# Add the app directory to the Python path
sys.path.append(str(Path(__file__).parent))
from app.database.connection import init_database, engine
async def ensure_database_initialized():
"""Ensure the database is properly initialized."""
try:
print("Initializing database...")
# Create data directory if it doesn't exist
data_dir = Path("/app/data")
data_dir.mkdir(parents=True, exist_ok=True)
# Set permissions on data directory
os.chmod(str(data_dir), 0o777)
# Initialize database
await init_database()
print("Database initialization completed successfully!")
return True
except Exception as e:
print(f"Database initialization failed: {e}")
# Don't exit - let the app try to continue
return False
finally:
# Clean up engine
try:
await engine.dispose()
except:
pass
if __name__ == "__main__":
asyncio.run(ensure_database_initialized())

13
main.py
View File

@ -9,7 +9,7 @@ from fastapi.staticfiles import StaticFiles
from fastapi.responses import RedirectResponse
from app.database.connection import init_database, close_database
from app.api import sessions, conversations, activities, waiting, git, projects, analytics, importer, tool_calls
from app.api import sessions, conversations, activities, waiting, git, projects, analytics, importer, tool_calls, hooks
from app.dashboard.routes import dashboard_router
@ -18,11 +18,21 @@ async def lifespan(app: FastAPI):
"""Application lifespan management."""
# Startup
print("Starting Claude Code Project Tracker...")
try:
await init_database()
print("Database initialized successfully!")
except Exception as e:
print(f"Database initialization failed: {e}")
print("Application will continue with limited functionality...")
yield
# Shutdown
print("Shutting down...")
try:
await close_database()
except Exception as e:
print(f"Error during shutdown: {e}")
# Create FastAPI app
@ -52,6 +62,7 @@ app.include_router(projects.router, prefix="/api", tags=["Projects"])
app.include_router(analytics.router, prefix="/api", tags=["Analytics"])
app.include_router(importer.router, prefix="/api", tags=["Data Import"])
app.include_router(tool_calls.router, prefix="/api", tags=["Tool Calls"])
app.include_router(hooks.router, prefix="/api", tags=["Hooks"])
# Include dashboard routes
app.include_router(dashboard_router, tags=["Dashboard"])