Use this file to discover all available pages before exploring further.
This cookbook shows how to use hooks to track Droid usage, collect development metrics, analyze patterns, and generate insights about your development workflow.
# Most edited filessqlite3 ~/.factory/file-changes.db \ "SELECT file_path, COUNT(*) as edits FROM file_changes GROUP BY file_path ORDER BY edits DESC LIMIT 10;"# Files edited by typesqlite3 ~/.factory/file-changes.db \ "SELECT file_type, COUNT(*) as count FROM file_changes GROUP BY file_type ORDER BY count DESC;"# Activity by projectsqlite3 ~/.factory/file-changes.db \ "SELECT project, COUNT(*) as changes FROM file_changes GROUP BY project ORDER BY changes DESC;"
# Average session durationsqlite3 ~/.factory/sessions.db \ "SELECT AVG(duration_seconds) / 60.0 as avg_minutes FROM sessions WHERE duration_seconds IS NOT NULL;"# Sessions by exit reasonsqlite3 ~/.factory/sessions.db \ "SELECT reason, COUNT(*) as count FROM sessions GROUP BY reason ORDER BY count DESC;"# Longest sessionssqlite3 ~/.factory/sessions.db \ "SELECT session_id, duration_seconds / 60.0 as minutes FROM sessions ORDER BY duration_seconds DESC LIMIT 10;"
Track when Droid is used most:Create .factory/hooks/usage-heatmap.py:
#!/usr/bin/env python3"""Generate usage heatmap showing when Droid is used most."""import jsonimport sysimport sqlite3from datetime import datetimefrom collections import defaultdictdef generate_heatmap(): """Create a heatmap of Droid usage by hour and day.""" db_path = os.path.expanduser('~/.factory/sessions.db') if not os.path.exists(db_path): return conn = sqlite3.connect(db_path) cursor = conn.cursor() # Get all session starts cursor.execute("SELECT start_time FROM sessions WHERE start_time IS NOT NULL") # Count by day of week and hour heatmap = defaultdict(lambda: defaultdict(int)) for (start_time,) in cursor.fetchall(): try: dt = datetime.fromisoformat(start_time.replace('Z', '+00:00')) day = dt.strftime('%A') hour = dt.hour heatmap[day][hour] += 1 except: continue conn.close() # Print heatmap days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'] hours = range(24) print("\n📊 Droid Usage Heatmap") print("=" * 80) print(f"{'Day':<12} {'Morning (6-12)':<15} {'Afternoon (12-18)':<15} {'Evening (18-24)':<15}") print("-" * 80) for day in days: morning = sum(heatmap[day][h] for h in range(6, 12)) afternoon = sum(heatmap[day][h] for h in range(12, 18)) evening = sum(heatmap[day][h] for h in range(18, 24)) print(f"{day:<12} {morning:<15} {afternoon:<15} {evening:<15}") print("=" * 80)if __name__ == '__main__': import os generate_heatmap()
chmod +x .factory/hooks/usage-heatmap.py
Run periodically:
# Add to weekly report~/.factory/hooks/usage-heatmap.py
#!/bin/bash# This hook measures its own performance and logs itstart_time=$(date +%s.%N)input=$(cat)hook_event=$(echo "$input" | jq -r '.hook_event_name')tool_name=$(echo "$input" | jq -r '.tool_name // "none"')# Simulate your actual hook work here# ...end_time=$(date +%s.%N)duration=$(echo "$end_time - $start_time" | bc)# Log performanceperf_log="$HOME/.factory/hook-performance.log"timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")echo "$timestamp $hook_event $tool_name ${duration}s" >> "$perf_log"# Warn if hook is slowif (( $(echo "$duration > 1.0" | bc -l) )); then echo "⚠️ Hook took ${duration}s to execute (>1s threshold)" >&2fiexit 0
Analyze performance:
# Slowest hookssort -k4 -rn ~/.factory/hook-performance.log | head -10# Average execution time by eventawk '{sum[$2]+=$4; count[$2]++} END {for (event in sum) print event, sum[event]/count[event] "s"}' \ ~/.factory/hook-performance.log
Monitor token usage and API costs:Create .factory/hooks/track-costs.sh:
#!/bin/bashinput=$(cat)hook_event=$(echo "$input" | jq -r '.hook_event_name')# Only track on session endif [ "$hook_event" != "SessionEnd" ]; then exit 0fisession_id=$(echo "$input" | jq -r '.session_id')transcript_path=$(echo "$input" | jq -r '.transcript_path')# Parse transcript for token usageif [ ! -f "$transcript_path" ]; then exit 0fi# Extract token counts from transcript (simplified)# In reality, you'd parse the actual transcript formatinput_tokens=$(grep -o '"input_tokens":[0-9]*' "$transcript_path" | \ cut -d':' -f2 | paste -sd+ - | bc)output_tokens=$(grep -o '"output_tokens":[0-9]*' "$transcript_path" | \ cut -d':' -f2 | paste -sd+ - | bc)# Calculate approximate cost (rates vary by model)# Claude Sonnet 4.5: $3 per 1M input, $15 per 1M outputinput_cost=$(echo "scale=4; $input_tokens * 3 / 1000000" | bc)output_cost=$(echo "scale=4; $output_tokens * 15 / 1000000" | bc)total_cost=$(echo "scale=4; $input_cost + $output_cost" | bc)# Log costscost_db="$HOME/.factory/costs.db"sqlite3 "$cost_db" "CREATE TABLE IF NOT EXISTS costs ( session_id TEXT PRIMARY KEY, timestamp TEXT, input_tokens INTEGER, output_tokens INTEGER, total_cost REAL);" 2>/dev/nulltimestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")sqlite3 "$cost_db" "INSERT OR REPLACE INTO costs VALUES ( '$session_id', '$timestamp', $input_tokens, $output_tokens, $total_cost);" 2>/dev/null# Print summaryecho "💰 Session cost: \$${total_cost} (${input_tokens} input + ${output_tokens} output tokens)"exit 0
chmod +x .factory/hooks/track-costs.sh
Query costs:
# Total costssqlite3 ~/.factory/costs.db \ "SELECT SUM(total_cost) as total FROM costs;"# Cost by datesqlite3 ~/.factory/costs.db \ "SELECT DATE(timestamp) as date, SUM(total_cost) as cost FROM costs GROUP BY DATE(timestamp) ORDER BY date DESC;"# Most expensive sessionssqlite3 ~/.factory/costs.db \ "SELECT session_id, total_cost FROM costs ORDER BY total_cost DESC LIMIT 10;"