ccstats is a fast CLI for token and cost usage analytics for Claude Code, OpenAI Codex, Cursor, Grok, and Kimi Code logs.
Search keywords: claude code usage stats, codex usage stats, cursor usage stats, token usage cli, ai token cost tracker.
- Fast local analysis of usage JSONL logs
- Claude Code support (
~/.claude/projects/) - OpenAI Codex support (
~/.codex/sessions/) - Codex weekly quota pace and reset estimates from provider snapshots
- Cursor usage API support (
CURSOR_API_KEYorCURSOR_SESSION_TOKEN) - Grok support (
~/.grok/sessions/) - Kimi Code support (
~/.kimi-code/sessions/) - Daily/weekly/monthly/project/session views
- Top-N leaderboard ranking models or projects by cost share
- Optional model-level token and cost breakdown
- Reusable Rust SDK for embedding local usage and cost summaries in other apps
brew install majiayu000/tap/ccstatscargo binstall ccstatscargo install ccstatscurl -fsSL https://raw.githubusercontent.com/majiayu000/ccstats/main/install.sh | sh
# Install a specific version
curl -fsSL https://raw.githubusercontent.com/majiayu000/ccstats/main/install.sh | VERSION=v0.2.63 shDownload prebuilt archives and SHA-256 checksums from GitHub Releases.
# Install
brew install majiayu000/tap/ccstats
# Today
ccstats codex today
# Daily trend
ccstats codex daily
# Weekly quota pace, remaining percentage, and reset time
ccstats quota
# Same result via unified source flag
ccstats daily --source codexCursor usage comes from Cursor's usage API, not from local state.vscdb files. Enterprise teams should set CURSOR_API_KEY. Individual and self-serve plans should set CURSOR_SESSION_TOKEN to the WorkosCursorSessionToken cookie from cursor.com/dashboard/usage.
# Install
brew install majiayu000/tap/ccstats
# Today
ccstats today --source cursor
# Daily trend
ccstats daily --source cursor
# Same source via alias
ccstats daily --source curGrok support reads each shell.turn.inference_done record from ~/.grok/logs/unified.jsonl. It reports uncached input, cached prompt, completion, and reasoning tokens, then calculates Grok 4.5/4.6 USD cost per inference using xAI's short- or long-context price for the whole request. Observed records are kept in an atomic ccstats ledger because Grok trims the live log in place.
# Install
brew install majiayu000/tap/ccstats
# Today's Grok usage
ccstats grok today
# Daily Grok usage
ccstats grok
# Same source via alias
ccstats daily --source gxKimi Code support reads per-turn usage.record entries from wire logs under ~/.kimi-code/sessions/, including sub-agent usage, and reports actual input/output/cache token usage per turn.
# Install
brew install majiayu000/tap/ccstats
# Today's usage and cost
ccstats kimi today
# Daily breakdown
ccstats kimi
# Same source via alias
ccstats daily --source km- docs.rs: https://docs.rs/ccstats/latest/ccstats/
- crates.io: https://crates.io/crates/ccstats
- The crate-level Rustdoc in
src/lib.rsexplains the SDK entry points and CLI runtime.
ccstats can be used as a Rust library when another app needs structured local usage and cost data without spawning the CLI.
use ccstats::{SummaryOptions, UsageRange, UsageSource, summarize_cost_with_cli_config};
let summary = summarize_cost_with_cli_config(SummaryOptions {
source: UsageSource::Codex,
range: UsageRange::Today,
..SummaryOptions::default()
})?;
println!("today: ${:.2}", summary.cost_usd.unwrap_or(0.0));The SDK uses the same source registry, parsers, aggregation logic, pricing cache, and fallback pricing as the CLI. Use summarize_cost_with_cli_config when SDK output should follow the same persisted CLI defaults for timezone, offline pricing, strict pricing, and currency. Use summarize_cost when the caller wants fully explicit options. Returned summaries include total tokens, cache read/create tokens, cache hit rate, reasoning tokens, per-model breakdowns, cost_usd, and an optional converted cost when SummaryOptions::currency is set.
Codex weekly quota pace is also available as structured SDK data without spawning the CLI:
use ccstats::load_codex_weekly_quota;
let quota = load_codex_weekly_quota(None)?;
println!("weekly used: {:.1}%", quota.used_pct);
println!("projected at reset: {:.1}%", quota.projected_pct_at_reset);Pass Some(codex_home) to read an explicit Codex home without modifying
process environment variables. The explicit path is authoritative and never
falls back to CODEX_HOME or ~/.codex. Missing, stale, malformed, and
unreadable snapshots return typed CodexQuotaError values.
Apps that need several windows at once can use the batch API so source logs, pricing, and currency are loaded once for the request:
use ccstats::{MultiSummaryOptions, UsageRange, UsageSource, summarize_cost_ranges};
let overview = summarize_cost_ranges(MultiSummaryOptions {
source: UsageSource::Claude,
ranges: vec![
UsageRange::Today,
UsageRange::ThisWeek,
UsageRange::ThisMonth,
],
timezone: None,
offline: true,
strict_pricing: false,
currency: Some("USD".to_string()),
})?;
for summary in overview.summaries {
println!("{:?}: ${:.2}", summary.range, summary.cost_usd.unwrap_or(0.0));
}# Today's usage
ccstats today
# Daily breakdown
ccstats daily
# Weekly summary
ccstats weekly
# Monthly summary
ccstats monthly
# By project
ccstats project
# By session
ccstats session
# 5-hour billing blocks
ccstats blocks
# Top-N leaderboard (ranks by cost, falls back to tokens when costs unknown)
ccstats top # top 10 models by cost
ccstats top --dim project --limit 5 # top 5 projects
# With model breakdown
ccstats today -b
# JSON output
ccstats today -j
# Debug mode (timing info)
ccstats today --debug
# Debug model pricing resolution (written to stderr)
# Example: Pricing: glm-5.2 -> glm-5.2 (live)
# Unknown models are reported as: Pricing: <model> -> no match (unknown)
ccstats today --breakdown --strict-pricing --debugBy default, ccstats checks Claude Code logs under ~/.claude/projects/.
If Claude Code uses a moved config directory, set CLAUDE_CONFIG_DIR to the
Claude config root:
CLAUDE_CONFIG_DIR="/path/to/claude-config" ccstats daily --source claude# Codex subcommand mode
ccstats codex daily
# Or use unified source flag
ccstats daily --source codex
# Today's Codex usage
ccstats codex today
# Daily Codex breakdown
ccstats codex daily
# Weekly Codex summary
ccstats codex weekly
# Provider weekly quota pace (same as `ccstats quota`)
ccstats codex quota
# By session
ccstats codex session
# With model breakdown
ccstats codex today -bBy default, ccstats checks Codex sessions under ~/.codex/sessions/. You can
override the Codex home directory with CODEX_HOME:
CODEX_HOME="/path/to/.codex" ccstats codex dailyccstats quota reads the newest server-provided 10,080-minute rate-limit
snapshot from local Codex session logs. It reports the used and remaining
percentages, reset time, projected percentage at reset, and an estimated
depletion time when the current pace would exceed 100%. It also prices local
usage from the exact active quota window and divides it by the reported used
fraction to estimate the full week's API-equivalent USD value and token count.
# Human-readable table
ccstats quota
# Equivalent nested command
ccstats codex quota
# Machine-readable output
ccstats quota --json
ccstats quota --csvThe dollar and token figures are approximations, not official provider
allowances. They vary with the current model and cache mix; token totals are
only comparable while that mix stays similar. Dollar values use ccstats' current
model price resolution; request-level pricing tiers may not be represented. Use
--no-cost to omit the value estimate. Quota estimates are reported in USD, so
an explicit non-USD --currency is rejected. If no current weekly snapshot
exists, the command exits with an error instead of estimating quota from token
totals.
Cursor uses the unified source flag rather than a dedicated subcommand.
# Today's Cursor usage
ccstats today --source cursor
# Daily Cursor breakdown
ccstats daily --source cursor
# Weekly Cursor summary
ccstats weekly --source cursor
# By session/conversation
ccstats session --source cursor
# Cursor alias
ccstats daily --source curAuthenticate with one of:
# Enterprise Admin API key from cursor.com/dashboard/api
CURSOR_API_KEY="..." ccstats daily --source cursor
# Dashboard session cookie for individual / self-serve plans
CURSOR_SESSION_TOKEN="..." ccstats daily --source cursorCURSOR_API_KEY calls POST https://api.cursor.com/teams/filtered-usage-events. CURSOR_SESSION_TOKEN calls the dashboard usage-events endpoint used by cursor.com/dashboard/usage. For tests or offline replay, point CURSOR_USAGE_FILE at a saved JSON payload.
Current limitations:
- ccstats does not read local Cursor SQLite auth tokens. Set
CURSOR_API_KEYorCURSOR_SESSION_TOKENexplicitly. - Project aggregation and 5-hour billing blocks are not supported for Cursor.
- Dashboard session cookies expire; refresh
CURSOR_SESSION_TOKENwhen requests start failing. - Self-serve plans may return token counts with
$0event costs. ccstats records that billed amount instead of estimating Cursor subscription cost from LiteLLM prices.
# Today's Grok usage
ccstats grok today
# Daily Grok usage
ccstats grok
# Weekly Grok usage
ccstats grok weekly
# By session
ccstats grok session
# By project
ccstats grok project
# Grok alias
ccstats daily --source gxBy default, ccstats uses:
~/.grok/logs/unified.jsonlfor per-inference token records~/.grok/sessions/**/summary.jsonfor model, project, and session metadata- the platform cache directory under
ccstats/grok/<source-root>/inference-v1.jsonlfor the durable, deduplicated ledger
For Grok 4.5 and 4.6, requests below 200k prompt tokens use the short-context rates. Requests at or above 200k use the long-context input, cached-input, and output rates for the entire inference. completion_tokens already includes reasoning, so ccstats separates the displayed fields without charging reasoning twice. Rates follow the xAI pricing reference.
If unified.jsonl is unavailable, ccstats retains the older session turn_completed.usage and context-snapshot fallback for installations that do not emit inference telemetry.
You can override the Grok home directory with GROK_HOME:
GROK_HOME="/path/to/.grok" ccstats grokCurrent limitations:
- The durable ledger starts when ccstats first observes an inference. It cannot recover records Grok trimmed before the first run.
- Session fallback totals use the fields available in those files and can differ from the Grok Build weekly allowance.
- Grok models without a published ccstats per-inference tier fall back to the normal pricing resolver.
- Grok 5-hour billing blocks are not supported.
# Today's Kimi Code usage and cost
ccstats kimi today
# Daily Kimi Code breakdown
ccstats kimi
# Weekly Kimi Code summary
ccstats kimi weekly
# By session
ccstats kimi session
# By project
ccstats kimi project
# Kimi alias
ccstats daily --source kmBy default, ccstats reads Kimi Code wire logs under:
~/.kimi-code/sessions/*/*/agents/*/wire.jsonl(main and sub-agent per-turnusage.recordentries)~/.kimi-code/session_index.jsonlfor session-to-project mapping
You can override the Kimi Code home directory with KIMI_CODE_HOME:
KIMI_CODE_HOME="/path/to/.kimi-code" ccstats kimiCurrent limitations:
- Kimi Code subscription models (e.g.
kimi-code/k3) have no public per-token pricing; costs use fallback estimates based on Moonshot's officialkimi-k2.6API rates and are marked asfallbackin structured output. Use--strict-pricingto show N/A instead. - Cache creation tokens are reported but priced at $0 by the Kimi fallback estimate (Moonshot does not publish a separate cache-creation rate).
- Kimi 5-hour billing blocks and tool-call statistics are not supported.
# Bucket by timezone
ccstats daily --timezone UTC
# Locale-aware number formatting
ccstats monthly --locale de
# Filter by date
ccstats daily --since 20260101 --until 20260131
# Monthly budget forecast (uses --until as the as-of date when present)
ccstats monthly --monthly-budget 25 --until 20260415
# Select data source explicitly (supports aliases)
ccstats daily --source codex
# Combine all supported data sources
ccstats monthly --source all
# Cursor source (usage API)
ccstats daily --source cursor
# Cursor alias
ccstats daily --source cur
# Grok source and alias
ccstats daily --source grok
ccstats daily --source gx
# Kimi Code source and alias
ccstats daily --source kimi
ccstats daily --source km
# Offline mode (use cached pricing)
ccstats today -O
# Compact output
ccstats today -c
# Hide cost column
ccstats today --no-costccstats reads an optional TOML config file before command execution. CLI flags override config values.
Search order:
~/.config/ccstats/config.toml- Platform config directory: for example
~/Library/Application Support/ccstats/config.tomlon macOS ~/.ccstats.toml
The first existing config file wins. If that file exists but cannot be read, has invalid TOML, or has a wrong field type, ccstats exits with an error. It does not fall back to defaults or lower-priority config paths. If no config file exists, defaults are used.
Example config.toml:
source = "codex"
timezone = "Asia/Shanghai"
locale = "en"
currency = "USD"
offline = true
strict_pricing = true
compact = true
breakdown = false
order = "desc"
color = "auto"
cost = "show"Supported keys:
| Key | Type | Values |
|---|---|---|
offline |
boolean | true or false |
compact |
boolean | true or false |
no_cost |
boolean | true or false |
no_color |
boolean | true or false |
breakdown |
boolean | true or false |
debug |
boolean | true or false |
strict_pricing |
boolean | true or false |
order |
string | asc, desc |
color |
string | auto, always, never |
cost |
string | show, hide |
timezone |
string | IANA timezone such as UTC or Asia/Shanghai |
locale |
string | Locale used for number formatting, such as en or de |
currency |
string | Currency code such as USD, CNY, or EUR |
source |
string | Source name or alias such as claude, codex, cursor, grok, kimi, or all |
Source root env overrides are independent of config keys:
| Source | Env var | Value | Default when unset |
|---|---|---|---|
| Claude Code | CLAUDE_CONFIG_DIR |
Claude config root containing projects/ |
~/.claude |
| OpenAI Codex | CODEX_HOME |
Codex root containing sessions/ |
~/.codex |
| Cursor | CURSOR_API_KEY or CURSOR_SESSION_TOKEN |
Admin API key or dashboard session cookie | No default; optional CURSOR_USAGE_FILE replay |
| Grok | GROK_HOME |
Grok root containing sessions/ |
~/.grok |
| Kimi Code | KIMI_CODE_HOME |
Kimi Code root containing sessions/ |
~/.kimi-code |
ccstats session --csv now includes:
reasoning_tokenscache_creation_tokenscache_read_tokenscache_hit_rate
Statistical table, JSON, CSV, statusline, top, session, project, and block outputs report prompt-cache hit rate as:
cache_read / (input + cache_creation + cache_read) * 100
Table output uses one decimal place and a % suffix. JSON uses the numeric
cache_hit_rate field, while CSV uses a two-decimal cache_hit_rate column.
Claude, Codex, Cursor, Grok, and Kimi Code expose the required cache-read metric.
Mixed --source all output reports the aggregate rate across all selected usage.
When malformed JSONL records are encountered, ccstats reports them in stderr:
Warning: ignored <N> malformed records
| Source | Directory | Override | Features |
|---|---|---|---|
| Claude Code | ~/.claude/projects/ |
CLAUDE_CONFIG_DIR |
Projects, Billing Blocks, Deduplication |
| OpenAI Codex | ~/.codex/sessions/ |
CODEX_HOME |
Reasoning Tokens |
| All Sources | Multiple | Source-specific env vars | Combined daily/weekly/monthly/today/statusline summaries |
| Cursor | Cursor usage API | CURSOR_API_KEY / CURSOR_SESSION_TOKEN |
Per-event tokens, cache tokens, recorded chargedCents |
| Grok | ~/.grok/logs/unified.jsonl |
GROK_HOME |
Per-inference usage, Projects, Cache / reasoning tokens, 200k pricing tier, durable ledger |
| Kimi Code | ~/.kimi-code/sessions/ |
KIMI_CODE_HOME |
Per-turn usage records, Projects, Cache tokens |
See docs/ARCHITECTURE.md for:
- Adding new data sources
- Data flow and processing pipeline
- Caching mechanism
- Architecture and module boundaries
See docs/algorithm/authoritative-token-accounting.md for:
- Token accounting rules
- Source-specific normalization
- Deduplication semantics
MIT. See LICENSE.
