Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Common Development Commands

- **Development server**: `pnpm dev` (runs on port 3000 with Turbopack)
- **Build**: `pnpm build`
- **Lint**: `pnpm lint`
- **Database schema generation**: `pnpm db:generate`
- **Database migrations**: `pnpm db:migrate`
- **Database studio**: `pnpm db:studio`

## Architecture Overview

viberank is a Next.js 15 application that tracks and ranks Claude Code usage statistics. The app has migrated from Convex to PostgreSQL with Drizzle ORM.

### Key Architecture Components

**Database Layer (PostgreSQL + Drizzle)**
- Schema defined in `src/lib/db/schema.ts` with two main tables:
- `submissions`: Stores usage data submissions with daily breakdowns, validation flags, and metadata
- `profiles`: User profiles linked to GitHub accounts
- Database operations centralized in `src/lib/db/operations.ts`
- Configuration in `drizzle.config.ts`

**Authentication**
- NextAuth.js with GitHub OAuth provider
- Configuration in `src/app/api/auth/[...nextauth]/route.ts`
- Environment variables managed through `src/lib/env.ts` with validation

**API Routes Structure**
- `/api/submit`: Main endpoint for usage data submission (supports CLI and OAuth)
- `/api/leaderboard`: Global rankings with filtering
- `/api/profile/[username]`: Individual user profiles
- `/api/stats`: Global statistics
- `/api/admin/flagged-submissions`: Admin moderation interface
- `/api/health`: Health check endpoint

**Data Validation & Integrity**
- Multi-level validation for submissions to prevent gaming
- Automatic flagging system for suspicious data
- Smart merging of overlapping date ranges in submissions
- Validation limits: max $5,000/day, 250M tokens/day, cost-per-token ratios

**Frontend Components**
- `Leaderboard.tsx`: Main ranking display with filtering
- `TokenChart.tsx`: Recharts-based usage visualization
- `FileUpload.tsx`: Drag-and-drop submission interface
- `ShareCard.tsx`: Social sharing functionality
- Profile pages at `/profile/[username]` with detailed analytics

### Environment Setup

Required environment variables (see `.env.example`):
- `DATABASE_URL`: PostgreSQL connection string
- `NEXTAUTH_SECRET`: NextAuth session encryption key
- `NEXTAUTH_URL`: Application URL
- `GITHUB_ID`: GitHub OAuth app ID
- `GITHUB_SECRET`: GitHub OAuth app secret

### Data Flow

1. Users submit Claude Code usage data via CLI tool, web upload, or API
2. Data is validated and processed through `/api/submit`
3. Submissions are stored with daily breakdowns and flagging metadata
4. Leaderboards aggregate data with real-time filtering
5. Profile pages display individual user analytics and charts

### Technology Stack

- **Framework**: Next.js 15 with TypeScript
- **Database**: PostgreSQL with Drizzle ORM
- **Authentication**: NextAuth.js
- **Styling**: Tailwind CSS
- **Charts**: Recharts
- **Build**: Turbopack for development
- **Package Manager**: pnpm (required)
83 changes: 83 additions & 0 deletions DEPLOYMENT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Employee Claude Code Usage Submission Setup

## Installation Instructions

### 1. Copy Files to System Locations

**Prerequisites:**
1. Install ccusage: `npm install -g ccusage` (https://github.com/ryoppippi/ccusage)

```bash
# Copy the script to system location
sudo cp submit-ccusage.sh /usr/local/bin/
sudo chmod +x /usr/local/bin/submit-ccusage.sh

# Edit the plist file to set the correct email address
# Replace "user@company.com" with the actual employee email
nano com.company.ccusage.plist

# Copy the plist to user's LaunchAgents directory
cp com.company.ccusage.plist ~/Library/LaunchAgents/
```

### 2. Load the LaunchAgent

```bash
# Bootstrap the agent (modern approach)
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.company.ccusage.plist

# Enable the agent
launchctl enable gui/$(id -u)/com.company.ccusage
```

### 3. Verify Installation

```bash
# Check if the agent is loaded
launchctl list | grep com.company.ccusage

# Test the script manually
/usr/local/bin/submit-ccusage.sh user@company.com
```

## How It Works

- **Schedule**: Runs daily at 10:00 AM and on system startup
- **Duplicate Prevention**: Uses daily lock files (`/tmp/ccusage-submitted-YYYY-MM-DD`)
- **Email Parameter**: Takes email address as command line argument
- **Data Generation**: Runs `ccusage` command to generate fresh usage data in temp file
- **Logging**: Logs to `/tmp/ccusage-submit.log` and `/tmp/ccusage-submit-error.log`
- **Cleanup**: Automatically removes files older than 7 days and cleans up temp files after submission

## Troubleshooting

### Check Logs
```bash
tail -f /tmp/ccusage-submit.log
tail -f /tmp/ccusage-submit-error.log
```

### Manual Test
```bash
/usr/local/bin/submit-ccusage.sh user@company.com
```

### Uninstall
```bash
# Disable and remove the agent
launchctl disable gui/$(id -u)/com.company.ccusage
launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/com.company.ccusage.plist
rm ~/Library/LaunchAgents/com.company.ccusage.plist
sudo rm /usr/local/bin/submit-ccusage.sh
```

## Email Configuration

The script requires an email address as a command line parameter. In the plist file, this is already configured in the `ProgramArguments` section. Make sure to replace `user@company.com` with the actual employee email address before copying the plist file.

## Requirements

- macOS with LaunchAgent support
- `curl` (pre-installed on macOS)
- `ccusage` installed globally (`npm install -g ccusage`)
- Access to Claude Code for the ccusage tool to read usage data
22 changes: 9 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,32 +68,28 @@ If you prefer to use curl directly:
# Generate usage data
npx ccusage@latest --json > cc.json

# Get your GitHub username
GITHUB_USER=$(git config user.name)
# Get your email address
USER_EMAIL="your-email@example.com"

# Submit to viberank
curl -X POST https://www.viberank.app/api/submit \
-H "Content-Type: application/json" \
-H "X-GitHub-User: $GITHUB_USER" \
-H "X-User-Email: $USER_EMAIL" \
-d @cc.json
```

#### Option 4: Web Upload
#### Option 4: API Only

1. Visit [viberank.app](https://viberank.app)
2. Sign in with GitHub
3. Click "Submit Your Stats"
4. Upload your `cc.json` file
Web uploads have been disabled. Please use the CLI tool (`npx viberank`) or direct API submission methods above.

### Profile Pages

Every user gets a beautiful profile page at `viberank.app/profile/{github-username}` featuring:
Every user gets a beautiful profile page at `viberank.app/profile/{email-address}` featuring:

- 📊 **Usage Chart** - Interactive area chart showing daily costs over time
- 📈 **Statistics** - Total cost, tokens, days active, and averages
- 📝 **Submission History** - Detailed breakdown of all submissions
- 🏷️ **Model Usage** - See which Claude models you use most
- 🔗 **GitHub Integration** - Links to your GitHub profile

### Data Validation & Fair Play

Expand Down Expand Up @@ -208,7 +204,7 @@ Submit usage data programmatically:
```bash
curl -X POST https://www.viberank.app/api/submit \
-H "Content-Type: application/json" \
-H "X-GitHub-User: YOUR_GITHUB_USERNAME" \
-H "X-User-Email: YOUR_EMAIL_ADDRESS" \
-d @cc.json
```

Expand All @@ -217,8 +213,8 @@ Response:
{
"success": true,
"submissionId": "...",
"message": "Successfully submitted data for username",
"profileUrl": "https://viberank.app/profile/username"
"message": "Successfully submitted data for your-email@example.com",
"profileUrl": "https://viberank.app/profile/your-email@example.com"
}
```

Expand Down
8 changes: 8 additions & 0 deletions check_script_run.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Check if the lock file exists (indicates successful submission today)
ls -la /tmp/ccusage-submitted-$(date +%Y-%m-%d)

# View today's log entries
cat /tmp/ccusage-submit.log | grep "$(date +%Y-%m-%d)"

# Check for any errors
cat /tmp/ccusage-submit-error.log 2>/dev/null
40 changes: 40 additions & 0 deletions com.company.ccusage.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.company.ccusage</string>

<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/submit-ccusage.sh</string>
<string>user@company.com</string>
</array>

<key>StartCalendarInterval</key>
<dict>
<key>Hour</key>
<integer>10</integer>
<key>Minute</key>
<integer>0</integer>
</dict>

<key>RunAtLoad</key>
<true/>

<key>StandardOutPath</key>
<string>/tmp/ccusage-submit.log</string>

<key>StandardErrorPath</key>
<string>/tmp/ccusage-submit-error.log</string>

<key>KeepAlive</key>
<false/>

<key>LaunchOnlyOnce</key>
<false/>

<key>ProcessType</key>
<string>Background</string>
</dict>
</plist>
5 changes: 0 additions & 5 deletions convex.json

This file was deleted.

58 changes: 0 additions & 58 deletions convex/schema.ts

This file was deleted.

46 changes: 0 additions & 46 deletions convex/stats.ts

This file was deleted.

Loading