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:
parent
bec1606c86
commit
50c80596d0
87
.dockerignore
Normal file
87
.dockerignore
Normal 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/
|
32
.env.example
32
.env.example
@ -1,10 +1,18 @@
|
|||||||
# Database
|
# Claude Code Tracker Configuration
|
||||||
DATABASE_URL=sqlite+aiosqlite:///./data/tracker.db
|
|
||||||
|
|
||||||
# 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_HOST=0.0.0.0
|
||||||
API_PORT=8000
|
API_PORT=8000
|
||||||
DEBUG=true
|
|
||||||
|
# Data storage path (host directory to bind mount)
|
||||||
|
DATA_PATH=./data
|
||||||
|
|
||||||
# Security (generate with: openssl rand -hex 32)
|
# Security (generate with: openssl rand -hex 32)
|
||||||
SECRET_KEY=your-secret-key-here
|
SECRET_KEY=your-secret-key-here
|
||||||
@ -17,3 +25,19 @@ ANALYTICS_BATCH_SIZE=1000
|
|||||||
# Logging
|
# Logging
|
||||||
LOG_LEVEL=INFO
|
LOG_LEVEL=INFO
|
||||||
LOG_FILE=tracker.log
|
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
345
DOCKER.md
Normal 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
53
Dockerfile
Normal 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
214
README.md
@ -1,146 +1,116 @@
|
|||||||
# Claude Code Project Tracker
|
# Claude Code Hook Configurations
|
||||||
|
|
||||||
A comprehensive development intelligence system that tracks your Claude Code sessions, providing insights into your coding patterns, productivity, and learning journey.
|
This directory contains various pre-configured hook setups for different use cases:
|
||||||
|
|
||||||
## Overview
|
## Available Configurations
|
||||||
|
|
||||||
The Claude Code Project Tracker automatically captures your development workflow through Claude Code's hook system, creating a detailed record of:
|
### basic.json
|
||||||
|
Essential hooks for basic session and tool tracking.
|
||||||
|
- Session management
|
||||||
|
- Tool calls
|
||||||
|
- File modifications
|
||||||
|
- Conversations
|
||||||
|
|
||||||
- **Development Sessions** - When you start/stop working, what projects you focus on
|
### comprehensive.json
|
||||||
- **Conversations** - Full dialogue history with Claude for context and learning analysis
|
Complete hook setup with all available hook types.
|
||||||
- **Code Changes** - File modifications, tool usage, and command executions
|
- All performance monitoring
|
||||||
- **Thinking Patterns** - Wait times between interactions to understand your workflow
|
- Code quality tracking
|
||||||
- **Git Activity** - Repository changes, commits, and branch operations
|
- Learning analytics
|
||||||
- **Productivity Metrics** - Engagement levels, output quality, and learning velocity
|
- Collaboration insights
|
||||||
|
- Project intelligence
|
||||||
|
|
||||||
## Architecture
|
### essential.json
|
||||||
|
Minimal setup for core functionality.
|
||||||
|
|
||||||
```
|
### developer.json
|
||||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
Focused on development workflow and code quality.
|
||||||
│ Claude Code │───▶│ Hook System │───▶│ FastAPI Server │
|
- Essential hooks
|
||||||
│ (your IDE) │ │ │ │ │
|
- Performance monitoring
|
||||||
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
- Code quality checks
|
||||||
│
|
|
||||||
▼
|
|
||||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
|
||||||
│ Web Dashboard │◀───│ Analytics │◀───│ SQLite Database │
|
|
||||||
│ │ │ Engine │ │ │
|
|
||||||
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
### 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
|
### research.json
|
||||||
- **SQLite Database**: Local storage for all tracking data
|
Optimized for learning and exploration.
|
||||||
- **Hook Integration**: Claude Code hooks that capture development events
|
- Essential hooks
|
||||||
- **Analytics Engine**: Processes raw data into meaningful insights
|
- Learning tracking
|
||||||
- **Web Dashboard**: Interactive interface for exploring your development patterns
|
- 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
|
## Installation
|
||||||
- Automatic project detection and session management
|
|
||||||
- Working directory and git branch context
|
|
||||||
- Session duration and engagement analysis
|
|
||||||
|
|
||||||
### 💬 Conversation Intelligence
|
1. Choose the configuration that matches your needs
|
||||||
- Full dialogue history with semantic search
|
2. Copy the JSON content to your Claude Code settings file:
|
||||||
- Problem-solving pattern recognition
|
- macOS/Linux: `~/.config/claude/settings.json`
|
||||||
- Learning topic identification and progress tracking
|
- 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
|
## Available Hook Variables
|
||||||
- Productivity metrics and engagement scoring
|
|
||||||
- Tool usage patterns and optimization insights
|
|
||||||
- Cross-project learning and code reuse analysis
|
|
||||||
|
|
||||||
### 🔍 Advanced Insights
|
Each hook can use these variables that Claude Code provides:
|
||||||
- Think time analysis and flow state detection
|
|
||||||
- Git activity correlation with conversations
|
|
||||||
- Skill development velocity tracking
|
|
||||||
- Workflow optimization recommendations
|
|
||||||
|
|
||||||
## 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
|
### Tool Variables
|
||||||
- **No External Services**: No data transmission to third parties
|
- `$TOOL_NAME` - Name of tool being called
|
||||||
- **Full Control**: Complete ownership of your development history
|
- `$TOOL_PARAMS` - Tool parameters (JSON)
|
||||||
- **Selective Tracking**: Configurable hook activation per project
|
- `$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**
|
### Context Variables
|
||||||
```bash
|
- `$CONTENT` - Conversation content
|
||||||
pip install -r requirements.txt
|
- `$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**
|
### Performance Variables
|
||||||
```bash
|
- `$MEMORY_MB` - Memory usage in MB
|
||||||
python main.py
|
- `$DURATION_MS` - Duration in milliseconds
|
||||||
```
|
- `$THRESHOLD_EXCEEDED` - Boolean for threshold alerts
|
||||||
|
|
||||||
3. **Configure Claude Code Hooks**
|
And many more! Each hook type has specific variables available.
|
||||||
```bash
|
|
||||||
# Add hooks to your Claude Code settings
|
|
||||||
cp config/claude-hooks.json ~/.config/claude-code/
|
|
||||||
```
|
|
||||||
|
|
||||||
4. **Access Dashboard**
|
## Customization
|
||||||
```
|
|
||||||
Open http://localhost:8000 in your browser
|
|
||||||
```
|
|
||||||
|
|
||||||
## 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
|
||||||
|
|
||||||
```
|
## Troubleshooting
|
||||||
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
|
|
||||||
```
|
|
||||||
|
|
||||||
## 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
|
For more help, see the documentation at `/dashboard/docs/hook-setup`.
|
||||||
- [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
|
|
||||||
|
619
app/api/hooks.py
Normal file
619
app/api/hooks.py
Normal 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)}")
|
@ -11,7 +11,7 @@ from datetime import datetime, timedelta
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Dict, List, Optional, Any
|
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.ext.asyncio import AsyncSession
|
||||||
from sqlalchemy import select
|
from sqlalchemy import select
|
||||||
|
|
||||||
@ -40,6 +40,19 @@ class ClaudeJsonImporter:
|
|||||||
except json.JSONDecodeError as e:
|
except json.JSONDecodeError as e:
|
||||||
raise ValueError(f"Invalid JSON in Claude configuration file: {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 = {
|
results = {
|
||||||
"projects_imported": 0,
|
"projects_imported": 0,
|
||||||
"sessions_estimated": 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")
|
@router.get("/import/claude-json/preview")
|
||||||
async def preview_claude_json_import(
|
async def preview_claude_json_import(
|
||||||
file_path: Optional[str] = None
|
file_path: Optional[str] = None
|
||||||
@ -388,3 +459,70 @@ async def preview_claude_json_import(
|
|||||||
preview["history_entries"] = total_history
|
preview["history_entries"] = total_history
|
||||||
|
|
||||||
return preview
|
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
|
@ -96,10 +96,22 @@ async def dashboard_docs_section(request: Request, section: str, db: AsyncSessio
|
|||||||
"template": "docs/getting-started.html",
|
"template": "docs/getting-started.html",
|
||||||
"title": "Getting Started - Claude Code Tracker"
|
"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": {
|
"hook-setup": {
|
||||||
"template": "docs/hook-setup.html",
|
"template": "docs/hook-setup.html",
|
||||||
"title": "Hook Setup Guide - Claude Code Tracker"
|
"title": "Hook Setup Guide - Claude Code Tracker"
|
||||||
},
|
},
|
||||||
|
"hook-reference": {
|
||||||
|
"template": "docs/hook-reference.html",
|
||||||
|
"title": "Complete Hook Reference - Claude Code Tracker"
|
||||||
|
},
|
||||||
"api-reference": {
|
"api-reference": {
|
||||||
"template": "docs/api-reference.html",
|
"template": "docs/api-reference.html",
|
||||||
"title": "API Reference - Claude Code Tracker"
|
"title": "API Reference - Claude Code Tracker"
|
||||||
|
9
app/dashboard/static/claude-hooks-basic.json
Normal file
9
app/dashboard/static/claude-hooks-basic.json
Normal 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\"}'"
|
||||||
|
}
|
||||||
|
}
|
50
app/dashboard/static/claude-hooks-comprehensive.json
Normal file
50
app/dashboard/static/claude-hooks-comprehensive.json
Normal 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"
|
||||||
|
}
|
||||||
|
}
|
25
app/dashboard/static/claude-hooks-developer.json
Normal file
25
app/dashboard/static/claude-hooks-developer.json
Normal 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"
|
||||||
|
}
|
||||||
|
}
|
16
app/dashboard/static/claude-hooks-essential.json
Normal file
16
app/dashboard/static/claude-hooks-essential.json
Normal 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"
|
||||||
|
}
|
||||||
|
}
|
30
app/dashboard/static/claude-hooks-power_user.json
Normal file
30
app/dashboard/static/claude-hooks-power_user.json
Normal 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"
|
||||||
|
}
|
||||||
|
}
|
29
app/dashboard/static/claude-hooks-research.json
Normal file
29
app/dashboard/static/claude-hooks-research.json
Normal 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
app/dashboard/static/claude-hooks-team.json
Normal file
29
app/dashboard/static/claude-hooks-team.json
Normal 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"
|
||||||
|
}
|
||||||
|
}
|
562
app/dashboard/templates/docs/data-import.html
Normal file
562
app/dashboard/templates/docs/data-import.html
Normal 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 %}
|
415
app/dashboard/templates/docs/docker-deployment.html
Normal file
415
app/dashboard/templates/docs/docker-deployment.html
Normal 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 <repository-url> 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 %}
|
@ -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>
|
<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">
|
<div class="bg-light p-3 rounded mb-3">
|
||||||
<h6><i class="fas fa-terminal me-2"></i>Steps:</h6>
|
<h6><i class="fas fa-cloud-upload-alt me-2"></i>File Upload Method (Recommended):</h6>
|
||||||
<ol class="mb-0">
|
<ol class="mb-2">
|
||||||
<li>Navigate to the <a href="/dashboard/import">Import Data</a> page</li>
|
<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 "Select .claude.json file" and choose your file</li>
|
||||||
<li>Click "Import Data" and wait for processing to complete</li>
|
<li>Click "Preview Upload" to review what will be imported</li>
|
||||||
<li>Review the import summary for any issues</li>
|
<li>Click "Import Upload" to complete the import</li>
|
||||||
</ol>
|
</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>
|
||||||
|
|
||||||
<div class="alert alert-info mb-0">
|
<div class="alert alert-info mb-0">
|
||||||
|
531
app/dashboard/templates/docs/hook-reference.html
Normal file
531
app/dashboard/templates/docs/hook-reference.html
Normal 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 %}
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<!-- Getting Started -->
|
<!-- 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 h-100 border-0 shadow-sm">
|
||||||
<div class="card-body d-flex flex-column">
|
<div class="card-body d-flex flex-column">
|
||||||
<div class="text-center mb-3">
|
<div class="text-center mb-3">
|
||||||
@ -38,8 +38,54 @@
|
|||||||
</div>
|
</div>
|
||||||
</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 -->
|
<!-- 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 h-100 border-0 shadow-sm">
|
||||||
<div class="card-body d-flex flex-column">
|
<div class="card-body d-flex flex-column">
|
||||||
<div class="text-center mb-3">
|
<div class="text-center mb-3">
|
||||||
@ -61,13 +107,36 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- API Reference -->
|
<!-- Hook Reference -->
|
||||||
<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 h-100 border-0 shadow-sm">
|
||||||
<div class="card-body d-flex flex-column">
|
<div class="card-body d-flex flex-column">
|
||||||
<div class="text-center mb-3">
|
<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;">
|
<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-code fa-lg text-info"></i>
|
<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>
|
||||||
</div>
|
</div>
|
||||||
<h5 class="card-title text-center">API Reference</h5>
|
<h5 class="card-title text-center">API Reference</h5>
|
||||||
@ -75,7 +144,7 @@
|
|||||||
Detailed API documentation for integrating with Claude Code Tracker.
|
Detailed API documentation for integrating with Claude Code Tracker.
|
||||||
</p>
|
</p>
|
||||||
<div class="text-center">
|
<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>
|
<i class="fas fa-arrow-right me-1"></i>
|
||||||
View API
|
View API
|
||||||
</a>
|
</a>
|
||||||
@ -85,12 +154,12 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- FAQ -->
|
<!-- 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 h-100 border-0 shadow-sm">
|
||||||
<div class="card-body d-flex flex-column">
|
<div class="card-body d-flex flex-column">
|
||||||
<div class="text-center mb-3">
|
<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;">
|
<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-warning"></i>
|
<i class="fas fa-question-circle fa-lg text-danger"></i>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<h5 class="card-title text-center">FAQ</h5>
|
<h5 class="card-title text-center">FAQ</h5>
|
||||||
@ -98,7 +167,7 @@
|
|||||||
Frequently asked questions and troubleshooting guide.
|
Frequently asked questions and troubleshooting guide.
|
||||||
</p>
|
</p>
|
||||||
<div class="text-center">
|
<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>
|
<i class="fas fa-arrow-right me-1"></i>
|
||||||
Get Help
|
Get Help
|
||||||
</a>
|
</a>
|
||||||
|
@ -29,7 +29,56 @@
|
|||||||
This will create projects and estimate sessions based on your past usage.
|
This will create projects and estimate sessions based on your past usage.
|
||||||
</p>
|
</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">
|
<form id="import-form">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="file-path" class="form-label">File Path (optional)</label>
|
<label for="file-path" class="form-label">File Path (optional)</label>
|
||||||
@ -51,6 +100,8 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Results -->
|
<!-- Results -->
|
||||||
<div id="import-results" class="mt-4" style="display: none;">
|
<div id="import-results" class="mt-4" style="display: none;">
|
||||||
@ -122,6 +173,142 @@
|
|||||||
|
|
||||||
{% block scripts %}
|
{% block scripts %}
|
||||||
<script>
|
<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() {
|
async function previewImport() {
|
||||||
const filePath = document.getElementById('file-path').value.trim();
|
const filePath = document.getElementById('file-path').value.trim();
|
||||||
const resultsDiv = document.getElementById('import-results');
|
const resultsDiv = document.getElementById('import-results');
|
||||||
@ -204,14 +391,14 @@ async function runImport() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function showPreviewResults(data) {
|
function showPreviewResults(data, isUpload = false) {
|
||||||
const html = `
|
const html = `
|
||||||
<div class="alert alert-info">
|
<div class="alert alert-info">
|
||||||
<h6><i class="fas fa-eye me-1"></i> Import Preview</h6>
|
<h6><i class="fas fa-eye me-1"></i> Import Preview</h6>
|
||||||
<hr>
|
<hr>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-6">
|
<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>
|
<p><strong>Size:</strong> ${data.file_size_mb} MB</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
@ -241,7 +428,7 @@ function showPreviewResults(data) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="text-center">
|
<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>
|
<i class="fas fa-check me-1"></i>
|
||||||
Looks good - Import this data
|
Looks good - Import this data
|
||||||
</button>
|
</button>
|
||||||
@ -251,13 +438,18 @@ function showPreviewResults(data) {
|
|||||||
document.getElementById('results-content').innerHTML = html;
|
document.getElementById('results-content').innerHTML = html;
|
||||||
}
|
}
|
||||||
|
|
||||||
function showImportResults(data) {
|
function showImportResults(data, isUpload = false) {
|
||||||
const results = data.results;
|
const results = data.results;
|
||||||
const hasErrors = results.errors && results.errors.length > 0;
|
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 = `
|
const html = `
|
||||||
<div class="alert alert-success">
|
<div class="alert alert-success">
|
||||||
<h6><i class="fas fa-check me-1"></i> Import Completed Successfully!</h6>
|
${successMessage}
|
||||||
<hr>
|
<hr>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-4 text-center">
|
<div class="col-md-4 text-center">
|
||||||
|
@ -56,9 +56,16 @@ async def init_database():
|
|||||||
# Import all models to ensure they're registered
|
# Import all models to ensure they're registered
|
||||||
from app.models import (
|
from app.models import (
|
||||||
Project, Session, Conversation, Activity,
|
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
|
# Create all tables
|
||||||
await conn.run_sync(Base.metadata.create_all)
|
await conn.run_sync(Base.metadata.create_all)
|
||||||
|
|
||||||
|
@ -10,6 +10,11 @@ from .activity import Activity
|
|||||||
from .waiting_period import WaitingPeriod
|
from .waiting_period import WaitingPeriod
|
||||||
from .git_operation import GitOperation
|
from .git_operation import GitOperation
|
||||||
from .tool_call import ToolCall
|
from .tool_call import ToolCall
|
||||||
|
from .hooks import (
|
||||||
|
HookEvent, ToolError, WaitingPeriodNew, PerformanceMetric,
|
||||||
|
CodeQualityEvent, WorkflowEvent, LearningEvent,
|
||||||
|
EnvironmentEvent, CollaborationEvent, ProjectIntelligence
|
||||||
|
)
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"Base",
|
"Base",
|
||||||
@ -20,4 +25,14 @@ __all__ = [
|
|||||||
"WaitingPeriod",
|
"WaitingPeriod",
|
||||||
"GitOperation",
|
"GitOperation",
|
||||||
"ToolCall",
|
"ToolCall",
|
||||||
|
"HookEvent",
|
||||||
|
"ToolError",
|
||||||
|
"WaitingPeriodNew",
|
||||||
|
"PerformanceMetric",
|
||||||
|
"CodeQualityEvent",
|
||||||
|
"WorkflowEvent",
|
||||||
|
"LearningEvent",
|
||||||
|
"EnvironmentEvent",
|
||||||
|
"CollaborationEvent",
|
||||||
|
"ProjectIntelligence",
|
||||||
]
|
]
|
225
app/models/hooks.py
Normal file
225
app/models/hooks.py
Normal 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
9
claude-hooks-basic.json
Normal 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\"}'"
|
||||||
|
}
|
||||||
|
}
|
50
claude-hooks-comprehensive.json
Normal file
50
claude-hooks-comprehensive.json
Normal 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"
|
||||||
|
}
|
||||||
|
}
|
25
claude-hooks-developer.json
Normal file
25
claude-hooks-developer.json
Normal 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"
|
||||||
|
}
|
||||||
|
}
|
16
claude-hooks-essential.json
Normal file
16
claude-hooks-essential.json
Normal 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"
|
||||||
|
}
|
||||||
|
}
|
30
claude-hooks-power_user.json
Normal file
30
claude-hooks-power_user.json
Normal 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"
|
||||||
|
}
|
||||||
|
}
|
29
claude-hooks-research.json
Normal file
29
claude-hooks-research.json
Normal 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
29
claude-hooks-team.json
Normal 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
53
docker-compose.yml
Normal 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
123
docker-deploy.sh
Executable 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
281
generate_hook_config.py
Normal 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
49
init_db.py
Normal 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
13
main.py
@ -9,7 +9,7 @@ from fastapi.staticfiles import StaticFiles
|
|||||||
from fastapi.responses import RedirectResponse
|
from fastapi.responses import RedirectResponse
|
||||||
|
|
||||||
from app.database.connection import init_database, close_database
|
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
|
from app.dashboard.routes import dashboard_router
|
||||||
|
|
||||||
|
|
||||||
@ -18,11 +18,21 @@ async def lifespan(app: FastAPI):
|
|||||||
"""Application lifespan management."""
|
"""Application lifespan management."""
|
||||||
# Startup
|
# Startup
|
||||||
print("Starting Claude Code Project Tracker...")
|
print("Starting Claude Code Project Tracker...")
|
||||||
|
try:
|
||||||
await init_database()
|
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
|
yield
|
||||||
|
|
||||||
# Shutdown
|
# Shutdown
|
||||||
print("Shutting down...")
|
print("Shutting down...")
|
||||||
|
try:
|
||||||
await close_database()
|
await close_database()
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error during shutdown: {e}")
|
||||||
|
|
||||||
|
|
||||||
# Create FastAPI app
|
# 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(analytics.router, prefix="/api", tags=["Analytics"])
|
||||||
app.include_router(importer.router, prefix="/api", tags=["Data Import"])
|
app.include_router(importer.router, prefix="/api", tags=["Data Import"])
|
||||||
app.include_router(tool_calls.router, prefix="/api", tags=["Tool Calls"])
|
app.include_router(tool_calls.router, prefix="/api", tags=["Tool Calls"])
|
||||||
|
app.include_router(hooks.router, prefix="/api", tags=["Hooks"])
|
||||||
|
|
||||||
# Include dashboard routes
|
# Include dashboard routes
|
||||||
app.include_router(dashboard_router, tags=["Dashboard"])
|
app.include_router(dashboard_router, tags=["Dashboard"])
|
||||||
|
Loading…
x
Reference in New Issue
Block a user