Compare your Claude Code usage with your team.
Compares your Claude Code usage with teammates on a shared leaderboard.
/plugin marketplace add pabloprx/vibechampion/plugin install vibechampion@pabloprx-vibechampionCompare your Claude Code usage with your team.
Config stored at: ~/.config/vibechampion/config.json
{
"machine_id": "uuid-v4-generated-once",
"display_name": "your-name",
"team": "TEAM-CODE",
"visibility": "both",
"server": "https://vibechampion.vercel.app",
"acknowledged": true
}
Fields:
machine_id: Unique identifier for this machine (auto-generated UUID, never changes)display_name: Your display name on the leaderboard (can be changed)team: Team code (optional) - if set, shows team leaderboard by defaultvisibility: Where your stats appear - "public", "team", or "both"server: API server URLacknowledged: User accepted data sharingRead ~/.config/vibechampion/config.json. If it doesn't exist or acknowledged is false, run onboarding.
Use AskUserQuestion to collect info. Ask all questions in ONE call with multiple questions:
Question 1: "What's your battle name?"
Question 2: "Team code (optional)"
Question 3: "Where should your stats appear?" (only if team code provided)
Question 4: "VibeBattle tracks ONLY token counts (no code, no prompts). Continue?"
If they accept:
crypto.randomUUID() to generate a unique identifiermkdir -p ~/.config/vibechampioncurl -s -X POST "https://vibechampion.vercel.app/api/teams/{TEAM_CODE}/join" \
-H "Content-Type: application/json" \
-d '{"machine_id": "{MACHINE_ID}", "display_name": "{DISPLAY_NAME}", "visibility": "{VISIBILITY}"}'
If they decline: Exit with "No worries, your stats stay private."
After reading config, check if machine_id exists:
crypto.randomUUID() and save it to configBefore syncing stats, check if user's team membership changed on the server:
# Get user's teams from server using machine_id
curl -s "https://vibechampion.vercel.app/api/users/{MACHINE_ID}/teams"
Response:
{
"teams": [
{"code": "MYCOMPANY", "name": "Acme Corp", "visibility": "both"}
]
}
If server returns a team but local config has no team (or different team):
If server returns no teams but local config has a team:
Get stats from START OF CURRENT MONTH. Calculate the first day of current month in YYYYMMDD format.
# Get first day of current month (e.g., 20260101 for January 2026)
SINCE=$(date +%Y%m01)
npx --yes ccusage@latest daily --json --since $SINCE
Parse the JSON output. The format is:
{
"daily": [
{
"date": "2026-01-05",
"inputTokens": 123,
"outputTokens": 456,
"cacheCreationTokens": 789,
"cacheReadTokens": 1000,
"totalTokens": 2368,
"totalCost": 1.23,
"modelsUsed": ["claude-opus-4-5-20251101"]
}
]
}
POST to https://vibechampion.vercel.app/api/stats:
{
"machine_id": "{machine_id}",
"display_name": "{display_name}",
"daily": [/* array from ccusage */]
}
Use curl:
curl -s -X POST https://vibechampion.vercel.app/api/stats \
-H "Content-Type: application/json" \
-d '{"machine_id": "MACHINE_ID", "display_name": "NAME", "daily": [...]}'
Build the URL based on config:
https://vibechampion.vercel.app/api/leaderboard?period=month (or week, semester, year, all)/vibebattle global: add &team={TEAM_CODE}Examples:
# Global monthly (no team or /vibebattle global)
GET https://vibechampion.vercel.app/api/leaderboard?period=month
# Team monthly (team in config)
GET https://vibechampion.vercel.app/api/leaderboard?period=month&team=MYCOMPANY
Available periods: today, week, month, semester, year, all
Format the leaderboard nicely. Include team name if showing team leaderboard:
VIBE CHAMPION - January 2026
Team: Acme Corp
=============================
# | Name | Archetype | Tokens (M) | Cost ($)
----|----------------|------------|------------|----------
1 | pablo | Vibe Coder | 318.3 | 348.17
2 | diego | Architect | 180.5 | 198.00
3 | carlos | Thinker | 95.2 | 102.30
Your rank: #1 / 3
Stats synced! View full leaderboard: vibechampion.vercel.app/?team=MYCOMPANY
Notes:
Handle these BEFORE doing anything else:
/vibebattle pause - Set "paused": true in config. Say "Auto-sync paused. Run /vibebattle resume to re-enable."/vibebattle resume - Remove paused from config. Say "Auto-sync resumed."/vibebattle reset - Delete config file. Re-run onboarding next time./vibebattle status - Show current config (display_name, machine_id, team, visibility, paused state)/vibebattle join CODE - Join a team:
POST /api/teams/{CODE}/join with machine_id, display_name, and visibility/vibebattle leave-team - Leave current team:
POST /api/teams/{CODE}/leave with machine_id/vibebattle team - Show team leaderboard (if in a team)
/vibebattle - Sync stats and show leaderboard (team if configured, otherwise global monthly)/vibebattle global - Show global leaderboard (ignores team setting)/vibebattle week - Show weekly leaderboard/vibebattle semester - Show semester leaderboard/vibebattle year - Show yearly leaderboard/vibebattle all - Show all-time leaderboard$ARGUMENTS