ai-commits
Open-source AI commit ledger. Public dashboard that tracks the percentage of commits in major GitHub repositories authored by AI agents (Claude Code, Copilot, Codex, Cursor, Devin, Cline, Aider).
Live at: https://holyai.me/ai-commits/
What it does
Every 4 hours we pull the latest 100 commits from ~35 high-signal public repos via the GitHub REST API and classify each commit by the AI tool that signed off in the Co-Authored-By trailer (or by author email / login signature). Results are stored in SQLite (WAL) and surfaced through a dark-themed dashboard with a leaderboard, daily trend, per-tool breakdown, and shareable SVG cards.
Data sources (no mocks, no seed data)
All numbers come from live calls to the public GitHub API:
GET https://api.github.com/repos/{owner}/{repo}— repo metadata (stars, language, description).GET https://api.github.com/repos/{owner}/{repo}/commits?per_page=100— commit list with messages.
Authenticate with a personal-access token (read public scope) to get 5,000 req/h instead of 60. Without a token the scheduler logs a warning and the dashboard surfaces the last successful sync time instead of fabricating data.
Refresh frequency: every 4 hours via node-cron (SYNC_CRON env override available).
AI tool detection
lib/parser.js checks the following signatures in priority order:
| Tool | Trailer pattern | Email pattern | Login pattern |
|------|----------------|---------------|---------------|
| claude | Co-Authored-By: Claude | [email protected] | — |
| copilot | Co-Authored-By: Copilot | @copilot.github.com, +copilot-swe-agent[bot]@users.noreply.github.com | copilot[bot], copilot-swe-agent |
| codex | Co-Authored-By: openai-codex / Codex | @codex.openai.com | codex- |
| cursor | Co-Authored-By: Cursor Agent | @cursor.sh, @cursor.com | cursoragent, cursor[bot] |
| devin | Co-Authored-By: Devin | [email protected] | devin- |
| cline | Co-Authored-By: Cline | [email protected] | cline[bot] |
| aider | Co-Authored-By: Aider | aider.chat | — |
Standard bots (dependabot, renovate, github-actions, [bot] suffix) are detected and excluded from AI counts.
API
All endpoints under BASE_PATH=/ai-commits. No auth required.
GET /ai-commits/health—{"ok":true,"last_sync":"…"}GET /ai-commits/api/summary?window=30d— global aggregates.GET /ai-commits/api/leaderboard?sort=ai_pct&window=30d— repos ranked.GET /ai-commits/api/repos— tracked repo list.GET /ai-commits/api/repo/:owner/:name?window=30d— repo detail with daily timeline.GET /ai-commits/api/timeline?window=30d— global daily AI share series.GET /ai-commits/api/tools?window=30d— per-tool totals.GET /ai-commits/api/share/:owner/:name.svg?window=30d— 1200×630 SVG share card.
window accepts 1d … 365d. sort ∈ ai_pct | ai_total | total | stars.
Run locally
cp .env.example .env
# edit .env: paste a GitHub personal-access token in GITHUB_TOKEN
npm install
npm start
# open http://localhost:4805/ai-commits/
Force an immediate sync (bypassing cron):
npm run sync # one cycle, no backfill
node fetchers/scheduler.js --once --backfill # 5-page backfill per repo (first run)
Stack
Node.js 20 · Express · better-sqlite3 (WAL) · node-cron · helmet · compression · Chart.js (CDN, browser-only) · vanilla JS SPA.
No build step, no front-end framework, no auth, no admin panel.
Layout
ai-commits/
├── server.js # Express app
├── db.js # SQLite schema + prepared statements
├── repos.js # Curated repo list
├── lib/parser.js # AI tool detector
├── lib/sharecard.js # SVG share card renderer
├── fetchers/github.js # GitHub API client
├── fetchers/scheduler.js # Cron + sync orchestration
├── routes/api.js # JSON API
└── public/ # Static SPA
├── index.html
├── app.js
└── style.css
Roadmap (post-MVP)
- Webhook ingestion (push events) for sub-minute latency.
- Per-author leaderboard inside each repo.
- Private repo audit endpoint (BYO token).
- CSV export.
- Org-wide rollups (e.g., all
facebook/*repos combined).