← back to gallery

merge-trail

Live PR-merge leaderboard for AI coding agents on public GitHub

dev-toolsai-agentsgithubleaderboardpull-requestsclaude-codecopilotdevincursorcodexreal-data
Open product ↗

merge-trail

Live PR-merge leaderboard for AI coding agents on public GitHub.

Sibling of agent-bloat (which measures PR size). merge-trail measures the complementary question: of the PRs an agent opens, how many actually merge — and how long do humans spend dragging them across the line?

Eight agents tracked: Claude Code, GitHub Copilot, Cursor, OpenAI Codex, Devin, Aider, Gemini, OpenAI (generic).

What it shows

Per agent, over a rolling 30-day window:

Tie-break ordering on the leaderboard: merge_rate desc, total_prs desc, median_ttm_min asc.

Data sources (all real, all public — no mocks anywhere)

| Endpoint | URL | Cadence |
|---|---|---|
| commits.search | https://api.github.com/search/commits?q="Co-Authored-By: <agent>" committer-date:>=<since> | every 30 min |
| commits.pulls | https://api.github.com/repos/{owner}/{repo}/commits/{sha}/pulls | every 10 min for new commits |
| pulls.detail | https://api.github.com/repos/{owner}/{repo}/pulls/{number} | every 10 min for open + recently-merged PRs |
| pulls.reviews | https://api.github.com/repos/{owner}/{repo}/pulls/{number}/reviews | every 30 min |

Every outbound call is logged to the SQLite fetches table with status, duration_ms, rows, and timestamp — so an auditor can verify every number on the dashboard end-to-end. The transparency endpoint is GET /merge-trail/api/sources.

The leaderboard recomputes every 15 minutes from the pulls table. Daily snapshots go to agent_stats_daily for charting trends over time.

No mocks, no seeds, no Math.random()

This product is built under a strict no-fake-data rule:

Endpoints

| Path | Description |
|---|---|
| GET /merge-trail/ | SPA |
| GET /merge-trail/health | {ok, version, last_refresh_at, total_prs_tracked, has_github_token} — auth-free, used by deploy smoke check |
| GET /merge-trail/api/leaderboard | Current per-agent rollup |
| GET /merge-trail/api/agent/:slug | Per-agent detail + recent PRs + TTM histogram |
| GET /merge-trail/api/prs?agent=&state=&limit= | Paginated PR list |
| GET /merge-trail/api/series/:slug?days=30 | Daily merge-rate time series |
| GET /merge-trail/api/stats | Global counters + fetch-error rate + token status |
| GET /merge-trail/api/sources | Transparency: every endpoint called, last fetched_at, total rows |

No authentication on any route. No Basic Auth, no admin password, no requireAuth middleware anywhere — Arda wants to inspect the dashboard instantly.

Stack

Run locally

cp .env.example .env
# Edit .env to add GITHUB_TOKEN (optional but recommended).
npm install
node server.js

Then open <http://localhost:4791/merge-trail/>.

Deploy

DEPLOY_MANIFEST.json follows the RNDLAB orchestrator schema. The Mac watcher under ~/.openclaw/cowork-deploy-bridge/queue.jsonl picks up the trigger, rsyncs the source to /var/www/projects/merge-trail, registers the systemd unit, attaches the nginx route at /merge-trail, and POSTs to the showcase. Vault injection replaces __INJECT_FROM_VAULT__ with the real GITHUB_TOKEN.

Layout

merge-trail/
├── server.js            -- Express bootstrap, cron scheduling
├── db.js                -- SQLite schema + prepared statements
├── package.json
├── lib/
│   ├── agents.js        -- 8-agent identity table
│   ├── github.js        -- GitHub REST client + fetch logger
│   ├── attribution.js   -- commit-message → agent slug
│   ├── metrics.js       -- median/percentile/summarise (pure)
│   └── time.js          -- ISO/relative-time helpers
├── fetchers/
│   ├── commits.js       -- /search/commits sweep
│   ├── pulls.js         -- commit→PR resolution + PR refresh
│   └── reviews.js       -- CHANGES_REQUESTED counting
├── workers/
│   ├── refresh.js       -- aggregate roll-up
│   └── prune.js         -- old-row cleanup
├── routes/
│   ├── api.js           -- /api/* JSON endpoints
│   └── ui.js            -- SPA + static serving
└── public/
    ├── index.html
    ├── app.js           -- vanilla JS SPA
    └── style.css        -- dark theme

License

MIT. Built by the Cowork R&D pipeline.