Loading...
Generates a comprehensive report when Claude Code workflow stops, including files modified, tests run, and git status
{
"hookConfig": {
"hooks": {
"stop": {
"script": "./.claude/hooks/workflow-completion-report.sh",
"matchers": [
"*"
]
}
}
},
"scriptContent": "#!/bin/bash\n\necho \"๐ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\"\necho \"๐ฏ WORKFLOW COMPLETION REPORT\"\necho \"๐
Session Completed: $(date)\"\necho \"โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\"\n\n# Session metadata\nSESSION_ID=\"session-$(date +%Y%m%d_%H%M%S)\"\nCOMPLETION_TIME=$(date)\nSTART_TIME=\"unknown\"\nUSER=$(whoami 2>/dev/null || echo \"developer\")\nHOST=$(hostname 2>/dev/null || echo \"unknown\")\nWORKDIR=$(pwd)\nPROJECT_NAME=$(basename \"$WORKDIR\" 2>/dev/null || echo \"project\")\n\necho \"๐ท๏ธ Session Info:\"\necho \" โข Session ID: $SESSION_ID\"\necho \" โข Project: $PROJECT_NAME\"\necho \" โข User: $USER@$HOST\"\necho \" โข Directory: $WORKDIR\"\n\n# Attempt to determine session duration\nif [ -d \".claude\" ] && [ \"$(find .claude -type f 2>/dev/null | wc -l)\" -gt 0 ]; then\n START_TIMESTAMP=$(stat -f %B .claude/*.log 2>/dev/null | sort | head -1 || date +%s)\n END_TIMESTAMP=$(date +%s)\n DURATION=$((END_TIMESTAMP - START_TIMESTAMP))\n HOURS=$((DURATION / 3600))\n MINUTES=$(((DURATION % 3600) / 60))\n echo \" โข Duration: ${HOURS}h ${MINUTES}m\"\nelse\n echo \" โข Duration: Unknown (no .claude directory)\"\nfi\n\necho \"\"\necho \"๐ File System Analysis:\"\necho \"โโโโโโโโโโโโโโโโโโโโโโโโโโโ\"\n\n# Git analysis\nif git rev-parse --git-dir >/dev/null 2>&1; then\n echo \"๐ Git Repository Status:\"\n \n BRANCH=$(git branch --show-current 2>/dev/null || echo \"unknown\")\n echo \" โข Current branch: $BRANCH\"\n \n # Count modified files\n MODIFIED_FILES=$(git status --porcelain 2>/dev/null | wc -l | tr -d ' ')\n echo \" โข Modified files: $MODIFIED_FILES\"\n \n # Show file status breakdown\n if [ \"$MODIFIED_FILES\" -gt 0 ]; then\n echo \" โข File status breakdown:\"\n git status --porcelain 2>/dev/null | cut -c1-2 | sort | uniq -c | while read -r count status; do\n case \"$status\" in\n \"M \"*) echo \" - Modified: $count files\" ;;\n \"A \"*) echo \" - Added: $count files\" ;;\n \"D \"*) echo \" - Deleted: $count files\" ;;\n \"??\"*) echo \" - Untracked: $count files\" ;;\n *) echo \" - Other ($status): $count files\" ;;\n esac\n done\n fi\n \n # Diff statistics\n DIFF_STATS=$(git diff --stat 2>/dev/null)\n if [ -n \"$DIFF_STATS\" ]; then\n echo \" โข Changes summary:\"\n echo \"$DIFF_STATS\" | tail -1 | sed 's/^/ /' 2>/dev/null || echo \" No statistics available\"\n fi\n \n # List modified files (top 10)\n if [ \"$MODIFIED_FILES\" -gt 0 ]; then\n echo \" โข Modified files (top 10):\"\n git status --porcelain 2>/dev/null | head -10 | while read -r status file; do\n echo \" - $file ($status)\"\n done\n fi\n \n # Recent commits\n echo \" โข Recent commits:\"\n git log --oneline -3 2>/dev/null | sed 's/^/ /' || echo \" No recent commits\"\n \nelse\n echo \"โ Not a git repository\"\n echo \" โข Analyzing file system changes...\"\n \n # Alternative: look for recently modified files\n echo \" โข Recently modified files (last 2 hours):\"\n find . -type f -newermt '2 hours ago' 2>/dev/null | head -10 | while read -r file; do\n echo \" - $file\"\n done\nfi\n\necho \"\"\necho \"๐งช Testing & Quality Analysis:\"\necho \"โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\"\n\n# Test framework detection and analysis\nTEST_FRAMEWORK=\"none\"\nTEST_COUNT=0\n\nif [ -f \"package.json\" ]; then\n echo \"๐ฆ Node.js Project Analysis:\"\n \n # Detect test framework\n if grep -q '\"jest\"' package.json 2>/dev/null; then\n TEST_FRAMEWORK=\"jest\"\n echo \" โข Testing framework: Jest\"\n elif grep -q '\"vitest\"' package.json 2>/dev/null; then\n TEST_FRAMEWORK=\"vitest\"\n echo \" โข Testing framework: Vitest\"\n elif grep -q '\"mocha\"' package.json 2>/dev/null; then\n TEST_FRAMEWORK=\"mocha\"\n echo \" โข Testing framework: Mocha\"\n else\n echo \" โข Testing framework: Not detected\"\n fi\n \n # Count test files\n TEST_COUNT=$(find . -name \"*.test.*\" -o -name \"*.spec.*\" | grep -v node_modules | wc -l | tr -d ' ')\n echo \" โข Test files found: $TEST_COUNT\"\n \n # Dependencies analysis\n DEPS_COUNT=$(jq -r '.dependencies // {} | keys | length' package.json 2>/dev/null || echo \"unknown\")\n DEV_DEPS_COUNT=$(jq -r '.devDependencies // {} | keys | length' package.json 2>/dev/null || echo \"unknown\")\n echo \" โข Dependencies: $DEPS_COUNT production, $DEV_DEPS_COUNT development\"\n \n # Check for outdated packages\n echo \" โข Checking for outdated packages...\"\n OUTDATED_COUNT=$(npm outdated 2>/dev/null | tail -n +2 | wc -l | tr -d ' ')\n if [ \"$OUTDATED_COUNT\" -gt 0 ]; then\n echo \" - $OUTDATED_COUNT packages have updates available\"\n else\n echo \" - All packages are up to date\"\n fi\n \nelif [ -f \"requirements.txt\" ] || [ -f \"setup.py\" ] || [ -f \"pyproject.toml\" ]; then\n echo \"๐ Python Project Analysis:\"\n \n if command -v pytest >/dev/null 2>&1; then\n TEST_FRAMEWORK=\"pytest\"\n echo \" โข Testing framework: pytest\"\n TEST_COUNT=$(find . -name \"test_*.py\" -o -name \"*_test.py\" | wc -l | tr -d ' ')\n else\n echo \" โข Testing framework: unittest (built-in)\"\n TEST_COUNT=$(find . -name \"test*.py\" | wc -l | tr -d ' ')\n fi\n echo \" โข Test files found: $TEST_COUNT\"\n \nelif [ -f \"Cargo.toml\" ]; then\n echo \"๐ฆ Rust Project Analysis:\"\n echo \" โข Testing framework: Built-in (cargo test)\"\n TEST_COUNT=$(find . -name \"*.rs\" -exec grep -l \"#\\[test\\]\" {} \\; | wc -l | tr -d ' ')\n echo \" โข Files with tests: $TEST_COUNT\"\n \nelse\n echo \"โ Project type not recognized\"\nfi\n\n# Performance and metrics\necho \"\"\necho \"๐ Performance & Metrics:\"\necho \"โโโโโโโโโโโโโโโโโโโโโโโโโโโ\"\n\n# Code complexity analysis (basic)\nif [ \"$TEST_COUNT\" -gt 0 ]; then\n echo \"โ
Test Coverage Status:\"\n echo \" โข Test files available: $TEST_COUNT\"\n echo \" โข Testing framework: $TEST_FRAMEWORK\"\nelse\n echo \"โ ๏ธ No test files detected\"\nfi\n\n# File type analysis\necho \"๐ Codebase Composition:\"\nfor ext in js ts jsx tsx py rs go java c cpp; do\n count=$(find . -name \"*.$ext\" | grep -v node_modules | wc -l | tr -d ' ')\n if [ \"$count\" -gt 0 ]; then\n echo \" โข .$ext files: $count\"\n fi\ndone\n\n# Lines of code estimation\nTOTAL_LOC=$(find . -type f \\( -name \"*.js\" -o -name \"*.ts\" -o -name \"*.jsx\" -o -name \"*.tsx\" -o -name \"*.py\" -o -name \"*.rs\" -o -name \"*.go\" \\) | grep -v node_modules | xargs wc -l 2>/dev/null | tail -1 | awk '{print $1}' || echo \"unknown\")\necho \" โข Estimated lines of code: $TOTAL_LOC\"\n\n# Session archival\necho \"\"\necho \"๐พ Session Archival:\"\necho \"โโโโโโโโโโโโโโโโโโโ\"\n\n# Create session report file\nREPORT_FILE=\".claude-reports/$SESSION_ID.log\"\nmkdir -p .claude-reports\n\ncat > \"$REPORT_FILE\" << EOF\nCLAUDE CODE WORKFLOW COMPLETION REPORT\n======================================\n\nSession ID: $SESSION_ID\nCompleted: $COMPLETION_TIME\nProject: $PROJECT_NAME\nUser: $USER@$HOST\nDirectory: $WORKDIR\n\nFILE CHANGES:\n$(git status --porcelain 2>/dev/null || echo \"Not a git repository\")\n\nDIFF STATISTICS:\n$(git diff --stat 2>/dev/null || echo \"No git changes\")\n\nTEST STATUS:\n- Framework: $TEST_FRAMEWORK\n- Test files: $TEST_COUNT\n\nPROJECT METRICS:\n- Total LOC (estimated): $TOTAL_LOC\n- Modified files: $MODIFIED_FILES\n\nEOF\n\necho \"๐ Session report saved: $REPORT_FILE\"\necho \"๐ Report directory: .claude-reports/\"\n\n# Cleanup old reports (keep last 30)\nfind .claude-reports -name \"session-*.log\" | sort | head -n -30 | xargs rm -f 2>/dev/null\n\necho \"\"\necho \"๐ก Workflow Summary:\"\necho \"โโโโโโโโโโโโโโโโโโโ\"\necho \" โข Session completed successfully\"\necho \" โข Files modified: $MODIFIED_FILES\"\necho \" โข Test files available: $TEST_COUNT\"\necho \" โข Project type: $([ -f package.json ] && echo 'Node.js' || [ -f requirements.txt ] && echo 'Python' || [ -f Cargo.toml ] && echo 'Rust' || echo 'Unknown')\"\necho \" โข Git repository: $([ -d .git ] && echo 'Yes' || echo 'No')\"\n\necho \"\"\necho \"๐ฏ Next Steps:\"\necho \" โข Review all changes before committing\"\necho \" โข Run tests to ensure code quality\"\necho \" โข Update documentation if needed\"\necho \" โข Consider code review for significant changes\"\n\necho \"\"\necho \"๐ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\"\necho \"๐ Workflow completion report generated successfully!\"\necho \"๐ Full report available at: $REPORT_FILE\"\necho \"โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\"\n\nexit 0"
}.claude/hooks/~/.claude/hooks/{
"hooks": {
"stop": {
"script": "./.claude/hooks/workflow-completion-report.sh",
"matchers": [
"*"
]
}
}
}#!/bin/bash
echo "๐ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ"
echo "๐ฏ WORKFLOW COMPLETION REPORT"
echo "๐
Session Completed: $(date)"
echo "โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ"
# Session metadata
SESSION_ID="session-$(date +%Y%m%d_%H%M%S)"
COMPLETION_TIME=$(date)
START_TIME="unknown"
USER=$(whoami 2>/dev/null || echo "developer")
HOST=$(hostname 2>/dev/null || echo "unknown")
WORKDIR=$(pwd)
PROJECT_NAME=$(basename "$WORKDIR" 2>/dev/null || echo "project")
echo "๐ท๏ธ Session Info:"
echo " โข Session ID: $SESSION_ID"
echo " โข Project: $PROJECT_NAME"
echo " โข User: $USER@$HOST"
echo " โข Directory: $WORKDIR"
# Attempt to determine session duration
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 | sort | head -1 || date +%s)
END_TIMESTAMP=$(date +%s)
DURATION=$((END_TIMESTAMP - START_TIMESTAMP))
HOURS=$((DURATION / 3600))
MINUTES=$(((DURATION % 3600) / 60))
echo " โข Duration: ${HOURS}h ${MINUTES}m"
else
echo " โข Duration: Unknown (no .claude directory)"
fi
echo ""
echo "๐ File System Analysis:"
echo "โโโโโโโโโโโโโโโโโโโโโโโโโโโ"
# Git analysis
if git rev-parse --git-dir >/dev/null 2>&1; then
echo "๐ Git Repository Status:"
BRANCH=$(git branch --show-current 2>/dev/null || echo "unknown")
echo " โข Current branch: $BRANCH"
# Count modified files
MODIFIED_FILES=$(git status --porcelain 2>/dev/null | wc -l | tr -d ' ')
echo " โข Modified files: $MODIFIED_FILES"
# Show file status breakdown
if [ "$MODIFIED_FILES" -gt 0 ]; then
echo " โข File status breakdown:"
git status --porcelain 2>/dev/null | cut -c1-2 | sort | uniq -c | while read -r count status; do
case "$status" in
"M "*) echo " - Modified: $count files" ;;
"A "*) echo " - Added: $count files" ;;
"D "*) echo " - Deleted: $count files" ;;
"??"*) echo " - Untracked: $count files" ;;
*) echo " - Other ($status): $count files" ;;
esac
done
fi
# Diff statistics
DIFF_STATS=$(git diff --stat 2>/dev/null)
if [ -n "$DIFF_STATS" ]; then
echo " โข Changes summary:"
echo "$DIFF_STATS" | tail -1 | sed 's/^/ /' 2>/dev/null || echo " No statistics available"
fi
# List modified files (top 10)
if [ "$MODIFIED_FILES" -gt 0 ]; then
echo " โข Modified files (top 10):"
git status --porcelain 2>/dev/null | head -10 | while read -r status file; do
echo " - $file ($status)"
done
fi
# Recent commits
echo " โข Recent commits:"
git log --oneline -3 2>/dev/null | sed 's/^/ /' || echo " No recent commits"
else
echo "โ Not a git repository"
echo " โข Analyzing file system changes..."
# Alternative: look for recently modified files
echo " โข Recently modified files (last 2 hours):"
find . -type f -newermt '2 hours ago' 2>/dev/null | head -10 | while read -r file; do
echo " - $file"
done
fi
echo ""
echo "๐งช Testing & Quality Analysis:"
echo "โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ"
# Test framework detection and analysis
TEST_FRAMEWORK="none"
TEST_COUNT=0
if [ -f "package.json" ]; then
echo "๐ฆ Node.js Project Analysis:"
# Detect test framework
if grep -q '"jest"' package.json 2>/dev/null; then
TEST_FRAMEWORK="jest"
echo " โข Testing framework: Jest"
elif grep -q '"vitest"' package.json 2>/dev/null; then
TEST_FRAMEWORK="vitest"
echo " โข Testing framework: Vitest"
elif grep -q '"mocha"' package.json 2>/dev/null; then
TEST_FRAMEWORK="mocha"
echo " โข Testing framework: Mocha"
else
echo " โข Testing framework: Not detected"
fi
# Count test files
TEST_COUNT=$(find . -name "*.test.*" -o -name "*.spec.*" | grep -v node_modules | wc -l | tr -d ' ')
echo " โข Test files found: $TEST_COUNT"
# Dependencies analysis
DEPS_COUNT=$(jq -r '.dependencies // {} | keys | length' package.json 2>/dev/null || echo "unknown")
DEV_DEPS_COUNT=$(jq -r '.devDependencies // {} | keys | length' package.json 2>/dev/null || echo "unknown")
echo " โข Dependencies: $DEPS_COUNT production, $DEV_DEPS_COUNT development"
# Check for outdated packages
echo " โข Checking for outdated packages..."
OUTDATED_COUNT=$(npm outdated 2>/dev/null | tail -n +2 | wc -l | tr -d ' ')
if [ "$OUTDATED_COUNT" -gt 0 ]; then
echo " - $OUTDATED_COUNT packages have updates available"
else
echo " - All packages are up to date"
fi
elif [ -f "requirements.txt" ] || [ -f "setup.py" ] || [ -f "pyproject.toml" ]; then
echo "๐ Python Project Analysis:"
if command -v pytest >/dev/null 2>&1; then
TEST_FRAMEWORK="pytest"
echo " โข Testing framework: pytest"
TEST_COUNT=$(find . -name "test_*.py" -o -name "*_test.py" | wc -l | tr -d ' ')
else
echo " โข Testing framework: unittest (built-in)"
TEST_COUNT=$(find . -name "test*.py" | wc -l | tr -d ' ')
fi
echo " โข Test files found: $TEST_COUNT"
elif [ -f "Cargo.toml" ]; then
echo "๐ฆ Rust Project Analysis:"
echo " โข Testing framework: Built-in (cargo test)"
TEST_COUNT=$(find . -name "*.rs" -exec grep -l "#\[test\]" {} \; | wc -l | tr -d ' ')
echo " โข Files with tests: $TEST_COUNT"
else
echo "โ Project type not recognized"
fi
# Performance and metrics
echo ""
echo "๐ Performance & Metrics:"
echo "โโโโโโโโโโโโโโโโโโโโโโโโโโโ"
# Code complexity analysis (basic)
if [ "$TEST_COUNT" -gt 0 ]; then
echo "โ
Test Coverage Status:"
echo " โข Test files available: $TEST_COUNT"
echo " โข Testing framework: $TEST_FRAMEWORK"
else
echo "โ ๏ธ No test files detected"
fi
# File type analysis
echo "๐ Codebase Composition:"
for ext in js ts jsx tsx py rs go java c cpp; do
count=$(find . -name "*.$ext" | grep -v node_modules | wc -l | tr -d ' ')
if [ "$count" -gt 0 ]; then
echo " โข .$ext files: $count"
fi
done
# Lines of code estimation
TOTAL_LOC=$(find . -type f \( -name "*.js" -o -name "*.ts" -o -name "*.jsx" -o -name "*.tsx" -o -name "*.py" -o -name "*.rs" -o -name "*.go" \) | grep -v node_modules | xargs wc -l 2>/dev/null | tail -1 | awk '{print $1}' || echo "unknown")
echo " โข Estimated lines of code: $TOTAL_LOC"
# Session archival
echo ""
echo "๐พ Session Archival:"
echo "โโโโโโโโโโโโโโโโโโโ"
# Create session report file
REPORT_FILE=".claude-reports/$SESSION_ID.log"
mkdir -p .claude-reports
cat > "$REPORT_FILE" << EOF
CLAUDE CODE WORKFLOW COMPLETION REPORT
======================================
Session ID: $SESSION_ID
Completed: $COMPLETION_TIME
Project: $PROJECT_NAME
User: $USER@$HOST
Directory: $WORKDIR
FILE CHANGES:
$(git status --porcelain 2>/dev/null || echo "Not a git repository")
DIFF STATISTICS:
$(git diff --stat 2>/dev/null || echo "No git changes")
TEST STATUS:
- Framework: $TEST_FRAMEWORK
- Test files: $TEST_COUNT
PROJECT METRICS:
- Total LOC (estimated): $TOTAL_LOC
- Modified files: $MODIFIED_FILES
EOF
echo "๐ Session report saved: $REPORT_FILE"
echo "๐ Report directory: .claude-reports/"
# Cleanup old reports (keep last 30)
find .claude-reports -name "session-*.log" | sort | head -n -30 | xargs rm -f 2>/dev/null
echo ""
echo "๐ก Workflow Summary:"
echo "โโโโโโโโโโโโโโโโโโโ"
echo " โข Session completed successfully"
echo " โข Files modified: $MODIFIED_FILES"
echo " โข Test files available: $TEST_COUNT"
echo " โข Project type: $([ -f package.json ] && echo 'Node.js' || [ -f requirements.txt ] && echo 'Python' || [ -f Cargo.toml ] && echo 'Rust' || echo 'Unknown')"
echo " โข Git repository: $([ -d .git ] && echo 'Yes' || echo 'No')"
echo ""
echo "๐ฏ Next Steps:"
echo " โข Review all changes before committing"
echo " โข Run tests to ensure code quality"
echo " โข Update documentation if needed"
echo " โข Consider code review for significant changes"
echo ""
echo "๐ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ"
echo "๐ Workflow completion report generated successfully!"
echo "๐ Full report available at: $REPORT_FILE"
echo "โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ"
exit 0Report shows 'unknown' for session duration and start time
Hook reads .claude/*.log times but files may not exist. Create marker: 'echo "$(date +%s)" > .claude/session-start' at init, then read: 'START_TIMESTAMP=$(cat .claude/session-start)'.
Outdated package check causes long delays (npm outdated hangs)
npm outdated performs network checks timing out on slow connections. Add wrapper: 'timeout 10 npm outdated 2>/dev/null || echo "Check skipped"'. Or comment out for speed.
Report directory cleanup removes current session's report file
Sort bug: 'find | sort | head -n -30' removes newest alphabetically. Fix with time sort: 'find .claude-reports -type f -printf "%T@ %p\\n" | sort -n | head -n -30 | cut -d" " -f2-'.
Diff statistics show empty output despite uncommitted changes
git diff excludes untracked files. Combine: 'git diff --stat; git diff --cached --stat' for staged. Or use: 'git diff HEAD --stat' showing all uncommitted modifications.
Test file count inaccurate with nested test directories
find without depth limit includes node_modules. Add exclusion: 'find . -name "*.test.*" -not -path "*/node_modules/*" -not -path "*/vendor/*"' for accurate counts.
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