sculptdotfun
viberank
TypeScript

๐Ÿ† The AI coding usage leaderboard โ€” Claude Code, Codex, Gemini CLI & more. Real costs and tokens from ccusage data. Submit with: npx viberank-cli

Last updated Aug 7, 2026
113
Stars
18
Forks
3
Issues
+1
Stars/day
Attention Score
67
Language breakdown
TypeScript 91.0%
JavaScript 6.1%
PLpgSQL 1.8%
CSS 0.7%
Shell 0.4%
โ–ธ Files click to expand
README

viberank

A community-driven leaderboard for AI coding usage โ€” Claude Code, Codex, Gemini CLI and every other tool ccusage tracks. Submit your stats and see how you rank.

viberank โ€” a global multi-tool AI coding leaderboard. Submit your ccusage stats from Claude Code, Codex, Gemini and more, and see how you rank by cost, tokens, and days active.

viberank License Next.js TypeScript

Live at viberank.app.

v2 โ€” multi-tool support. viberank started as a Claude Code leaderboard. As ccusage grew to track Codex, Gemini CLI, Copilot, OpenCode and more, viberank evolved with it: submissions from any supported tool are now accepted, recorded per tool, and filterable on the leaderboard. Claude Code remains a first-class citizen โ€” you can now just see how it stacks up against the rest of your stack. Full details in the CHANGELOG.

Features

  • ๐Ÿ† Global leaderboard โ€” top-3 podium + full table, sorted by cost or tokens, with 7d / 30d / custom date filters
  • ๐Ÿงฐ Multi-tool โ€” usage from Claude Code, Codex, Gemini CLI, Copilot, OpenCode and other ccusage-supported agents; every row shows tool chips and the board filters per tool
  • ๐ŸŽฏ Per-tool boards โ€” dedicated leaderboards at /tool/claude, /tool/codex, /tool/gemini, /tool/copilot, /tool/opencode
  • ๐Ÿ“Š Profile pages at viberank.app/profile/{username} โ€” global rank, daily charts, token breakdown, tools used
  • โšก Server-rendered โ€” homepage, profiles, and tool boards are SSR'd with structured data (FAQPage, ProfilePage, BreadcrumbList) for fast paint and full crawlability
  • ๐Ÿš€ Four ways to submit: npx viberank-cli, plain curl, signed-in web upload, or MCP
  • โ™พ๏ธ Autosubmit โ€” viberank login once, viberank autosubmit once, and your rank stays current instead of freezing on the day you first submitted
  • ๐Ÿ” GitHub OAuth + API tokens โ€” OAuth and token submissions show a blue check; header-only CLI submissions show a cli pill
  • ๐Ÿ–ฅ๏ธ Multi-machine โ€” a laptop and a desktop sum into one profile instead of overwriting each other
  • ๐Ÿ“ˆ /stats โ€” site-wide spend curve, monthly trend, and where your burn lands against everyone else
  • ๐Ÿงฎ /calculator โ€” which subscription tier your actual usage justifies, based on your real ccusage numbers rather than a guess
  • ๐ŸŽ–๏ธ README badges โ€” https://www.viberank.app/api/badge/{username} for rank, cost, or tokens
  • ๐Ÿ›ก๏ธ Input validation โ€” one-sided token math (reasoning-token aware), cost/token ratio guard, date sanity, realistic-range ceilings
  • ๐Ÿ”„ Merge flow โ€” re-submitting the same range overwrites prior daily entries; merging combines unverified CLI rows into your verified profile
  • โœ๏ธ Blog โ€” data-backed posts on AI coding costs at viberank.app/blog

Submitting your usage data

Option 1: npx viberank-cli (recommended)

npx viberank-cli

This generates a fresh cc.json via ccusage daily --json (the aggregate report across all your detected tools) and POSTs it to /api/submit. It picks up your GitHub username from your git remote / git config user.name.

Set it and forget it. A one-off submission freezes your rank on the day you ran it. Mint a token at viberank.app/settings/tokens, then:

npx viberank-cli login       # paste the token once
npx viberank-cli autosubmit  # daily background submission

autosubmit registers with your platform's own scheduler โ€” launchd, systemd user timers, or Task Scheduler โ€” rather than running a daemon of its own, so it survives reboots and catches up after a missed run. npx viberank-cli status shows the token and schedule state; autosubmit off removes it. Token submissions are verified, so they carry a blue check without a browser sign-in.

Option 2: curl

npx ccusage@latest daily --json > cc.json
curl -X POST https://www.viberank.app/api/submit \
  -H "Content-Type: application/json" \
  -H "X-GitHub-User: $(git config user.name)" \
  -d @cc.json
ccusage v20 keys daily entries by period and reports an agent per day; viberank normalizes this server-side, so either the new or older ccusage output works.

Option 3: Web upload

  • Sign in to viberank.app with GitHub
  • Click Submit Stats โ†’ Upload cc.json
  • Drop your cc.json file
Web uploads come back with a verified badge automatically. CLI submissions show as unverified until you sign in and merge them via the prompt on the homepage.

Option 4: MCP server

If you use an MCP-compatible client, viberank-mcp (source) exposes submit and lookup tools:

npx viberank-mcp

Data validation

Submissions are checked at the API level. Anything that fails these rules is rejected:

  • Token math โ€” total >= input + output + cachecreation + cacheread. The total may legitimately exceed the four components because reasoning/thinking tokens (Gemini, Codex, Claude extended thinking) are counted in totalTokens but not broken out by ccusage. We only reject a total that is less than its known parts.
  • Cost/token ratio โ€” must fall within a realistic band; this is the primary guard against inflated token counts now that the token-sum check is one-sided
  • No negative values anywhere in totals or daily breakdowns
  • Valid date format โ€” YYYY-MM-DD
  • Not too far in the future โ€” dates after tomorrow-UTC are rejected (covers users at any global timezone offset)
  • Realistic ranges โ€” total cost can't exceed $5,000 ร— 365 days
Submissions can also be flagged for review by an admin via /admin; flagged rows are hidden from the leaderboard by default.

See VALIDATION.md for the full ruleset.

Merging multiple submissions

If you submit via the CLI before signing in, the row lands on the leaderboard as unverified (cli pill). Once you sign in with the matching GitHub account, the homepage shows a banner offering to verify or merge. That hits an authenticated /api/claim endpoint which:

  • Finds all submissions under your GitHub username
  • Picks a base submission (OAuth-verified row wins; else most recent)
  • Merges daily breakdowns โ€” overlapping dates take the OAuth version
  • Recomputes totals, sets verified: true, deletes the duplicates

Submitting from more than one machine

Supported โ€” a laptop and a desktop sum into one profile rather than overwriting each other (#43).

Each machine generates an anonymous random UUID on first run, stored at ~/.viberank/machine-id. The server keeps usage as a per-machine slice and re-sums them, so re-submitting from one machine replaces only that machine's contribution and leaves the others intact. No hardware or identifying information is involved.

Two consequences worth knowing:

  • A machine's totals never silently decrease. If a re-submission reports less than that machine previously contributed โ€” a pruned ~/.claude/projects, a fresh install, a partial export โ€” the higher prior figure is retained instead. Deleting local transcripts doesn't erase your rank.
  • Genuine deletion is still recorded. The CLI reports per-month file and byte counts of your transcript corpus, and the server classifies a shrink as deleted vs rewritten rather than guessing (#112). Counts only โ€” no transcript content ever leaves your machine.

Development

Prerequisites

  • Node.js 18+ and pnpm 10+
  • A Supabase project (free tier is fine)
  • A GitHub OAuth app

Setup

git clone https://github.com/sculptdotfun/viberank.git
cd viberank
pnpm install
cp .env.example .env.local

Fill in .env.local (see .env.example for the full list). The required keys are:

NEXTPUBLICSUPABASE_URL=https://<project-ref>.supabase.co
NEXTPUBLICSUPABASEANONKEY=<anon-key>
SUPABASESERVICEROLE_KEY=<service-role-key>

NEXTAUTH_URL=http://localhost:3000 NEXTAUTH_SECRET=<openssl rand -base64 32>

GITHUB_ID=<github-oauth-client-id> GITHUB_SECRET=<github-oauth-client-secret>

Apply the schema:

# Run the SQL in supabase/migrations/ in order against your project,

either via the Supabase SQL editor or the supabase CLI:

001initialschema.sql

002multitool.sql # submissions.tools[] + daily_breakdowns.agents[]

003opento_work.sql # hire-me flags on profiles

004modelbreakdowns.sql # per-model token/cost split

005machinecontributions.sql # per-machine slices (#43)

006rawsubmissions.sql # raw payload archive

007sitestats.sql # cached site-wide aggregates

008sitestatsmonthlytiers.sql

009opentoworkemail.sql

010apitokens.sql # hashed CLI tokens

011_efficiency.sql # cost-per-token, generated column

012corpusobservations.sql # per-month corpus counts for drift (#112)

Applying migrations to an existing instance: apply the SQL before deploying the app code. Every migration is additive โ€” new columns default to empty and new tables are created IF NOT EXISTS โ€” so each is safe to run ahead of its deploy.

Run the dev server:

pnpm dev

Open .

For local visual QA without a Supabase project, enable the built-in demo data:

NEXTPUBLICVIBERANKDEMODATA=1 pnpm dev

Demo data is read-only and only intended to render realistic leaderboard, profile, model-list, and hire-page states during UI review.

Useful scripts

| Command | What it does | |---|---| | pnpm dev | Start Next dev server (Turbopack) on port 3000 | | pnpm build | Production build | | pnpm start | Serve the production build | | pnpm lint | Run next lint | | pnpm test | Run every test/*.test.mts suite โ€” ccusage parsing, data layer, submissions, tokens, badges, corpus scanning, drift classification, plan comparison. Exits on the first failure. node --import tsx test/ccusage.test.mts <path-to-cc.json> additionally tests against real data | | pnpm exec tsc --noEmit | Type-check without emitting |

Tech stack

  • Frontend: Next.js 16, React 19, TypeScript 5, Tailwind CSS 4
  • Backend: Next.js API routes + Supabase (Postgres)
  • Auth: NextAuth.js v4 with GitHub OAuth
  • Charts: Recharts
  • Animation: Framer Motion
  • Hosting: Vercel

API

POST /api/submit

Submit usage data. Authenticated submissions (with a NextAuth session cookie) are marked verified: true; otherwise the request must include an X-GitHub-User header.

Body: contents of cc.json (output of npx ccusage@latest daily --json).

Auth, in precedence order:

| | Verified | Notes | |---|---|---| | Authorization: Bearer vbr_โ€ฆ | โœ… | API token; works headlessly, which is what autosubmit uses | | NextAuth session cookie | โœ… | Web upload | | X-GitHub-User: <name> | โŒ | Unauthenticated; anyone can set it, so the row shows a cli pill |

Response:

{
  "success": true,
  "submissionId": "...",
  "message": "Successfully submitted data for username",
  "profileUrl": "https://viberank.app/profile/username"
}

POST /api/claim

Authenticated โ€” merges unverified CLI submissions into the caller's verified profile. Username is taken from the session, not the request body. Returns 401 without a session.

GET|POST /api/tokens, DELETE /api/tokens/{id}

Authenticated (session only โ€” a token cannot mint another token). Lists, creates and revokes API tokens for the signed-in user. Only the SHA-256 of a token is stored; the plaintext is shown once at creation and is unrecoverable afterwards. Revocation is soft, so lastusedat stays auditable after a suspected leak. UI at /settings/tokens.

GET /api/badge/{username}

Public, unauthenticated. Returns a shields-style SVG for a README:

viberank
spend
tokens

metric is rank (default), cost, or tokens. Hand-built SVG rather than a rasterised image so it stays a few hundred bytes and sits crisply next to shields.io badges; cached at the edge with stale-while-revalidate.

POST /api/admin/flag

Admin-only (allowlist in src/lib/admin.ts) โ€” flags or unflags a submission for review. Runs server-side with the service-role client; returns 403 for non-admins.

GET /api/health

Returns backend status:

{ "api": "ok", "backend": "supabase", "backendConnection": "ok", "timestamp": "..." }

Deployment

Designed to run on Vercel. Push to main to trigger an auto-deploy. The required production env vars are the same as .env.example; make sure SUPABASESERVICEROLEKEY and the NEXTPUBLIC_* Supabase vars are also listed in turbo.json's build.env allowlist so Turbo passes them through.

Deploy with Vercel

Contributing

See CONTRIBUTING.md.

License

MIT.

Acknowledgments

Links

๐Ÿ”— More in this category

ยฉ 2026 GitRepoTrend ยท sculptdotfun/viberank ยท Updated daily from GitHub