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>
279 lines
10 KiB
Markdown
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). |