feat: add git-based insights dashboard report#299
Conversation
Generates an HTML insights report from actual git history showing commit velocity, type breakdown, hotspot files, day/hour activity, language distribution, and key project insights. https://claude.ai/code/session_01LQtS6mgGPiYt1BTugXsbAH
📝 WalkthroughWalkthroughAdded a new standalone static HTML report ( Changes
Estimated code review effort🎯 1 (Trivial) | ⏱️ ~3 minutes 🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@insights-report.html`:
- Line 2: Add a lang attribute to the root html element (the <html> tag) so
assistive tech and search engines can determine the document language; set it to
the document's primary language (e.g., lang="en" or the correct BCP 47 code) in
the file where the <html> element is defined and ensure any templates or
rendering code that produces <html> also emits this attribute consistently.
- Line 6: Remove the external Google Fonts link tag that loads "Inter" (the
<link href="https://fonts.googleapis.com/...Inter..."> tag) to avoid leaking
user data; update the report's CSS to use system font fallbacks (e.g., Inter →
system UI stack) or, if Inter is required, replace the external link by
self-hosting the Inter font files and referencing them via `@font-face` in your
stylesheet so no external CDN is contacted.
- Around line 3-6: Add a viewport meta element to the head so the responsive CSS
works on mobile: insert a meta with name "viewport" and content set to
width=device-width, initial-scale=1 before the <title> (i.e., within the
existing head block that contains the title and Google Fonts link) so the `@media`
rules at the responsive CSS section take effect on mobile devices.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 2da1e154-9748-40f4-95ee-4cf2c1cd6168
📒 Files selected for processing (1)
insights-report.html
- Add lang="en" to <html> for accessibility - Add viewport meta tag for responsive rendering on mobile - Remove external Google Fonts CDN to avoid leaking user data; use system font stack instead https://claude.ai/code/session_01LQtS6mgGPiYt1BTugXsbAH
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@insights-report.html`:
- Around line 159-176: The commit messages and file paths are embedded raw into
the HTML elements with classes commit-subj and commit-meta (and author name at
lines ~66–67); sanitize all git-derived strings by applying HTML entity encoding
for &, <, >, " and ' before rendering. Add/use a single escape utility (e.g.,
escapeHtml) and call it wherever commit-subj, commit-meta, file path, or author
name values are inserted into the template/DOM so the rendered values are safe
from stored XSS.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 7ff3cd85-77a2-4ef6-9e2a-6bb3028957a8
📒 Files selected for processing (1)
insights-report.html
| <div class="commit-subj">feat: add automated welcome campaign system (#275)</div> | ||
| <div class="commit-meta">2026-03-26 • <span class="lines">+1,422 / -80</span> lines • 8 files</div> | ||
| </div> | ||
| <div class="commit-card"> | ||
| <div class="commit-subj">feat: add campaign data recovery from orphaned recipients (#295)</div> | ||
| <div class="commit-meta">2026-03-27 • <span class="lines">+712 / -0</span> lines • 4 files</div> | ||
| </div> | ||
| <div class="commit-card"> | ||
| <div class="commit-subj">fix: resolve 6 admin bugs with input validation and filter consistency (#297)</div> | ||
| <div class="commit-meta">2026-03-27 • <span class="lines">+525 / -7</span> lines • 3 files</div> | ||
| </div> | ||
| <div class="commit-card"> | ||
| <div class="commit-subj">Fix server startup crash when lsof is unavailable (#212)</div> | ||
| <div class="commit-meta">2026-03-16 • <span class="lines">+352 / -25</span> lines • 2 files</div> | ||
| </div> | ||
| <div class="commit-card"> | ||
| <div class="commit-subj">fix: resolve TOCTOU race in Resend webhook handler (#226)</div> | ||
| <div class="commit-meta">2026-03-16 • <span class="lines">+340 / -122</span> lines • 2 files</div> |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify whether the report generator escapes git-derived strings before HTML output.
set -euo pipefail
echo "== Candidate generator files =="
fd -i 'insight|report|git' .
echo
echo "== Places where git history is read =="
rg -n -C2 'git log|git show|rev-list|pretty=format|numstat|shortstat' .
echo
echo "== Places where HTML is generated/template strings are built =="
rg -n -C2 '<html|<table|<div class="commit-subj"|innerHTML|template|writeFile|fs\.writeFile|render' .
echo
echo "== Escaping/sanitization helpers present? =="
rg -n -C2 'escape|sanitize|encode|he\.escape|lodash\.escape|entities|replace\(/&|replace\(/</|replace\(/>/' .
echo
echo "Expected: dynamic git strings flow through a dedicated escape function before being inserted into HTML."Repository: bd73-com/fetchthechange
Length of output: 161
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== All script and code files in repo ==="
git ls-files | head -50
echo
echo "=== Search for 'insights-report' references ==="
rg -n 'insights-report' . 2>/dev/null || echo "(no matches)"
echo
echo "=== GitHub Actions workflows that might generate this ==="
find . -path './.github/workflows/*.yml' -o -path './.github/workflows/*.yaml' 2>/dev/null | xargs cat 2>/dev/null || echo "(no workflows found)"
echo
echo "=== Search for report/insight generation in all code files ==="
rg -n -t js -t ts -t py 'insights-report|generateReport|writeReport|renderReport' . 2>/dev/null || echo "(no matches)"
echo
echo "=== Check package.json for build scripts ==="
cat package.json 2>/dev/null | jq '.scripts' 2>/dev/null || echo "(no package.json or no scripts key)"
echo
echo "=== Search for writeFile/fs operations that might write HTML ==="
rg -n 'writeFile|writeFileSync|write.*insights|write.*report' . 2>/dev/null || echo "(no matches)"Repository: bd73-com/fetchthechange
Length of output: 1913
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== Direct search for insights-report anywhere in repo ==="
rg -l 'insights-report' . 2>/dev/null | head -20
echo
echo "=== All files matching *insight* or *report* ==="
fd -i 'insight|report' . 2>/dev/null | head -30
echo
echo "=== Check if insights-report.html is in git tracking ==="
git ls-files | grep -i 'insight\|report'
echo
echo "=== All .js/.ts/.mjs/.mts files for code review ==="
git ls-files | grep -E '\.(js|ts|mjs|mts)$' | head -30
echo
echo "=== Search all code for git command execution or HTML template generation ==="
rg -n 'execSync|execFile|spawn|exec\(' . --type js --type ts --type py 2>/dev/null | head -20Repository: bd73-com/fetchthechange
Length of output: 125
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== All HTML files in repo ==="
find . -name '*.html' -type f 2>/dev/null | head -20
echo
echo "=== Check if file exists and its status ==="
ls -la ./insights-report.html 2>/dev/null || echo "File not found in current directory"
echo
echo "=== Search for any HTML generation with common patterns ==="
rg -n 'innerHTML|document\.write|fs\.write|\.html|\.append|ejs|handlebars|pug' . --type js --type ts --type py 2>/dev/null | head -30
echo
echo "=== Directory structure ==="
ls -la . | head -20
echo
echo "=== All TypeScript/JavaScript files ==="
git ls-files | grep -E '\.(ts|tsx|js|jsx)$' | head -20Repository: bd73-com/fetchthechange
Length of output: 5120
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== Git history of insights-report.html (last 5 commits) ==="
git log --oneline -5 -- ./insights-report.html 2>/dev/null || echo "(no git history)"
echo
echo "=== All script files (.sh, .py, package.json scripts) ==="
find . -name '*.sh' -o -name '*.py' 2>/dev/null | grep -v node_modules | head -20
echo
echo "=== Check package.json scripts ==="
cat package.json 2>/dev/null | grep -A 50 '"scripts"' || echo "(no package.json)"
echo
echo "=== Read first 100 lines of insights-report.html to see actual content ==="
head -100 ./insights-report.htmlRepository: bd73-com/fetchthechange
Length of output: 11254
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== Lines 140-180 of insights-report.html to check commit subject escaping ==="
sed -n '140,180p' ./insights-report.html
echo
echo "=== Search for any occurrence of < or & (escaped HTML) in file ==="
rg -c '<|&|"|&#' ./insights-report.html || echo "No escaped HTML entities found"
echo
echo "=== Check if commit subjects contain any special characters that need escaping ==="
grep -o 'commit-subj">[^<]*</div>' ./insights-report.html | head -20Repository: bd73-com/fetchthechange
Length of output: 3478
Escape all git-derived strings before embedding in HTML to prevent stored XSS.
The report embeds commit subjects and file paths directly into HTML without escaping. Lines 159–176 show commit messages like feat: add automated welcome campaign system (#275) and lines 143–152 show file paths like server/routes.ts inserted as raw text. If git data flows through a generation pipeline, a malicious commit message (e.g., feat: <img src=x onerror="alert(1)">) or crafted file path would execute JavaScript when the report is opened. Apply HTML entity encoding for &, <, >, ", ' before inserting any git-sourced content.
Also applies to: 66–67 (author name)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@insights-report.html` around lines 159 - 176, The commit messages and file
paths are embedded raw into the HTML elements with classes commit-subj and
commit-meta (and author name at lines ~66–67); sanitize all git-derived strings
by applying HTML entity encoding for &, <, >, " and ' before rendering. Add/use
a single escape utility (e.g., escapeHtml) and call it wherever commit-subj,
commit-meta, file path, or author name values are inserted into the template/DOM
so the rendered values are safe from stored XSS.
Summary
Adds a standalone HTML insights report (
insights-report.html) generated from the repository's actual git history. This replaces the broken Claude Code/insightsreport which showed zero sessions despite extensive project activity. The report uses a dark theme matching the app's design system.Changes
insights-report.html— New standalone HTML dashboard with:How to test
git checkout claude/build-insights-dashboard-V3vmxinsights-report.htmlin a browsergit log --oneline | wc -lshould show 50+ commits)https://claude.ai/code/session_01LQtS6mgGPiYt1BTugXsbAH
Summary by CodeRabbit