npm package: @semboja/opencode-claude
Description: Claude usage tracking plugin for OpenCode - monitor tokens, costs, sessions, and API performance
Latest version: 0.2.1

# @semboja/opencode-claude

<p align="center">
  <img src="assets/logo.svg" alt="opencode-claude logo" width="400">
</p>

<p align="center">
  <a href="https://www.npmjs.com/package/@semboja/opencode-claude"><img src="https://img.shields.io/npm/v/@semboja/opencode-claude.svg" alt="npm version"></a>
  <a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT"></a>
  <a href="https://github.com/SembojaTech/opencode-claude/actions"><img src="https://github.com/SembojaTech/opencode-claude/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
</p>

<p align="center">
  Claude usage tracking plugin for OpenCode - monitor tokens, costs, sessions, and API performance.
</p>

## Features

- **Token Tracking**: Input, output, cache read, and cache creation tokens
- **Cost Monitoring**: Track USD costs per request and session
- **Performance Metrics**: API latency and tool execution times
- **Model Breakdown**: Usage statistics per model
- **Tool Analytics**: Track tool invocations and success rates
- **Daily Aggregation**: View usage trends over time
- **Multiple Storage Backends**: File-based or in-memory storage
- **Prometheus Integration**: Export metrics for scraping or push to Pushgateway
- **Grafana Dashboard**: Pre-built dashboard for visualization

## Installation

```bash
npm install @semboja/opencode-claude
# or
bun add @semboja/opencode-claude
```

## Configuration

### 1. Enable OpenTelemetry in OpenCode

Add to your `.opencode/opencode.json`:

```json
{
  "experimental": {
    "openTelemetry": true
  },
  "plugin": ["@semboja/opencode-claude"]
}
```

### 2. Environment Variables (Optional)

| Variable | Default | Description |
|----------|---------|-------------|
| `CLAUDE_TRACKER_STORAGE` | `file` | Storage type: `file` or `memory` |
| `CLAUDE_TRACKER_PATH` | `~/.opencode/claude-usage` | Storage directory path |
| `CLAUDE_TRACKER_VERBOSE` | `0` | Set to `1` for verbose logging |
| `CLAUDE_TRACKER_FLUSH_INTERVAL` | `30000` | Flush interval in milliseconds |

### 3. Prometheus Configuration (Optional)

| Variable | Default | Description |
|----------|---------|-------------|
| `CLAUDE_TRACKER_PROMETHEUS` | `0` | Set to `1` to enable Prometheus metrics server |
| `CLAUDE_TRACKER_PROMETHEUS_PORT` | `9464` | Port for `/metrics` endpoint |
| `CLAUDE_TRACKER_PUSHGATEWAY_URL` | - | Pushgateway URL (e.g., `http://localhost:9091`) |
| `CLAUDE_TRACKER_PUSHGATEWAY_JOB` | `claude_tracker` | Job name for Pushgateway |
| `CLAUDE_TRACKER_PUSHGATEWAY_INTERVAL` | `15000` | Push interval in milliseconds |

## Usage

Once configured, the plugin automatically tracks all Claude API usage. No additional code changes required.

### Viewing Usage Reports

Use the CLI to view your usage:

```bash
# Show usage report
npx claude-tracker report

# List recent sessions
npx claude-tracker sessions 20

# Export as JSON
npx claude-tracker export json > usage.json

# Export as CSV
npx claude-tracker export csv > usage.csv
```

### Example Report Output

```
=== Claude Usage Report ===

Total Sessions: 42
Total API Requests: 1,337
Total Cost: $12.3456

Token Usage:
  Input:              1,234,567
  Output:               456,789
  Cache Read:           789,012
  Cache Creation:       123,456
  Total:              2,603,824

Usage by Model:
  Model                                   Requests         Tokens        Cost
  ---------------------------------------------------------------------------
  claude-sonnet-4-20250514                    1000        1,500,000     $8.5000
  claude-opus-4-20250514                       337        1,103,824     $3.8456

Top Tools:
  Tool                     Calls   Success    Avg Time
  ---------------------------------------------------
  Read                       500     99.8%        12ms
  Edit                       250     98.5%        45ms
  Bash                       200     95.0%       234ms
```

## Cost Calculation

The plugin automatically calculates costs based on Claude model pricing:

| Model | Input (per MTok) | Output (per MTok) |
|-------|------------------|-------------------|
| Claude Opus 4 | $15.00 | $75.00 |
| Claude Sonnet 4 | $3.00 | $15.00 |
| Claude Haiku 4 | $0.80 | $4.00 |

Cache tokens are also calculated:
- Cache read: 10% of input price
- Cache creation: 25% more than input price

Prices are updated as of January 2025. The plugin normalizes model names (e.g., `claude-opus-4-5` → Opus 4 pricing).

## Data Storage

By default, usage data is stored in `~/.opencode/claude-usage/`:

```
~/.opencode/claude-usage/
├── sessions/
│   ├── <session-id>.json    # Session summaries
│   └── ...
└── requests/
    ├── <session-id>.jsonl   # Individual API requests
    └── ...
```

## Tracked Metrics

### Per API Request
- Timestamp
- Model name
- Duration (ms)
- Input tokens
- Output tokens
- Cache read tokens
- Cache creation tokens
- Cost (USD)
- Success/failure status

### Per Session
- Session ID
- Start/end time
- Total tokens by type
- Total cost
- API request count
- Tool usage breakdown
- Per-model breakdown

### Aggregated Statistics
- Total sessions
- Total API requests
- Total tokens by type
- Total cost
- Usage by model
- Usage by day
- Top tools by invocation count

## Prometheus & Grafana Integration

This section provides a complete, step-by-step guide to set up monitoring for your Claude usage using Prometheus and Grafana. No prior experience with these tools is required.

### What is Prometheus and Grafana?

- **Prometheus**: A time-series database that collects and stores metrics (numbers over time)
- **Grafana**: A visualization tool that creates beautiful dashboards from your metrics
- **Pushgateway**: A bridge that accepts metrics from short-lived jobs (like CLI commands)

Together, they let you see charts of your Claude API usage, costs, and performance over time.

### Prerequisites

Before starting, make sure you have:

1. **Docker and Docker Compose** installed
   ```bash
   # Check if Docker is installed
   docker --version
   # Should output something like: Docker version 24.0.0

   # Check if Docker Compose is installed
   docker compose version
   # Should output something like: Docker Compose version v2.20.0
   ```

   If not installed, download from: https://docs.docker.com/get-docker/

2. **Node.js 18+** installed
   ```bash
   node --version
   # Should output v18.0.0 or higher
   ```

3. **The plugin installed** in your OpenCode project
   ```bash
   npm install @semboja/opencode-claude
   ```

### Step 1: Start the Monitoring Stack

First, clone the repository (or copy the docker-compose.yml to your project):

```bash
# Clone the repository
git clone https://github.com/SembojaTech/opencode-claude.git
cd opencode-claude

# Start all services in the background
docker compose up -d
```

You should see output like:
```
[+] Running 4/4
 ✔ Network claude-monitoring       Created
 ✔ Container claude-pushgateway    Started
 ✔ Container claude-prometheus     Started
 ✔ Container claude-grafana        Started
```

### Step 2: Verify Services Are Running

Check that all containers are healthy:

```bash
docker compose ps
```

Expected output:
```
NAME                 STATUS    PORTS
claude-grafana       running   0.0.0.0:3000->3000/tcp
claude-prometheus    running   0.0.0.0:9090->9090/tcp
claude-pushgateway   running   0.0.0.0:9091->9091/tcp
```

Test each service in your browser:

| Service | URL | What You Should See |
|---------|-----|---------------------|
| Prometheus | http://localhost:9090 | Prometheus web UI with query box |
| Pushgateway | http://localhost:9091 | Pushgateway status page |
| Grafana | http://localhost:3000 | Login page (use admin/admin) |

### Step 3: Configure the Plugin

You have two options for sending metrics. Choose based on your use case:

#### Option A: Pushgateway (Recommended for CLI usage)

Best for: Short-lived OpenCode sessions, CLI tools

```bash
# Add to your shell profile (~/.bashrc, ~/.zshrc) or run before starting OpenCode
export CLAUDE_TRACKER_PUSHGATEWAY_URL=http://localhost:9091
export CLAUDE_TRACKER_VERBOSE=1  # Optional: see logs
```

#### Option B: Direct Prometheus Scraping

Best for: Long-running OpenCode sessions, server deployments

```bash
export CLAUDE_TRACKER_PROMETHEUS=1
export CLAUDE_TRACKER_PROMETHEUS_PORT=9464
export CLAUDE_TRACKER_VERBOSE=1  # Optional: see logs
```

**Note**: You can enable both options simultaneously.

### Step 4: Generate Some Test Metrics

Now use OpenCode normally to generate some Claude API calls:

```bash
# Start OpenCode with the environment variables set
opencode
```

Make a few requests to Claude (ask questions, run commands, etc.). The plugin will automatically track:
- Token usage (input, output, cache)
- Costs in USD
- API latency
- Tool invocations

### Step 5: Verify Metrics Are Being Collected

#### If using Pushgateway:

1. Open http://localhost:9091 in your browser
2. You should see metrics listed under "claude_tracker" job
3. Look for metrics like `claude_tokens_total`, `claude_sessions_total`

#### If using direct scraping:

1. Check the metrics endpoint directly:
   ```bash
   curl http://localhost:9464/metrics
   ```
2. You should see output like:
   ```
   # HELP claude_tokens_total Total number of tokens used
   # TYPE claude_tokens_total counter
   claude_tokens_total{type="input",model="claude-sonnet-4"} 1234
   claude_tokens_total{type="output",model="claude-sonnet-4"} 567
   ...
   ```

#### Verify in Prometheus:

1. Open http://localhost:9090
2. In the query box, type: `claude_tokens_total`
3. Click "Execute"
4. You should see your metrics data

If you see "No data points found", wait a minute and try again - Prometheus scrapes every 15 seconds.

### Step 6: Set Up Grafana Dashboard

#### First-time Grafana Login:

1. Open http://localhost:3000
2. Login with:
   - Username: `admin`
   - Password: `admin`
3. You'll be prompted to change the password (you can skip this for local testing)

#### Import the Dashboard:

**Method 1: Auto-provisioned (if using docker-compose)**

The dashboard should already be available:
1. Click the hamburger menu (☰) on the left
2. Click "Dashboards"
3. Look for "Claude Usage Dashboard"

**Method 2: Manual Import**

1. Click the hamburger menu (☰) on the left
2. Click "Dashboards"
3. Click "New" → "Import"
4. Either:
   - Click "Upload JSON file" and select `grafana/claude-usage-dashboard.json`
   - Or paste the contents of the JSON file
5. Click "Load"
6. Select "Prometheus" as the data source
7. Click "Import"

### Step 7: Understanding the Dashboard

The dashboard shows several panels:

| Panel | What It Shows |
|-------|---------------|
| **Total Tokens** | Cumulative token count across all sessions |
| **Total Cost (USD)** | How much you've spent on Claude API |
| **Total API Requests** | Number of API calls made |
| **Total Sessions** | Number of OpenCode sessions |
| **Token Rate by Type** | Input vs output tokens over time |
| **Cost Rate by Model** | Spending per model (Opus, Sonnet, etc.) |
| **API Request Latency** | How fast Claude responds (p50, p95, p99) |
| **API Requests by Status** | Success vs error rates |
| **Top 10 Tools** | Most frequently used tools (Read, Edit, Bash, etc.) |
| **Tool Execution Latency** | How long each tool takes |

### Step 8: Test the Complete Pipeline

Let's verify everything works end-to-end:

```bash
# 1. Make sure environment is set
export CLAUDE_TRACKER_PUSHGATEWAY_URL=http://localhost:9091
export CLAUDE_TRACKER_VERBOSE=1

# 2. Start OpenCode and make some requests
opencode

# 3. In OpenCode, ask Claude something like:
#    "What is 2 + 2?"
#    "Read the README.md file"

# 4. Exit OpenCode (this flushes metrics)
```

Now check your data:

1. **Pushgateway** (http://localhost:9091): Should show new metrics
2. **Prometheus** (http://localhost:9090): Query `claude_sessions_total` - should show at least 1
3. **Grafana** (http://localhost:3000): Dashboard should show updated graphs

### Prometheus Metrics Reference

| Metric | Type | Labels | Description |
|--------|------|--------|-------------|
| `claude_tokens_total` | Counter | `type`, `model` | Total tokens by type (input, output, cache_read, cache_creation) |
| `claude_cost_usd_total` | Counter | `model` | Total cost in USD |
| `claude_api_requests_total` | Counter | `model`, `status` | API request count by status (success/error) |
| `claude_sessions_total` | Counter | - | Total session count |
| `claude_tool_invocations_total` | Counter | `tool`, `status` | Tool invocations by status |
| `claude_api_request_duration_seconds` | Histogram | `model` | API request latency |
| `claude_tool_duration_seconds` | Histogram | `tool` | Tool execution latency |
| `claude_session_tokens` | Gauge | `type` | Current session token counts |
| `claude_session_cost_usd` | Gauge | - | Current session cost |

### Example Prometheus Queries

Try these queries in Prometheus (http://localhost:9090):

```promql
# Total tokens used (all time)
sum(claude_tokens_total)

# Total tokens in the last hour
sum(increase(claude_tokens_total[1h]))

# Current cost in USD
sum(claude_cost_usd_total)

# Cost rate by model ($ per minute)
sum(rate(claude_cost_usd_total[5m])) by (model) * 60

# API request success rate (percentage)
sum(rate(claude_api_requests_total{status="success"}[5m])) /
sum(rate(claude_api_requests_total[5m])) * 100

# 95th percentile API latency (seconds)
histogram_quantile(0.95, sum(rate(claude_api_request_duration_seconds_bucket[5m])) by (le))

# Top 5 most used tools
topk(5, sum(claude_tool_invocations_total) by (tool))

# Average tokens per request
sum(rate(claude_tokens_total[5m])) / sum(rate(claude_api_requests_total[5m]))
```

### Troubleshooting

#### "No data" in Grafana

1. **Check Prometheus is receiving data**:
   - Go to http://localhost:9090
   - Query: `up` - should show `1` for all targets
   - Query: `claude_sessions_total` - should return data

2. **Check Pushgateway has metrics**:
   - Go to http://localhost:9091
   - Look for metrics under the job name

3. **Verify environment variables**:
   ```bash
   echo $CLAUDE_TRACKER_PUSHGATEWAY_URL
   # Should output: http://localhost:9091
   ```

4. **Check plugin logs** (if CLAUDE_TRACKER_VERBOSE=1):
   - Look for "Pushed metrics to Pushgateway" messages

#### Prometheus can't scrape metrics

1. **Check if metrics server is running**:
   ```bash
   curl http://localhost:9464/metrics
   # Should return Prometheus-formatted metrics
   ```

2. **On Linux**, you may need to update `prometheus/prometheus.yml`:
   ```yaml
   # Change from:
   - targets: ['host.docker.internal:9464']
   # To your host IP:
   - targets: ['172.17.0.1:9464']
   ```
   Then restart Prometheus:
   ```bash
   docker compose restart prometheus
   ```

#### Services won't start

1. **Port conflicts** - Check if ports are in use:
   ```bash
   lsof -i :9090  # Prometheus
   lsof -i :9091  # Pushgateway
   lsof -i :3000  # Grafana
   ```

2. **Docker issues** - Reset and try again:
   ```bash
   docker compose down -v
   docker compose up -d
   ```

#### Metrics are stale or not updating

1. **Force a flush** in OpenCode by exiting the session
2. **Check Pushgateway interval**:
   ```bash
   export CLAUDE_TRACKER_PUSHGATEWAY_INTERVAL=5000  # Push every 5 seconds
   ```

### Stopping the Monitoring Stack

When you're done:

```bash
# Stop all services (keeps data)
docker compose down

# Stop and remove all data
docker compose down -v
```

### Advanced: Running in Production

For production use, consider:

1. **Persistent storage**: The docker-compose already includes volumes for data persistence

2. **Security**: Change default Grafana password:
   ```yaml
   # In docker-compose.yml
   environment:
     - GF_SECURITY_ADMIN_PASSWORD=your-secure-password
   ```

3. **Remote Pushgateway**: Point to your production Pushgateway:
   ```bash
   export CLAUDE_TRACKER_PUSHGATEWAY_URL=https://pushgateway.yourcompany.com
   ```

4. **Alerting**: Set up Grafana alerts for cost thresholds:
   - Go to Dashboard → Edit panel → Alert tab
   - Create alert when `claude_cost_usd_total > 100`

## License

MIT