Loading...
Tracks all Claude Code activities in real-time and logs them for monitoring and debugging
{
"hookConfig": {
"hooks": {
"notification": {
"script": "./.claude/hooks/real-time-activity-tracker.sh",
"matchers": [
"*"
]
}
}
},
"scriptContent": "#!/bin/bash\n\n# Read the tool input from stdin\nINPUT=$(cat)\nTOOL_NAME=$(echo \"$INPUT\" | jq -r '.tool_name')\nFILE_PATH=$(echo \"$INPUT\" | jq -r '.tool_input.file_path // .tool_input.path // \"\"')\nTOOL_ACTION=$(echo \"$INPUT\" | jq -r '.tool_action // \"unknown\"')\n\necho \"📊 Real-time Activity Tracker - Logging activity...\"\n\n# Create .claude directory if it doesn't exist\nmkdir -p .claude\n\n# Create daily activity log\nACTIVITY_LOG=\".claude/activity-$(date +%Y%m%d).log\"\nACTIVITY_JSON=\".claude/activity-$(date +%Y%m%d).json\"\n\n# Current timestamp\nTIMESTAMP=$(date --iso-8601=seconds 2>/dev/null || date -Iseconds 2>/dev/null || date)\n\n# Log in human-readable format\necho \"[$TIMESTAMP] Tool: $TOOL_NAME | File: $FILE_PATH | Action: $TOOL_ACTION\" >> \"$ACTIVITY_LOG\"\n\n# Log in JSON format for programmatic analysis\ncat >> \"$ACTIVITY_JSON\" << EOF\n{\n \"timestamp\": \"$TIMESTAMP\",\n \"tool_name\": \"$TOOL_NAME\",\n \"file_path\": \"$FILE_PATH\",\n \"action\": \"$TOOL_ACTION\",\n \"session_id\": \"$(date +%Y%m%d_%H%M%S)_$$\"\n},\nEOF\n\n# Keep only last 100 entries in activity log to prevent it from growing too large\nif [ -f \"$ACTIVITY_LOG\" ]; then\n tail -n 100 \"$ACTIVITY_LOG\" > \"$ACTIVITY_LOG.tmp\" && mv \"$ACTIVITY_LOG.tmp\" \"$ACTIVITY_LOG\"\nfi\n\n# Keep only last 100 entries in JSON log\nif [ -f \"$ACTIVITY_JSON\" ]; then\n tail -n 100 \"$ACTIVITY_JSON\" > \"$ACTIVITY_JSON.tmp\" && mv \"$ACTIVITY_JSON.tmp\" \"$ACTIVITY_JSON\"\nfi\n\n# Activity statistics\nif [ -f \"$ACTIVITY_LOG\" ]; then\n TOTAL_ACTIVITIES=$(wc -l < \"$ACTIVITY_LOG\")\n echo \"📈 Session Activity Count: $TOTAL_ACTIVITIES\"\n \n # Show recent activity summary\n echo \"🕒 Recent Activities:\"\n tail -n 3 \"$ACTIVITY_LOG\" | while read -r line; do\n echo \" • $line\"\n done\n \n # File operation summary\n WRITE_COUNT=$(grep -c \"Write\\|Edit\" \"$ACTIVITY_LOG\" 2>/dev/null || echo 0)\n read_COUNT=$(grep -c \"Read\" \"$ACTIVITY_LOG\" 2>/dev/null || echo 0)\n \n echo \"📊 Today's Summary:\"\n echo \" • Write/Edit operations: $WRITE_COUNT\"\n echo \" • Read operations: $READ_COUNT\"\nfi\n\n# Weekly activity archive (every Sunday)\nif [ \"$(date +%u)\" = \"7\" ]; then\n ARCHIVE_DIR=\".claude/archive/$(date +%Y-%m)\"\n mkdir -p \"$ARCHIVE_DIR\"\n \n # Move old logs to archive\n find .claude -name \"activity-*.log\" -mtime +7 -exec mv {} \"$ARCHIVE_DIR/\" \\;\n find .claude -name \"activity-*.json\" -mtime +7 -exec mv {} \"$ARCHIVE_DIR/\" \\;\n \n echo \"📦 Weekly archive created in $ARCHIVE_DIR\"\nfi\n\necho \"✅ Activity logged to $ACTIVITY_LOG\"\n\nexit 0"
}.claude/hooks/~/.claude/hooks/{
"hooks": {
"notification": {
"script": "./.claude/hooks/real-time-activity-tracker.sh",
"matchers": [
"*"
]
}
}
}#!/bin/bash
# Read the tool input from stdin
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name')
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.path // ""')
TOOL_ACTION=$(echo "$INPUT" | jq -r '.tool_action // "unknown"')
echo "📊 Real-time Activity Tracker - Logging activity..."
# Create .claude directory if it doesn't exist
mkdir -p .claude
# Create daily activity log
ACTIVITY_LOG=".claude/activity-$(date +%Y%m%d).log"
ACTIVITY_JSON=".claude/activity-$(date +%Y%m%d).json"
# Current timestamp
TIMESTAMP=$(date --iso-8601=seconds 2>/dev/null || date -Iseconds 2>/dev/null || date)
# Log in human-readable format
echo "[$TIMESTAMP] Tool: $TOOL_NAME | File: $FILE_PATH | Action: $TOOL_ACTION" >> "$ACTIVITY_LOG"
# Log in JSON format for programmatic analysis
cat >> "$ACTIVITY_JSON" << EOF
{
"timestamp": "$TIMESTAMP",
"tool_name": "$TOOL_NAME",
"file_path": "$FILE_PATH",
"action": "$TOOL_ACTION",
"session_id": "$(date +%Y%m%d_%H%M%S)_$$"
},
EOF
# Keep only last 100 entries in activity log to prevent it from growing too large
if [ -f "$ACTIVITY_LOG" ]; then
tail -n 100 "$ACTIVITY_LOG" > "$ACTIVITY_LOG.tmp" && mv "$ACTIVITY_LOG.tmp" "$ACTIVITY_LOG"
fi
# Keep only last 100 entries in JSON log
if [ -f "$ACTIVITY_JSON" ]; then
tail -n 100 "$ACTIVITY_JSON" > "$ACTIVITY_JSON.tmp" && mv "$ACTIVITY_JSON.tmp" "$ACTIVITY_JSON"
fi
# Activity statistics
if [ -f "$ACTIVITY_LOG" ]; then
TOTAL_ACTIVITIES=$(wc -l < "$ACTIVITY_LOG")
echo "📈 Session Activity Count: $TOTAL_ACTIVITIES"
# Show recent activity summary
echo "🕒 Recent Activities:"
tail -n 3 "$ACTIVITY_LOG" | while read -r line; do
echo " • $line"
done
# File operation summary
WRITE_COUNT=$(grep -c "Write\|Edit" "$ACTIVITY_LOG" 2>/dev/null || echo 0)
read_COUNT=$(grep -c "Read" "$ACTIVITY_LOG" 2>/dev/null || echo 0)
echo "📊 Today's Summary:"
echo " • Write/Edit operations: $WRITE_COUNT"
echo " • Read operations: $READ_COUNT"
fi
# Weekly activity archive (every Sunday)
if [ "$(date +%u)" = "7" ]; then
ARCHIVE_DIR=".claude/archive/$(date +%Y-%m)"
mkdir -p "$ARCHIVE_DIR"
# Move old logs to archive
find .claude -name "activity-*.log" -mtime +7 -exec mv {} "$ARCHIVE_DIR/" \;
find .claude -name "activity-*.json" -mtime +7 -exec mv {} "$ARCHIVE_DIR/" \;
echo "📦 Weekly archive created in $ARCHIVE_DIR"
fi
echo "✅ Activity logged to $ACTIVITY_LOG"
exit 0Activity logs show incorrect timestamps or 'unknown' dates
ISO-8601 date varies by platform. Replace 'date --iso-8601=seconds' with portable: 'date -u +"%Y-%m-%dT%H:%M:%SZ"'. Works on both Linux and macOS without fallback.
JSON activity log is malformed with trailing commas
Each append adds trailing comma creating invalid JSON. Wrap in array: initialize with '[', append without trailing comma, close ']' on end. Or rebuild: 'jq -s . file.json'.
Weekly archive triggers fail on macOS (date +%u returns wrong day)
macOS date lacks %u for weekday. Replace with: 'if [ "$(date +%w)" = "0" ]; then' (Sunday=0). Or use portable: '[ $(date +%A) = "Sunday" ]' for name-based check.
Session IDs duplicate when multiple Claude instances run simultaneously
Current session_id uses timestamp+PID but PID can conflict. Add random suffix: "$(date +%Y%m%d_%H%M%S)_$$_$RANDOM" or use UUID: "$(uuidgen 2>/dev/null || echo $RANDOM$RANDOM)".
Log files locked causing permission denied errors on write
Concurrent writes from parallel Claude sessions. Use flock: '(flock -x 200; echo ".." >> log; ) 200>/var/lock/activity.lock' for atomic append operations.
Loading reviews...
Join our community of Claude power users. No spam, unsubscribe anytime.
Automated accessibility testing and compliance checking for web applications following WCAG guidelines
Automatically generates or updates API documentation when endpoint files are modified
Automatically formats code files after Claude writes or edits them using Prettier, Black, or other formatters