claude-code-tracker/docs/hook-setup.md
Ryan Malloy 44ed9936b7 Initial commit: Claude Code Project Tracker
Add comprehensive development intelligence system that tracks:
- Development sessions with automatic start/stop
- Full conversation history with semantic search
- Tool usage and file operation analytics
- Think time and engagement analysis
- Git activity correlation
- Learning pattern recognition
- Productivity insights and metrics

Features:
- FastAPI backend with SQLite database
- Modern web dashboard with interactive charts
- Claude Code hook integration for automatic tracking
- Comprehensive test suite with 100+ tests
- Complete API documentation (OpenAPI/Swagger)
- Privacy-first design with local data storage

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-11 02:59:21 -06:00

279 lines
10 KiB
Markdown

# Claude Code Hook Setup Guide
This guide explains how to configure Claude Code hooks to automatically track your development sessions with the Project Tracker API.
## Overview
Claude Code hooks are shell commands that execute in response to specific events. We'll configure hooks to send HTTP requests to our tracking API whenever key development events occur.
## Prerequisites
1. **Claude Code Project Tracker** server running on `http://localhost:8000`
2. **curl** or **httpie** available in your shell
3. **jq** for JSON processing (recommended)
## Hook Configuration Location
Claude Code hooks are configured in your settings file:
- **Linux/macOS**: `~/.config/claude-code/settings.json`
- **Windows**: `%APPDATA%\claude-code\settings.json`
## Complete Hook Configuration
Add this hooks section to your Claude Code settings:
```json
{
"hooks": {
"SessionStart": [
{
"matcher": "startup",
"command": "curl -s -X POST http://localhost:8000/api/session/start -H 'Content-Type: application/json' -d '{\"session_type\":\"startup\",\"working_directory\":\"'\"$PWD\"'\",\"git_branch\":\"'$(git branch --show-current 2>/dev/null || echo \"unknown\")'\",\"git_repo\":\"'$(git config --get remote.origin.url 2>/dev/null || echo \"null\")'\",\"environment\":{\"pwd\":\"'\"$PWD\"'\",\"user\":\"'\"$USER\"'\",\"timestamp\":\"'$(date -Iseconds)'\"}}' > /dev/null 2>&1 &"
},
{
"matcher": "resume",
"command": "curl -s -X POST http://localhost:8000/api/session/start -H 'Content-Type: application/json' -d '{\"session_type\":\"resume\",\"working_directory\":\"'\"$PWD\"'\",\"git_branch\":\"'$(git branch --show-current 2>/dev/null || echo \"unknown\")'\",\"git_repo\":\"'$(git config --get remote.origin.url 2>/dev/null || echo \"null\")'\",\"environment\":{\"pwd\":\"'\"$PWD\"'\",\"user\":\"'\"$USER\"'\",\"timestamp\":\"'$(date -Iseconds)'\"}}' > /dev/null 2>&1 &"
},
{
"matcher": "clear",
"command": "curl -s -X POST http://localhost:8000/api/session/start -H 'Content-Type: application/json' -d '{\"session_type\":\"clear\",\"working_directory\":\"'\"$PWD\"'\",\"git_branch\":\"'$(git branch --show-current 2>/dev/null || echo \"unknown\")'\",\"git_repo\":\"'$(git config --get remote.origin.url 2>/dev/null || echo \"null\")'\",\"environment\":{\"pwd\":\"'\"$PWD\"'\",\"user\":\"'\"$USER\"'\",\"timestamp\":\"'$(date -Iseconds)'\"}}' > /dev/null 2>&1 &"
}
],
"UserPromptSubmit": [
{
"command": "echo '{\"session_id\":1,\"timestamp\":\"'$(date -Iseconds)'\",\"user_prompt\":\"'\"$CLAUDE_USER_PROMPT\"'\",\"exchange_type\":\"user_prompt\"}' | curl -s -X POST http://localhost:8000/api/conversation -H 'Content-Type: application/json' -d @- > /dev/null 2>&1 &"
}
],
"Notification": [
{
"command": "curl -s -X POST http://localhost:8000/api/waiting/start -H 'Content-Type: application/json' -d '{\"session_id\":1,\"timestamp\":\"'$(date -Iseconds)'\",\"context_before\":\"Claude is waiting for input\"}' > /dev/null 2>&1 &"
}
],
"PostToolUse": [
{
"matcher": "Edit",
"command": "echo '{\"session_id\":1,\"tool_name\":\"Edit\",\"action\":\"file_edit\",\"file_path\":\"'\"$CLAUDE_TOOL_FILE_PATH\"'\",\"timestamp\":\"'$(date -Iseconds)'\",\"metadata\":{\"success\":true},\"success\":true}' | curl -s -X POST http://localhost:8000/api/activity -H 'Content-Type: application/json' -d @- > /dev/null 2>&1 &"
},
{
"matcher": "Write",
"command": "echo '{\"session_id\":1,\"tool_name\":\"Write\",\"action\":\"file_write\",\"file_path\":\"'\"$CLAUDE_TOOL_FILE_PATH\"'\",\"timestamp\":\"'$(date -Iseconds)'\",\"metadata\":{\"success\":true},\"success\":true}' | curl -s -X POST http://localhost:8000/api/activity -H 'Content-Type: application/json' -d @- > /dev/null 2>&1 &"
},
{
"matcher": "Read",
"command": "echo '{\"session_id\":1,\"tool_name\":\"Read\",\"action\":\"file_read\",\"file_path\":\"'\"$CLAUDE_TOOL_FILE_PATH\"'\",\"timestamp\":\"'$(date -Iseconds)'\",\"metadata\":{\"success\":true},\"success\":true}' | curl -s -X POST http://localhost:8000/api/activity -H 'Content-Type: application/json' -d @- > /dev/null 2>&1 &"
},
{
"matcher": "Bash",
"command": "echo '{\"session_id\":1,\"tool_name\":\"Bash\",\"action\":\"command_execution\",\"timestamp\":\"'$(date -Iseconds)'\",\"metadata\":{\"command\":\"'\"$CLAUDE_BASH_COMMAND\"'\",\"success\":true},\"success\":true}' | curl -s -X POST http://localhost:8000/api/activity -H 'Content-Type: application/json' -d @- > /dev/null 2>&1 &"
},
{
"matcher": "Grep",
"command": "echo '{\"session_id\":1,\"tool_name\":\"Grep\",\"action\":\"search\",\"timestamp\":\"'$(date -Iseconds)'\",\"metadata\":{\"pattern\":\"'\"$CLAUDE_GREP_PATTERN\"'\",\"success\":true},\"success\":true}' | curl -s -X POST http://localhost:8000/api/activity -H 'Content-Type: application/json' -d @- > /dev/null 2>&1 &"
},
{
"matcher": "Glob",
"command": "echo '{\"session_id\":1,\"tool_name\":\"Glob\",\"action\":\"file_search\",\"timestamp\":\"'$(date -Iseconds)'\",\"metadata\":{\"pattern\":\"'\"$CLAUDE_GLOB_PATTERN\"'\",\"success\":true},\"success\":true}' | curl -s -X POST http://localhost:8000/api/activity -H 'Content-Type: application/json' -d @- > /dev/null 2>&1 &"
},
{
"matcher": "Task",
"command": "echo '{\"session_id\":1,\"tool_name\":\"Task\",\"action\":\"subagent_call\",\"timestamp\":\"'$(date -Iseconds)'\",\"metadata\":{\"task_type\":\"'\"$CLAUDE_TASK_TYPE\"'\",\"success\":true},\"success\":true}' | curl -s -X POST http://localhost:8000/api/activity -H 'Content-Type: application/json' -d @- > /dev/null 2>&1 &"
}
],
"Stop": [
{
"command": "echo '{\"session_id\":1,\"timestamp\":\"'$(date -Iseconds)'\",\"claude_response\":\"Response completed\",\"exchange_type\":\"claude_response\"}' | curl -s -X POST http://localhost:8000/api/conversation -H 'Content-Type: application/json' -d @- > /dev/null 2>&1 && curl -s -X POST http://localhost:8000/api/waiting/end -H 'Content-Type: application/json' -d '{\"session_id\":1,\"timestamp\":\"'$(date -Iseconds)'\"}' > /dev/null 2>&1 &"
}
]
}
}
```
## Simplified Hook Configuration
For easier setup, you can use our provided configuration file:
```bash
# Copy the hook configuration to Claude Code settings
cp config/claude-hooks.json ~/.config/claude-code/
```
## Hook Details
### SessionStart Hooks
Triggered when starting Claude Code or resuming a session:
- **startup**: Fresh start of Claude Code
- **resume**: Resuming after --resume flag
- **clear**: Starting after clearing history
**Data Captured:**
- Working directory
- Git branch and repository
- System environment info
- Session type
### UserPromptSubmit Hook
Triggered when you submit a prompt to Claude:
**Data Captured:**
- Your input message
- Timestamp
- Session context
### Notification Hook
Triggered when Claude is waiting for input:
**Data Captured:**
- Wait start time
- Context before waiting
### PostToolUse Hooks
Triggered after successful tool execution:
**Tools Tracked:**
- **Edit/Write**: File modifications
- **Read**: File examinations
- **Bash**: Command executions
- **Grep/Glob**: Search operations
- **Task**: Subagent usage
**Data Captured:**
- Tool name and action
- Target files
- Success/failure status
- Tool-specific metadata
### Stop Hook
Triggered when Claude finishes responding:
**Data Captured:**
- Response completion
- End of waiting period
- Session activity summary
## Testing Hook Configuration
1. **Start the tracker server:**
```bash
python main.py
```
2. **Verify hooks are working:**
```bash
# Check server logs for incoming requests
tail -f tracker.log
# Test a simple operation in Claude Code
# You should see API calls in the logs
```
3. **Manual hook testing:**
```bash
# Test session start hook
curl -X POST http://localhost:8000/api/session/start \
-H 'Content-Type: application/json' \
-d '{"session_type":"startup","working_directory":"'$(pwd)'"}'
```
## Environment Variables
The hooks can use these Claude Code environment variables:
- `$CLAUDE_USER_PROMPT` - User's input message
- `$CLAUDE_TOOL_FILE_PATH` - File path for file operations
- `$CLAUDE_BASH_COMMAND` - Bash command being executed
- `$CLAUDE_GREP_PATTERN` - Search pattern for Grep
- `$CLAUDE_GLOB_PATTERN` - File pattern for Glob
- `$CLAUDE_TASK_TYPE` - Type of Task/subagent
## Troubleshooting
### Hooks Not Firing
1. **Check Claude Code settings syntax:**
```bash
# Validate JSON syntax
python -m json.tool ~/.config/claude-code/settings.json
```
2. **Verify tracker server is running:**
```bash
curl http://localhost:8000/api/projects
```
3. **Check hook command syntax:**
```bash
# Test commands manually in shell
echo "Testing hook command..."
```
### Missing Data
1. **Session ID issues**: The static `session_id: 1` in examples needs dynamic generation
2. **JSON escaping**: Special characters in prompts/paths may break JSON
3. **Network issues**: Hooks may fail if server is unreachable
### Performance Impact
- Hooks run asynchronously (`&` at end of commands)
- Failed hook calls don't interrupt Claude Code operation
- Network timeouts are handled gracefully
## Advanced Configuration
### Dynamic Session IDs
For production use, implement session ID management:
```bash
# Store session ID in temp file
CLAUDE_SESSION_FILE="/tmp/claude-session-id"
# In SessionStart hook:
SESSION_ID=$(curl -s ... | jq -r '.session_id')
echo $SESSION_ID > $CLAUDE_SESSION_FILE
# In other hooks:
SESSION_ID=$(cat $CLAUDE_SESSION_FILE 2>/dev/null || echo "1")
```
### Conditional Hook Execution
Skip tracking for certain directories:
```bash
# Only track in specific directories
if [[ "$PWD" =~ "/projects/" ]]; then
curl -X POST ...
fi
```
### Error Handling
Add error logging to hooks:
```bash
curl ... 2>> ~/claude-tracker-errors.log || echo "Hook failed: $(date)" >> ~/claude-tracker-errors.log
```
## Security Considerations
- Hooks execute with your shell privileges
- API calls are made to localhost only
- No sensitive data is transmitted externally
- Hook commands are logged in shell history
## Next Steps
After setting up hooks:
1. Start using Claude Code normally
2. Check the web dashboard at http://localhost:8000
3. Review captured data and analytics
4. Adjust hook configuration as needed
For detailed API documentation, see [API Specification](api-spec.yaml).