{"id":47708311,"url":"https://github.com/toolsu/ccost","last_synced_at":"2026-04-07T15:01:14.462Z","repository":{"id":347690949,"uuid":"1192694612","full_name":"toolsu/ccost","owner":"toolsu","description":"Analyze Claude Code token usage and costs from local conversation logs and statusline data","archived":false,"fork":false,"pushed_at":"2026-04-02T21:03:12.000Z","size":1618,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-03T04:32:08.612Z","etag":null,"topics":["anthropic","claude","claude-code","cost","token","usage"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/toolsu.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-26T13:23:20.000Z","updated_at":"2026-04-02T21:03:17.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/toolsu/ccost","commit_stats":null,"previous_names":["toolsu/ccost"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/toolsu/ccost","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/toolsu%2Fccost","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/toolsu%2Fccost/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/toolsu%2Fccost/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/toolsu%2Fccost/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/toolsu","download_url":"https://codeload.github.com/toolsu/ccost/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/toolsu%2Fccost/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31516839,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-07T03:10:19.677Z","status":"ssl_error","status_checked_at":"2026-04-07T03:10:13.982Z","response_time":105,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["anthropic","claude","claude-code","cost","token","usage"],"created_at":"2026-04-02T18:08:14.277Z","updated_at":"2026-04-07T15:01:14.426Z","avatar_url":"https://github.com/toolsu.png","language":"Rust","readme":"# ccost \u003cimg src=\"https://raw.githubusercontent.com/toolsu/ccost/main/logo.svg\" alt=\"ccost\" width=\"35\" /\u003e\n\nAnalyze Claude Code token usage and costs from local conversation logs and statusline data.\n\nReads JSONL files from `~/.claude/projects/`, deduplicates streaming entries, calculates costs using LiteLLM pricing, and outputs as table, JSON, Markdown, HTML, CSV, TSV, or braille chart (See [Screenshot](#screenshots)).\n\nThe [`ccost sl` subcommand](#statusline-analysis) ([setup statusline.jsonl first](#setup-for-statuslinejsonl)) analyzes `~/.claude/statusline.jsonl` for rate limit tracking, session summaries, budget estimation, and cost comparison (see [`ccost` vs `ccost sl`](#ccost-vs-ccost-sl)).\n\nBlazing fast CLI and library written in Rust with thorough tests. Also powers [CC Dashboard for Claude Code](https://github.com/toolsu/ccdashboard), a Tauri desktop app for visualizing your Claude Code usage and more.\n\n[![crates.io](https://img.shields.io/crates/v/ccost)](https://crates.io/crates/ccost) [![npm](https://img.shields.io/npm/v/ccost)](https://www.npmjs.com/package/ccost) [![CI](https://github.com/toolsu/ccost/actions/workflows/ci.yml/badge.svg)](https://github.com/toolsu/ccost/actions/workflows/ci.yml) [![License](https://img.shields.io/badge/license-MIT-brightgreen)](https://github.com/toolsu/ccost/blob/main/LICENSE)\n\n[中文文档](https://github.com/toolsu/ccost/blob/main/README.zh.md)\n\n## Install\n\n```bash\nnpm i -g ccost\n```\n\nOr download prebuilt binaries from [GitHub Releases](https://github.com/toolsu/ccost/releases).\n\nOr via Cargo (compiles from source):\n\n```bash\ncargo install ccost\n```\n\n## Quick Start\n\n```bash\nccost                                    # default: by day, then by model\nccost --from 2026-03-01 --to 2026-03-31 # date range\nccost --per model --cost decimal         # by model, 2-decimal cost\nccost --chart cost                       # cost chart over time\n\nccost sl                                 # 5h rate-limit windows (default)\nccost sl --per action                    # rate limit timeline\nccost sl --per 5h --cost decimal         # budget estimation\nccost sl --chart 5h                      # rate limit chart\n```\n\n## CLI Reference\n\n### Grouping\n\n| Flag | Description |\n|------|-------------|\n| `--per \u003cdim\u003e` | Group by: `day`, `hour`, `month`, `session`, `project`, `model`. Up to 2 for nested grouping. Default: `--per day --per model`. |\n| `--order \u003corder\u003e` | Sort: `asc` (default) or `desc`. |\n\nTwo-level grouping creates parent-child rows, e.g. `--per day --per model` shows each day with per-model breakdowns.\n\n### Date Filtering\n\n| Flag | Description |\n|------|-------------|\n| `--from \u003cdate\u003e` | Start date (inclusive). `YYYY-MM-DD` or `YYYY-MM-DDTHH:MM:SS`. |\n| `--to \u003cdate\u003e` | End date (inclusive). |\n| `--5hfrom`, `--5hto` | 5-hour window starting/ending at given time. |\n| `--1wfrom`, `--1wto` | 1-week window starting/ending at given time. |\n\n`--5hfrom`/`--5hto` are mutually exclusive. Same for `--1wfrom`/`--1wto`. The `5h` and `1w` shortcuts cannot be combined with `--from`/`--to`.\n\n### Record Filtering\n\n| Flag | Description |\n|------|-------------|\n| `--project \u003cname\u003e` | Filter by project path (case-insensitive substring). |\n| `--model \u003cname\u003e` | Filter by model name (case-insensitive substring). |\n| `--session \u003cid\u003e` | Filter by session ID (case-insensitive substring). |\n\n### Timezone\n\n| Flag | Description |\n|------|-------------|\n| `--tz \u003ctz\u003e` | `UTC`, fixed offset (`+08:00`), or IANA name (`Asia/Shanghai`). Default: local. |\n\n### Cost Display\n\n| Flag | Description |\n|------|-------------|\n| `--cost \u003cmode\u003e` | `true` (default): integer `$1`. `decimal`: `$1.23`. `false`: hide costs. |\n\n### Output\n\n| Flag | Description |\n|------|-------------|\n| `--output \u003cfmt\u003e` | `json`, `markdown`, `html`, `txt`, `csv`, `tsv`. Writes to file (default: `ccost.\u003cext\u003e`). |\n| `--filename \u003cpath\u003e` | Custom output filename. |\n| `--table \u003cmode\u003e` | `auto` (default), `full`, `compact`. Auto picks compact when terminal \u003c 120 cols. |\n| `--copy \u003cfmt\u003e` | Copy to clipboard. Uses `pbcopy`/`xclip`/`wl-copy`/OSC52. Independent of `--output`. |\n\n### Chart\n\n| Flag | Description |\n|------|-------------|\n| `--chart \u003cmode\u003e` | Braille line chart: `cost` or `token`. |\n\nGranularity auto-selects based on range (hour/day/month). Only `--output txt` works with `--chart`.\n\n### Pricing\n\n| Flag | Description |\n|------|-------------|\n| `--live-pricing` | Fetch latest from LiteLLM (requires network). |\n| `--pricing-data \u003cpath\u003e` | Custom pricing JSON file. |\n\n### Other\n\n| Flag | Description |\n|------|-------------|\n| `--claude-dir \u003cdir\u003e` | Override Claude config directory. Default: `~/.claude` and `~/.config/claude`. |\n| `--help` | Show help. |\n| `--version` | Show version. |\n\n## Statusline Analysis\n\n`ccost sl` command can analyze `~/.claude/statusline.jsonl`, a file produced by a Claude Code statusline hook that snapshots rate limits, cost, duration, and context window usage on every action (see [`ccost` vs `ccost sl`](#ccost-vs-ccost-sl)).\n\n### Setup for statusline.jsonl\n\n#### Automatic Setup\n\nRun in Claude Code on any OS:\n\n```\n/statusline Set up a command-type statusline using ~/.claude/statusline.sh (or ~/.claude/statusline.ps1 on Windows). The script should read stdin and append {\"ts\":\u003cunix_epoch\u003e,\"data\":\u003cstdin_json\u003e} to ~/.claude/statusline.jsonl. Create the script and configure settings.json.\n```\n\n#### Manual Setup\n\n##### Linux, macOS, WSL\n\nOr set it up manually: add to `~/.claude/settings.json`:\n\n```json\n  \"statusLine\": {\n    \"type\": \"command\",\n    \"command\": \"~/.claude/statusline.sh\"\n  }\n```\n\nCreate `~/.claude/statusline.sh`:\n\n```bash\n#!/bin/bash\ninput=$(cat)\necho \"{\\\"ts\\\":$(date +%s),\\\"data\\\":$input}\" \u003e\u003e ~/.claude/statusline.jsonl\n```\n\n```sh\nchmod +x ~/.claude/statusline.sh\n```\n\nIf you already have a statusline script, just append the `echo` line.\n\n##### Windows (PowerShell)\n\nAdd to `~/.claude/settings.json`:\n\n```json\n  \"statusLine\": {\n    \"type\": \"command\",\n    \"command\": \"powershell -NoProfile -File ~/.claude/statusline.ps1\"\n  }\n```\n\nCreate `~/.claude/statusline.ps1`:\n\n```powershell\n$input = $Input | Out-String\n$ts = [int](New-TimeSpan -Start (Get-Date '1970-01-01') -End (Get-Date).ToUniversalTime()).TotalSeconds\n$line = \"{\"\"ts\"\":$ts,\"\"data\"\":\" + $input.Trim() + \"}\"\nAdd-Content -Path \"$env:USERPROFILE\\.claude\\statusline.jsonl\" -Value $line -Encoding UTF8\n```\n\n### View Modes\n\n| Command | Description |\n|---------|-------------|\n| `ccost sl` | 5-hour windows (default) |\n| `ccost sl --per action` | Rate limit timeline with per-action cost |\n| `ccost sl --per session` | By session |\n| `ccost sl --per project` | By project |\n| `ccost sl --per day` | By day |\n| `ccost sl --per 1h` | 1-hour windows within 5h windows |\n| `ccost sl --per 5h` | 5-hour rate-limit windows |\n| `ccost sl --per 1w` | 1-week rate-limit windows |\n| `ccost sl --chart 5h` | 5-hour rate limit % chart |\n| `ccost sl --chart 1w` | 1-week rate limit % chart |\n| `ccost sl --chart cost` | Cumulative cost chart |\n\nThe `session/project/day/1h/5h/1w` views share columns: `Cost`, `Duration`, `API Time`, `Lines +/-`, `Sess`, `5h%`, `1w%`. Window views (`1h/5h/1w`) add `Est 5h Budget` or `Est 1w Budget`. The `1h` view also adds `5h Resets`. The `action` view has its own layout: `Time`, `Cost`, `5h%`, `1w%`, `5h Resets`, `Session`.\n\nThe `5h%` and `1w%` columns show the observed min-max range (e.g. `1-29%`).\n\n### Statusline Flags\n\n| Flag | Description |\n|------|-------------|\n| `--file \u003cpath\u003e` | Statusline file. Default: `~/.claude/statusline.jsonl`. |\n| `--nopromo` | Disable promo adjustment for budget estimation. See below. |\n| `--cost-diff` | Compare statusline cost with LiteLLM pricing. Only with `--per session`. |\n\nAll shared flags (`--from`, `--to`, `--tz`, `--session`, `--project`, `--model`, `--cost`, `--output`, `--filename`, `--copy`, `--order`, `--table`) work with `ccost sl`.\n\n### Segments and Continued Sessions\n\nWhen a session is closed and resumed, cumulative counters reset to zero. `ccost sl` detects these resets and sums across segments correctly.\n\nWhen a session is continued via `claude --continue`, a new session ID is created but cumulative counters (cost, duration, lines) carry over from the predecessor without resetting. `ccost sl` detects this by subtracting each session's first record values as a baseline, so only the work done in the current session instance is counted.\n\nRate limits are account-level and do not reset with sessions.\n\nNote: `--per day` assigns each session to the day it started. Sessions spanning midnight are not split.\n\n### Budget Estimation\n\nWindow views estimate the total rate-limit budget from cost and the delta in rate-limit percentage:\n\n```\nEst 5h Budget = Cost * 100 / delta_5h%    (for --per 1h and --per 5h)\nEst 1w Budget = Cost * 100 / delta_1w%    (for --per 1w)\n```\n\nWhere `delta% = max% - min%` within the window. This uses how much of the rate limit was actually consumed, not the absolute peak.\n\nSince `ccost sl` only sees Claude Code cost, usage from other Claude products (web, desktop, mobile) inflates the denominator without increasing the numerator. This makes the estimate a **lower bound** on the real budget, with the gap proportional to non-CC usage.\n\n### Promo Adjustment\n\nBudget estimates (and **only** budget estimates (\"Est 5h/1w Budget\")) are adjusted by default for known 2x usage promo periods (Dec 2025, Mar 2026). During these promos the rate-limit budget doubles, so the same spend uses half the percentage. Use `--nopromo` to disable:\n\n```sh\nccost sl --per 5h --nopromo\n```\n\nFor windows that partially overlap a promo period, the adjustment scales proportionally.\n\n## Examples\n\n```bash\n# HTML report with decimal cost\nccost --per project --cost decimal --output html --filename report.html\n\n# Filter to a specific session\nccost --session abc123 --from 2026-03-23\n\n# UTC, descending\nccost --tz UTC --order desc --from 2026-03-01\n\n# Opus models only, no cost\nccost --model opus --cost false\n\n# 5-hour window from a specific time\nccost --5hfrom 2026-03-24T10:00:00\n\n# Live pricing\nccost --live-pricing\n\n# Cost chart for last week\nccost --chart cost --1wto 2026-03-25\n\n# CSV by month\nccost --per month --output csv --filename usage.csv\n\n# Two-level: project \u003e model\nccost --per project --per model --table full\n\n# Copy JSON to clipboard\nccost --copy json\n\n# Statusline: budget estimation\nccost sl --per 5h --cost decimal\n\n# Statusline: cost comparison\nccost sl --per session --cost-diff --cost decimal\n\n# Statusline: rate limit chart\nccost sl --chart 5h\n```\n\n## Library API\n\nccost is also a Rust library.\n\n```toml\n[dependencies]\nccost = { path = \"../ccost\" }\n```\n\n### Pipeline\n\n```\nload_records -\u003e calculate_cost -\u003e group_records -\u003e format_*\n```\n\n```rust\nuse ccost::*;\n\nlet options = LoadOptions {\n    from: Some(\"2026-03-01\".to_string()),\n    to: Some(\"2026-03-31\".to_string()),\n    tz: Some(\"UTC\".to_string()),\n    model: Some(\"opus\".to_string()),\n    ..Default::default()\n};\n\nlet result = load_records(\u0026options);\nlet pricing = load_pricing();\nlet priced = calculate_cost(\u0026result.records, Some(\u0026pricing));\n\nlet dimensions = vec![GroupDimension::Day, GroupDimension::Model];\nlet group_options = GroupOptions {\n    order: SortOrder::Asc,\n    tz: Some(\"UTC\".to_string()),\n};\nlet grouped = group_records(\u0026priced, \u0026dimensions, Some(\u0026group_options));\n\nuse ccost::formatters::table::TableOptions;\nlet table_opts = TableOptions {\n    dimension_label: \"Date/Model\".to_string(),\n    price_mode: PriceMode::Decimal,\n    compact: false,\n    color: Some(true),\n};\nlet table = format_table(\u0026grouped.data, \u0026grouped.totals, \u0026table_opts);\nprint!(\"{}\", table);\n```\n\n### Key Types\n\n```rust\nstruct LoadOptions {\n    claude_dir: Option\u003cString\u003e,\n    from: Option\u003cString\u003e,       // YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS\n    to: Option\u003cString\u003e,\n    tz: Option\u003cString\u003e,         // UTC, +HH:MM, or IANA name\n    project: Option\u003cString\u003e,    // substring filter\n    model: Option\u003cString\u003e,\n    session: Option\u003cString\u003e,\n}\n\nenum GroupDimension { Day, Hour, Month, Session, Project, Model }\n\nstruct GroupedData {\n    label: String,\n    input_tokens: u64,\n    output_tokens: u64,\n    cache_creation_tokens: u64,\n    cache_read_tokens: u64,\n    input_cost: f64,\n    cache_creation_cost: f64,\n    cache_read_cost: f64,\n    output_cost: f64,\n    total_cost: f64,\n    children: Option\u003cVec\u003cGroupedData\u003e\u003e,\n}\n```\n\n### Formatters\n\n| Function | Output |\n|----------|--------|\n| `format_table()` | Unicode box-drawing table with optional ANSI colors |\n| `format_txt()` | Same table, no colors |\n| `format_json()` | JSON with `meta`, `data`, `totals`, `dedup` |\n| `format_markdown()` | GFM Markdown table |\n| `format_html()` | Self-contained HTML with sortable columns |\n| `format_csv()` | RFC 4180 CSV |\n| `format_tsv()` | Tab-separated values |\n| `render_chart()` | Braille line chart |\n\n## How It Works\n\n### Data Source\n\nReads JSONL conversation logs from Claude Code's local storage:\n- `~/.claude/projects/*/` (session files and `subagents/`)\n- `~/.config/claude/projects/*/` (alternate location)\n\nBoth are scanned and deduplicated via symlink detection. Subagent transcripts are found in both the old (`\u003cproject\u003e/subagents/`) and new (`\u003cproject\u003e/\u003csession-uuid\u003e/subagents/`) directory structures.\n\n### Deduplication\n\nStreaming entries share the same `messageId:requestId` key with increasing `output_tokens`. Only the highest-output record per key is kept. This dedup is global across all files, preventing double-counting between parent sessions and subagent files.\n\n### Pricing\n\nPer-record cost via model-to-price lookup:\n1. Exact match\n2. Strip date suffix (`-YYYYMMDD` / `@YYYYMMDD`), retry\n3. Substring match among `claude-*` keys\n\nBundled at compile time from LiteLLM. Use `--live-pricing` for latest or `--pricing-data` for custom.\n\n### `ccost` vs `ccost sl`\n\nBelow we'll compare `ccost` (data from `~/.claude/projects/`) and `ccost sl` (data from `statusline.jsonl`).\n\n`~/.claude/projects/` contains per-request JSONL logs with detailed token counts (input, output, cache creation, cache read) for every API call. `ccost` computes cost from these counts using LiteLLM pricing.\n\n`~/.claude/statusline.jsonl` contains periodic snapshots from Claude Code's statusline, including the server-reported cumulative cost and the 5-hour and 1-week rate-limit usage percentages, which are not available anywhere else.\n\nAs shown by `ccost sl --per session --cost-diff`, when LiteLLM pricing is accurate, the cost computed from `~/.claude/projects/` closely matches the server-reported cost in `statusline.jsonl`. The statusline cost may occasionally undercount because it does not always include subagent costs. Since `~/.claude/projects/` has full per-request token breakdowns, it may be the more reliable source for cost.\n\nThe primary value of `statusline.jsonl` is the rate-limit percentages, not cost. This is why [CC Dashboard for Claude Code](https://github.com/toolsu/ccdashboard) uses cost data computed from `~/.claude/projects/` combined with the 5-hour and 1-week rate-limit percentages from `statusline.jsonl`.\n\n### Project Path Decoding\n\nDirectory names like `-home-user-workspace-test` decode to `/home/user/workspace/test`.\n\n## Screenshots\n\n### Terminal\n\n![Terminal output](https://raw.githubusercontent.com/toolsu/ccost/main/screenshot_terminal.png)\n\n### Statusline Analysis (`ccost sl`)\n\n![Statusline output](https://raw.githubusercontent.com/toolsu/ccost/main/screenshot_terminal_sl.png)\n\n### HTML Report\n\n![HTML report](https://raw.githubusercontent.com/toolsu/ccost/main/screenshot_html.png)\n\n## Development\n\n```bash\ncargo test             # run all tests\ncargo build --release  # optimized build\ncargo run -- --help    # CLI help\n```\n\n## License\n\nMIT\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftoolsu%2Fccost","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftoolsu%2Fccost","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftoolsu%2Fccost/lists"}