Skip to main content
hooksSource-backedReview first Safety · Privacy ·

Session Metrics Collector - Hooks

Collects and reports detailed metrics about the coding session when Claude stops.

by JSONbored·added 2025-09-19·
Claude Code
HarnessClaude Code
Trigger:Stop
Review first review before installing

Open the source and read safety notes before installing.

Schema details

Install type
cli
Reading time
4 min
Difficulty score
0
Troubleshooting
Yes
Breaking changes
No
Runtime and command metadata
Trigger
Stop
Script language
bash
Script body
#!/bin/bash

echo "📊 Session Metrics Collector - Gathering session analytics..."
echo "⏱️ Session ended: $(date)"

# Create metrics directory
mkdir -p .metrics

# Session metadata
SESSION_ID="$(date +%Y%m%d_%H%M%S)"
METRICS_FILE=".metrics/session-${SESSION_ID}.json"
END_TIME=$(date)
END_TIMESTAMP=$(date +%s)

echo "💾 Collecting session metrics..."

# Get session start time (approximate from oldest .claude file or fallback)
if [ -d ".claude" ] && [ "$(find .claude -type f 2>/dev/null | wc -l)" -gt 0 ]; then
    START_TIMESTAMP=$(stat -f %B .claude/*.log 2>/dev/null | head -1 || echo $((END_TIMESTAMP - 3600)))
else
    # Fallback: assume 1 hour session
    START_TIMESTAMP=$((END_TIMESTAMP - 3600))
fi

SESSION_DURATION=$((END_TIMESTAMP - START_TIMESTAMP))
SESSION_HOURS=$((SESSION_DURATION / 3600))
SESSION_MINUTES=$(((SESSION_DURATION % 3600) / 60))

echo "⏱️ Session Duration: ${SESSION_HOURS}h ${SESSION_MINUTES}m"

# File statistics
echo "📁 Analyzing file changes..."

# Git-based analysis (preferred)
if git rev-parse --git-dir >/dev/null 2>&1; then
    FILES_MODIFIED=$(git diff --name-only 2>/dev/null | wc -l | tr -d ' ')
    FILES_ADDED=$(git diff --name-status 2>/dev/null | grep '^A' | wc -l | tr -d ' ')
    FILES_DELETED=$(git diff --name-status 2>/dev/null | grep '^D' | wc -l | tr -d ' ')
    
    # Line statistics
    LINE_STATS=$(git diff --shortstat 2>/dev/null || echo "0 files changed")
    LINES_ADDED=$(echo "$LINE_STATS" | grep -o '[0-9]\+ insertion' | grep -o '[0-9]\+' || echo 0)
    LINES_DELETED=$(echo "$LINE_STATS" | grep -o '[0-9]\+ deletion' | grep -o '[0-9]\+' || echo 0)
    
    # Languages used
    LANGUAGES=$(git diff --name-only 2>/dev/null | sed 's/.*\.//' | sort | uniq -c | sort -nr | head -5)
else
    # Fallback: recent file changes
    FILES_MODIFIED=$(find . -type f -newer .metrics 2>/dev/null | wc -l | tr -d ' ' || echo "0")
    FILES_ADDED="unknown"
    FILES_DELETED="unknown"
    LINES_ADDED="unknown"
    LINES_DELETED="unknown"
    LANGUAGES="unknown"
fi

echo "📊 File Statistics:"
echo "  • Files Modified: $FILES_MODIFIED"
echo "  • Files Added: $FILES_ADDED"
echo "  • Files Deleted: $FILES_DELETED"
echo "  • Lines Added: $LINES_ADDED"
echo "  • Lines Deleted: $LINES_DELETED"

# Repository analysis
if git rev-parse --git-dir >/dev/null 2>&1; then
    REPO_NAME=$(basename "$(git rev-parse --show-toplevel)" 2>/dev/null || echo "unknown")
    CURRENT_BRANCH=$(git branch --show-current 2>/dev/null || echo "unknown")
    COMMIT_COUNT=$(git rev-list --count HEAD 2>/dev/null || echo "unknown")
    
    echo "📂 Repository Info:"
    echo "  • Repository: $REPO_NAME"
    echo "  • Branch: $CURRENT_BRANCH"
    echo "  • Total Commits: $COMMIT_COUNT"
fi

# System information
CWD=$(pwd)
USER=$(whoami 2>/dev/null || echo "unknown")
HOST=$(hostname 2>/dev/null || echo "unknown")

echo "🖥️ Environment:"
echo "  • User: $USER"
echo "  • Host: $HOST"
echo "  • Directory: $(basename "$CWD")"

# Activity analysis from .claude logs
if [ -d ".claude" ]; then
    ACTIVITY_COUNT=$(find .claude -name "*.log" -exec cat {} \; 2>/dev/null | wc -l | tr -d ' ')
    echo "📈 Activity: $ACTIVITY_COUNT logged actions"
fi

# Generate JSON metrics
echo "💾 Saving detailed metrics to: $METRICS_FILE"

cat > "$METRICS_FILE" << EOF
{
  "session": {
    "id": "$SESSION_ID",
    "start_time": "$(date -r $START_TIMESTAMP 2>/dev/null || echo 'unknown')",
    "end_time": "$END_TIME",
    "duration_seconds": $SESSION_DURATION,
    "duration_formatted": "${SESSION_HOURS}h ${SESSION_MINUTES}m"
  },
  "files": {
    "modified": $FILES_MODIFIED,
    "added": $FILES_ADDED,
    "deleted": $FILES_DELETED
  },
  "lines": {
    "added": $LINES_ADDED,
    "deleted": $LINES_DELETED
  },
  "repository": {
    "name": "$REPO_NAME",
    "branch": "$CURRENT_BRANCH",
    "total_commits": $COMMIT_COUNT
  },
  "environment": {
    "user": "$USER",
    "host": "$HOST",
    "working_directory": "$CWD"
  },
  "productivity": {
    "files_per_hour": $(echo "scale=2; $FILES_MODIFIED * 3600 / $SESSION_DURATION" | bc -l 2>/dev/null || echo 0),
    "lines_per_hour": $(echo "scale=2; ($LINES_ADDED + $LINES_DELETED) * 3600 / $SESSION_DURATION" | bc -l 2>/dev/null || echo 0)
  }
}
EOF

# Summary statistics
echo ""
echo "📊 Session Summary:"
echo "  • Duration: ${SESSION_HOURS}h ${SESSION_MINUTES}m"
echo "  • Productivity: $(echo "scale=1; $FILES_MODIFIED * 3600 / $SESSION_DURATION" | bc -l 2>/dev/null || echo '0') files/hour"
echo "  • Total Changes: $((LINES_ADDED + LINES_DELETED)) lines"

# Historical comparison
if [ "$(find .metrics -name 'session-*.json' 2>/dev/null | wc -l)" -gt 1 ]; then
    PREV_SESSION=$(find .metrics -name 'session-*.json' | sort | tail -2 | head -1)
    if [ -f "$PREV_SESSION" ]; then
        echo "📈 Compared to last session:"
        echo "  • Previous session available for comparison"
    fi
fi

# Cleanup old metrics (keep last 30 sessions)
find .metrics -name 'session-*.json' | sort | head -n -30 | xargs rm -f 2>/dev/null

echo ""
echo "💡 Productivity Tips:"
echo "  • Review metrics regularly to identify patterns"
echo "  • Set productivity goals for future sessions"
echo "  • Use metrics to optimize development workflow"
echo "  • Compare sessions to track improvement"

echo ""
echo "🎯 Session metrics collection complete!"
echo "📄 Full report saved to: $METRICS_FILE"

exit 0
Full copyable content
{
  "hooks": {
    "stop": {
      "script": "./.claude/hooks/session-metrics-collector.sh",
      "matchers": [
        "*"
      ]
    }
  }
}

About this resource

Features

  • Comprehensive session analytics including session analytics integration (session metrics collection on session stop, detailed session reporting with comprehensive reports, session data aggregation with data aggregation, session analytics visualization with analytics visualization), analytics optimization (analytics performance with fast collection, analytics accuracy with accurate metrics, analytics efficiency with efficient processing, analytics coverage with comprehensive metrics), analytics validation (session data validation with data verification, analytics accuracy validation with accuracy checking, analytics completeness validation with completeness checking, analytics consistency validation with consistency checking), and analytics reporting (session analytics reporting with analytics results, session metrics reporting with metrics details, session statistics reporting with statistics, session insights reporting with insights)
  • File modification tracking including file tracking (file modification detection with change detection, file change tracking with change tracking, file activity monitoring with activity monitoring, file modification analysis with modification analysis), file statistics (file modification statistics with modification counts, file addition statistics with addition counts, file deletion statistics with deletion counts, file change statistics with change metrics), file analysis (file change analysis with change analysis, file pattern analysis with pattern detection, file type analysis with type detection, file activity analysis with activity analysis), and file reporting (file modification reporting with modification details, file statistics reporting with statistics, file analysis reporting with analysis results, file insights reporting with insights)
  • Language usage statistics including language detection (programming language detection with language identification, language usage tracking with usage tracking, language distribution analysis with distribution analysis, language trend analysis with trend analysis), language statistics (language file statistics with file counts, language line statistics with line counts, language change statistics with change metrics, language activity statistics with activity metrics), language analysis (language usage analysis with usage analysis, language pattern analysis with pattern detection, language preference analysis with preference detection, language productivity analysis with productivity analysis), and language reporting (language usage reporting with usage details, language statistics reporting with statistics, language analysis reporting with analysis results, language insights reporting with insights)
  • Productivity metrics collection including productivity tracking (productivity metric collection with metric collection, productivity measurement with productivity measurement, productivity analysis with productivity analysis, productivity optimization with optimization), productivity metrics (files per hour metrics with file productivity, lines per hour metrics with line productivity, session efficiency metrics with efficiency measurement, productivity trend metrics with trend tracking), productivity analysis (productivity pattern analysis with pattern detection, productivity trend analysis with trend analysis, productivity comparison analysis with comparison analysis, productivity optimization analysis with optimization suggestions), and productivity reporting (productivity metrics reporting with metrics details, productivity analysis reporting with analysis results, productivity insights reporting with insights, productivity recommendations reporting with recommendations)
  • Session duration measurement including duration tracking (session duration measurement with duration tracking, session time tracking with time tracking, session interval analysis with interval analysis, session timing analysis with timing analysis), duration statistics (session duration statistics with duration metrics, session time statistics with time metrics, session interval statistics with interval metrics, session timing statistics with timing metrics), duration analysis (session duration analysis with duration analysis, session time analysis with time analysis, session pattern analysis with pattern detection, session efficiency analysis with efficiency analysis), and duration reporting (session duration reporting with duration details, session time reporting with time details, session analysis reporting with analysis results, session insights reporting with insights)
  • Git integration for change tracking including Git integration (Git repository detection with repository detection, Git change tracking with change tracking, Git commit analysis with commit analysis, Git branch analysis with branch analysis), Git statistics (Git file statistics with file metrics, Git line statistics with line metrics, Git commit statistics with commit metrics, Git branch statistics with branch metrics), Git analysis (Git change analysis with change analysis, Git activity analysis with activity analysis, Git workflow analysis with workflow analysis, Git productivity analysis with productivity analysis), and Git reporting (Git integration reporting with integration status, Git statistics reporting with statistics, Git analysis reporting with analysis results, Git insights reporting with insights)
  • Historical session comparison and trend analysis including historical analysis (session history tracking with history tracking, session comparison analysis with comparison analysis, session trend analysis with trend analysis, session pattern analysis with pattern detection), trend metrics (productivity trend metrics with trend tracking, session duration trend metrics with duration trends, file activity trend metrics with activity trends, language usage trend metrics with language trends), trend reporting (historical comparison reporting with comparison results, trend analysis reporting with trend results, pattern analysis reporting with pattern results, trend insights reporting with insights), and trend optimization (trend-based recommendations with recommendations, trend-based optimization with optimization, trend-based insights with insights, trend-based planning with planning)
  • Development workflow integration including continuous analytics (real-time session metrics collection on session stop, immediate analytics reporting on session end, automatic metrics collection on session completion, seamless analytics integration with development workflow), workflow automation (automated session analytics without manual intervention, analytics automation with automatic collection, reporting automation with automatic reporting), and workflow optimization (session metrics tracking with metrics tracking, analytics optimization with optimization, session consistency maintenance with consistency checks)

Use Cases

  • Track coding session productivity automatically collecting session metrics, calculating productivity rates, and providing productivity insights
  • Analyze development patterns automatically tracking file modifications, language usage, and development activities to identify patterns
  • Measure session effectiveness automatically measuring session duration, productivity metrics, and session efficiency
  • Generate development reports automatically generating detailed JSON reports with session metrics, statistics, and insights
  • Monitor coding habits over time automatically tracking historical sessions, comparing sessions, and analyzing trends
  • Development workflow integration seamlessly integrating session metrics collection into development workflows without manual analytics or reporting

Installation

  1. Create hooks directory: mkdir -p .claude/hooks
  2. Create hook file: touch .claude/hooks/session-metrics-collector.sh
  3. Make executable: chmod +x .claude/hooks/session-metrics-collector.sh
  4. Add configuration from Hook Configuration section above to .claude/settings.json or ~/.claude/settings.json
  5. Alternative: Use the interactive /hooks command in Claude Code

Config paths

  • Local (not committed): .claude/settings.local.json
  • User settings (global): ~/.claude/settings.json
  • Project-wide (committed): .claude/settings.json

Requirements

  • Claude Code CLI installed
  • Project directory initialized
  • Bash shell available
  • Git installed (optional, for Git-based statistics)
  • jq (optional, for JSON generation and parsing)
  • bc or awk (optional, for calculations)
  • stat command (for timestamp extraction)

Hook Configuration

{
  "hooks": {
    "stop": {
      "script": "./.claude/hooks/session-metrics-collector.sh",
      "matchers": ["*"]
    }
  }
}

Hook Script

#!/bin/bash

echo "📊 Session Metrics Collector - Gathering session analytics..."
echo "⏱️ Session ended: $(date)"

# Create metrics directory
mkdir -p .metrics

# Session metadata
SESSION_ID="$(date +%Y%m%d_%H%M%S)"
METRICS_FILE=".metrics/session-${SESSION_ID}.json"
END_TIME=$(date)
END_TIMESTAMP=$(date +%s)

echo "💾 Collecting session metrics..."

# Get session start time (approximate from oldest .claude file or fallback)
if [ -d ".claude" ] && [ "$(find .claude -type f 2>/dev/null | wc -l)" -gt 0 ]; then
    START_TIMESTAMP=$(stat -f %B .claude/*.log 2>/dev/null | head -1 || echo $((END_TIMESTAMP - 3600)))
else
    # Fallback: assume 1 hour session
    START_TIMESTAMP=$((END_TIMESTAMP - 3600))
fi

SESSION_DURATION=$((END_TIMESTAMP - START_TIMESTAMP))
SESSION_HOURS=$((SESSION_DURATION / 3600))
SESSION_MINUTES=$(((SESSION_DURATION % 3600) / 60))

echo "⏱️ Session Duration: ${SESSION_HOURS}h ${SESSION_MINUTES}m"

# File statistics
echo "📁 Analyzing file changes..."

# Git-based analysis (preferred)
if git rev-parse --git-dir >/dev/null 2>&1; then
    FILES_MODIFIED=$(git diff --name-only 2>/dev/null | wc -l | tr -d ' ')
    FILES_ADDED=$(git diff --name-status 2>/dev/null | grep '^A' | wc -l | tr -d ' ')
    FILES_DELETED=$(git diff --name-status 2>/dev/null | grep '^D' | wc -l | tr -d ' ')

    # Line statistics
    LINE_STATS=$(git diff --shortstat 2>/dev/null || echo "0 files changed")
    LINES_ADDED=$(echo "$LINE_STATS" | grep -o '[0-9]\+ insertion' | grep -o '[0-9]\+' || echo 0)
    LINES_DELETED=$(echo "$LINE_STATS" | grep -o '[0-9]\+ deletion' | grep -o '[0-9]\+' || echo 0)

    # Languages used
    LANGUAGES=$(git diff --name-only 2>/dev/null | sed 's/.*\.//' | sort | uniq -c | sort -nr | head -5)
else
    # Fallback: recent file changes
    FILES_MODIFIED=$(find . -type f -newer .metrics 2>/dev/null | wc -l | tr -d ' ' || echo "0")
    FILES_ADDED="unknown"
    FILES_DELETED="unknown"
    LINES_ADDED="unknown"
    LINES_DELETED="unknown"
    LANGUAGES="unknown"
fi

echo "📊 File Statistics:"
echo "  • Files Modified: $FILES_MODIFIED"
echo "  • Files Added: $FILES_ADDED"
echo "  • Files Deleted: $FILES_DELETED"
echo "  • Lines Added: $LINES_ADDED"
echo "  • Lines Deleted: $LINES_DELETED"

# Repository analysis
if git rev-parse --git-dir >/dev/null 2>&1; then
    REPO_NAME=$(basename "$(git rev-parse --show-toplevel)" 2>/dev/null || echo "unknown")
    CURRENT_BRANCH=$(git branch --show-current 2>/dev/null || echo "unknown")
    COMMIT_COUNT=$(git rev-list --count HEAD 2>/dev/null || echo "unknown")

    echo "📂 Repository Info:"
    echo "  • Repository: $REPO_NAME"
    echo "  • Branch: $CURRENT_BRANCH"
    echo "  • Total Commits: $COMMIT_COUNT"
fi

# System information
CWD=$(pwd)
USER=$(whoami 2>/dev/null || echo "unknown")
HOST=$(hostname 2>/dev/null || echo "unknown")

echo "🖥️ Environment:"
echo "  • User: $USER"
echo "  • Host: $HOST"
echo "  • Directory: $(basename "$CWD")"

# Activity analysis from .claude logs
if [ -d ".claude" ]; then
    ACTIVITY_COUNT=$(find .claude -name "*.log" -exec cat {} \; 2>/dev/null | wc -l | tr -d ' ')
    echo "📈 Activity: $ACTIVITY_COUNT logged actions"
fi

# Generate JSON metrics
echo "💾 Saving detailed metrics to: $METRICS_FILE"

cat > "$METRICS_FILE" << EOF
{
  "session": {
    "id": "$SESSION_ID",
    "start_time": "$(date -r $START_TIMESTAMP 2>/dev/null || echo 'unknown')",
    "end_time": "$END_TIME",
    "duration_seconds": $SESSION_DURATION,
    "duration_formatted": "${SESSION_HOURS}h ${SESSION_MINUTES}m"
  },
  "files": {
    "modified": $FILES_MODIFIED,
    "added": $FILES_ADDED,
    "deleted": $FILES_DELETED
  },
  "lines": {
    "added": $LINES_ADDED,
    "deleted": $LINES_DELETED
  },
  "repository": {
    "name": "$REPO_NAME",
    "branch": "$CURRENT_BRANCH",
    "total_commits": $COMMIT_COUNT
  },
  "environment": {
    "user": "$USER",
    "host": "$HOST",
    "working_directory": "$CWD"
  },
  "productivity": {
    "files_per_hour": $(echo "scale=2; $FILES_MODIFIED * 3600 / $SESSION_DURATION" | bc -l 2>/dev/null || echo 0),
    "lines_per_hour": $(echo "scale=2; ($LINES_ADDED + $LINES_DELETED) * 3600 / $SESSION_DURATION" | bc -l 2>/dev/null || echo 0)
  }
}
EOF

# Summary statistics
echo ""
echo "📊 Session Summary:"
echo "  • Duration: ${SESSION_HOURS}h ${SESSION_MINUTES}m"
echo "  • Productivity: $(echo "scale=1; $FILES_MODIFIED * 3600 / $SESSION_DURATION" | bc -l 2>/dev/null || echo '0') files/hour"
echo "  • Total Changes: $((LINES_ADDED + LINES_DELETED)) lines"

# Historical comparison
if [ "$(find .metrics -name 'session-*.json' 2>/dev/null | wc -l)" -gt 1 ]; then
    PREV_SESSION=$(find .metrics -name 'session-*.json' | sort | tail -2 | head -1)
    if [ -f "$PREV_SESSION" ]; then
        echo "📈 Compared to last session:"
        echo "  • Previous session available for comparison"
    fi
fi

# Cleanup old metrics (keep last 30 sessions)
find .metrics -name 'session-*.json' | sort | head -n -30 | xargs rm -f 2>/dev/null

echo ""
echo "💡 Productivity Tips:"
echo "  • Review metrics regularly to identify patterns"
echo "  • Set productivity goals for future sessions"
echo "  • Use metrics to optimize development workflow"
echo "  • Compare sessions to track improvement"

echo ""
echo "🎯 Session metrics collection complete!"
echo "📄 Full report saved to: $METRICS_FILE"

exit 0

Examples

Session Metrics Collector Hook Script

Complete hook script that collects session metrics on session stop

#!/bin/bash
echo "📊 Session Metrics Collector - Gathering session analytics..."
echo "⏱️ Session ended: $(date)"
mkdir -p .metrics
SESSION_ID="$(date +%Y%m%d_%H%M%S)"
METRICS_FILE=".metrics/session-${SESSION_ID}.json"
END_TIMESTAMP=$(date +%s)
START_TIMESTAMP=$((END_TIMESTAMP - 3600))
SESSION_DURATION=$((END_TIMESTAMP - START_TIMESTAMP))
if git rev-parse --git-dir >/dev/null 2>&1; then
  FILES_MODIFIED=$(git diff --name-only 2>/dev/null | wc -l | tr -d ' ')
  LINES_ADDED=$(git diff --shortstat 2>/dev/null | grep -o '[0-9]\+ insertion' | grep -o '[0-9]\+' || echo 0)
else
  FILES_MODIFIED=0
  LINES_ADDED=0
fi
cat > "$METRICS_FILE" << EOF
{
  "session": {
    "id": "$SESSION_ID",
    "duration_seconds": $SESSION_DURATION
  },
  "files": {
    "modified": $FILES_MODIFIED
  },
  "lines": {
    "added": $LINES_ADDED
  }
}
EOF
echo "📄 Metrics saved to: $METRICS_FILE"
exit 0

Hook Configuration

Complete hook configuration for .claude/settings.json to enable session metrics collection

{
  "hooks": {
    "stop": {
      "script": "./.claude/hooks/session-metrics-collector.sh",
      "matchers": ["*"]
    }
  }
}

Enhanced Metrics Collection with jq

Enhanced hook script using jq for safe JSON generation and Git diff HEAD for all uncommitted changes

#!/bin/bash
SESSION_ID="$(date +%Y%m%d_%H%M%S)"
METRICS_FILE=".metrics/session-${SESSION_ID}.json"
END_TIMESTAMP=$(date +%s)
START_TIMESTAMP=$(stat -c %Y .claude 2>/dev/null || echo $((END_TIMESTAMP - 3600)))
SESSION_DURATION=$((END_TIMESTAMP - START_TIMESTAMP))
if [ "$SESSION_DURATION" -lt 60 ]; then
  SESSION_DURATION=60
fi
if git rev-parse --git-dir >/dev/null 2>&1; then
  FILES_MODIFIED=$(git diff HEAD --name-only 2>/dev/null | wc -l | tr -d ' ')
  LINES_ADDED=$(git diff HEAD --shortstat 2>/dev/null | grep -o '[0-9]\+ insertion' | grep -o '[0-9]\+' || echo 0)
  LINES_DELETED=$(git diff HEAD --shortstat 2>/dev/null | grep -o '[0-9]\+ deletion' | grep -o '[0-9]\+' || echo 0)
else
  FILES_MODIFIED=0
  LINES_ADDED=0
  LINES_DELETED=0
fi
PRODUCTIVITY=$(awk "BEGIN {printf \"%.2f\", $FILES_MODIFIED * 3600 / $SESSION_DURATION}")
jq -n --arg id "$SESSION_ID" --argjson duration $SESSION_DURATION --argjson files $FILES_MODIFIED --argjson added $LINES_ADDED --argjson deleted $LINES_DELETED --argjson productivity $PRODUCTIVITY '{session: {id: $id, duration_seconds: $duration}, files: {modified: $files}, lines: {added: $added, deleted: $deleted}, productivity: {files_per_hour: $productivity}}' > "$METRICS_FILE"
exit 0

Session Comparison and Language Analysis

Enhanced hook script with historical session comparison and language usage analysis

#!/bin/bash
SESSION_ID="$(date +%Y%m%d_%H%M%S)"
METRICS_FILE=".metrics/session-${SESSION_ID}.json"
if [ -d ".metrics" ] && [ "$(find .metrics -name 'session-*.json' 2>/dev/null | wc -l)" -gt 0 ]; then
  PREV_SESSION=$(find .metrics -name 'session-*.json' | sort | tail -1)
  if [ -f "$PREV_SESSION" ]; then
    PREV_FILES=$(jq -r '.files.modified // 0' "$PREV_SESSION" 2>/dev/null || echo 0)
    PREV_DURATION=$(jq -r '.session.duration_seconds // 0' "$PREV_SESSION" 2>/dev/null || echo 0)
    echo "📈 Previous session: $PREV_FILES files, ${PREV_DURATION}s"
  fi
fi
if git rev-parse --git-dir >/dev/null 2>&1; then
  FILES_MODIFIED=$(git diff HEAD --name-only 2>/dev/null | wc -l | tr -d ' ')
  LANGUAGES=$(git diff HEAD --name-only 2>/dev/null | sed 's/.*\.//' | sort | uniq -c | sort -nr | head -5 | awk '{print $2":"$1}' | tr '\n' ',' | sed 's/,$//')
else
  FILES_MODIFIED=0
  LANGUAGES=""
fi
jq -n --arg id "$SESSION_ID" --argjson files $FILES_MODIFIED --arg langs "$LANGUAGES" '{session: {id: $id}, files: {modified: $files}, languages: $langs}' > "$METRICS_FILE"
exit 0

Session Metrics Configuration Example

Example session metrics configuration for customizing metrics collection

{
  "session_metrics": {
    "metrics_directory": ".metrics",
    "retention_days": 30,
    "include_git_stats": true,
    "include_language_stats": true,
    "include_productivity_stats": true,
    "compare_with_previous": true
  }
}

Troubleshooting

Session metrics show 'unknown' duration or incorrect timing data

Hook relies on .claude directory timestamps. Ensure .claude exists before sessions. On Linux use 'stat -c %Y' instead of macOS 'stat -f %B' for timestamp extraction compatibility. Verify timestamp extraction. Test with various timestamp formats.

Git-based statistics return zero despite file modifications

Run 'git add .' before stopping to stage changes. Hook uses 'git diff' showing only unstaged. Modify script to use 'git diff HEAD' for all uncommitted changes instead. Verify Git status. Test with various Git states.

bc command errors: 'command not found' during metrics calculation

Install bc: 'brew install bc' (macOS) or 'apt-get install bc' (Linux). Or replace with awk: 'awk "BEGIN {printf "%.2f", $FILES_MODIFIED * 3600 / $SESSION_DURATION}"'. Verify calculation tools. Test with various calculation methods.

JSON metrics file has invalid format breaking parsers

Script appends without validation. Variables with special chars break JSON. Escape values: use jq for generation: 'jq -n --arg id "$SESSION_ID" '{session: {id: $id}}' > "$METRICS_FILE"'. Verify JSON format. Test with various data values.

Productivity calculations show zero or negative values

Division by zero when SESSION_DURATION=0. Add check: 'if [ "$SESSION_DURATION" -lt 60 ]; then SESSION_DURATION=60; fi' setting minimum 1-minute before calculations. Verify duration calculation. Test with various session durations.

Language statistics are incomplete or missing

Language detection relies on file extensions. Files without extensions or with uncommon extensions may not be detected. Use more sophisticated language detection or manual language mapping. Verify language detection. Test with various file types.

Historical session comparison fails or shows incorrect data

Previous session file may be missing or corrupted. Add file existence check: 'if [ -f "$PREV_SESSION" ]; then ...'. Verify file paths. Test with various session history scenarios.

Metrics directory grows too large with old session files

Add cleanup logic: 'find .metrics -name 'session-.json' -mtime +30 -delete' to remove files older than 30 days. Or limit retention: 'find .metrics -name 'session-.json' | sort | head -n -30 | xargs rm -f'. Verify cleanup logic. Test with various retention policies.

#metrics#analytics#stop-hook#performance#statistics

Source citations

Signals

Loading live community signals…

More like this, weekly

A short, calm digest of reviewed Claude resources. Unsubscribe any time.