|
2 | 2 |
|
3 | 3 | Fast Rust CLI/TUI/GUI token usage tracker for Codex usage and Claude Code usage. |
4 | 4 |
|
5 | | -- Unified report across Claude + Codex |
6 | | -- Fast parallel scan + cache |
7 | | -- CLI table, TUI, GUI (`iced` + `tiny-skia`) |
8 | | -- Share image card generator (`tu img`) |
9 | | -- Live monitor with progress bars |
| 5 | +[](https://github.com/hanbu97/tokenusage/actions/workflows/ci.yml) |
| 6 | +[](https://github.com/hanbu97/tokenusage/actions/workflows/release.yml) |
10 | 7 |
|
11 | | -Repository: [github.com/hanbu97/tokenusage](https://github.com/hanbu97/tokenusage) |
12 | | -Crate: [crates.io/crates/tokenusage](https://crates.io/crates/tokenusage) |
| 8 | +`tu` scans local session logs and gives one merged token + cost view across Codex and Claude in CLI, live monitor, and GUI. |
| 9 | + |
| 10 | +**Benchmark:** up to **131.1x faster than `ccusage`** on warm runs (**34.5x** on cold runs) with real local Codex logs. [See full benchmark](#benchmark-details). |
| 11 | + |
| 12 | +## Screenshots |
| 13 | + |
| 14 | +<table align="center" width="100%"> |
| 15 | + <tr> |
| 16 | + <td valign="top" width="50%"> |
| 17 | + <code>tu</code><br/> |
| 18 | + <p align="center"> |
| 19 | + <a href="https://github.com/hanbu97/tokenusage/blob/main/docs/images/cli-demo-padded.png"><img src="https://raw.githubusercontent.com/hanbu97/tokenusage/main/docs/images/thumbs/cli-demo-padded.png" alt="tu cli demo" height="220" loading="lazy" /></a> |
| 20 | + </p> |
| 21 | + </td> |
| 22 | + <td valign="top" width="50%"> |
| 23 | + <code>tu gui</code><br/> |
| 24 | + <p align="center"> |
| 25 | + <a href="https://github.com/hanbu97/tokenusage/blob/main/docs/images/gui-demo.png"><img src="https://raw.githubusercontent.com/hanbu97/tokenusage/main/docs/images/thumbs/gui-demo.png" alt="tu gui demo" height="220" loading="lazy" /></a> |
| 26 | + </p> |
| 27 | + </td> |
| 28 | + </tr> |
| 29 | + <tr> |
| 30 | + <td valign="top" width="50%"> |
| 31 | + <code>tu img day</code><br/> |
| 32 | + <p align="center"> |
| 33 | + <a href="https://github.com/hanbu97/tokenusage/blob/main/docs/images/share-demo.png"><img src="https://raw.githubusercontent.com/hanbu97/tokenusage/main/docs/images/thumbs/share-demo.png" alt="tu img daily demo" height="260" loading="lazy" /></a> |
| 34 | + </p> |
| 35 | + </td> |
| 36 | + <td valign="top" width="50%"> |
| 37 | + <code>tu img week</code><br/> |
| 38 | + <p align="center"> |
| 39 | + <a href="https://github.com/hanbu97/tokenusage/blob/main/docs/images/share-week-demo.png"><img src="https://raw.githubusercontent.com/hanbu97/tokenusage/main/docs/images/thumbs/share-week-demo.png" alt="tu img weekly demo" height="260" loading="lazy" /></a> |
| 40 | + </p> |
| 41 | + </td> |
| 42 | + </tr> |
| 43 | + <tr> |
| 44 | + <td valign="top" colspan="2"> |
| 45 | + <code>tu live codex</code><br/> |
| 46 | + <p align="center"> |
| 47 | + <a href="https://github.com/hanbu97/tokenusage/blob/main/docs/images/live-demo.png"><img src="https://raw.githubusercontent.com/hanbu97/tokenusage/main/docs/images/thumbs/live-demo.png" alt="tu live demo" width="100%" loading="lazy" /></a> |
| 48 | + </p> |
| 49 | + </td> |
| 50 | + </tr> |
| 51 | +</table> |
13 | 52 |
|
14 | 53 | ## Install |
15 | 54 |
|
| 55 | +### cargo (crates.io) |
| 56 | + |
| 57 | +```bash |
| 58 | +cargo install tokenusage --bin tu |
| 59 | +``` |
| 60 | + |
| 61 | +### npm |
| 62 | + |
16 | 63 | ```bash |
17 | 64 | npm install -g tokenusage |
18 | 65 | ``` |
19 | 66 |
|
| 67 | +### cargo-binstall (prebuilt binary) |
| 68 | + |
| 69 | +```bash |
| 70 | +cargo binstall tokenusage --no-confirm |
| 71 | +``` |
| 72 | + |
20 | 73 | ## Quick Start |
21 | 74 |
|
22 | 75 | ```bash |
@@ -48,48 +101,147 @@ tu img day |
48 | 101 | tu img week |
49 | 102 | ``` |
50 | 103 |
|
51 | | -## Screenshots |
| 104 | +## Why tokenusage |
| 105 | + |
| 106 | +- Faster feedback loop: native Rust + parallel scan/parsing + incremental cache. |
| 107 | +- One dashboard for both Codex and Claude, with merged totals and per-model breakdown. |
| 108 | +- Share-ready image card (`tu img`) for posting your token/cost trend. |
| 109 | +- Works in terminal and desktop GUI without sending your logs to a cloud service. |
| 110 | + |
| 111 | +## FAQ |
| 112 | + |
| 113 | +### Where does the data come from? |
| 114 | + |
| 115 | +From local log directories only: |
| 116 | +- Claude: `~/.config/claude/projects`, `~/.claude/projects` |
| 117 | +- Codex: `~/.codex/sessions`, `~/.config/codex/sessions` |
| 118 | + |
| 119 | +You can override with `--claude-projects-dir` and `--codex-sessions-dir`. |
| 120 | + |
| 121 | +### How is cost estimated? |
| 122 | + |
| 123 | +`tu` uses OpenRouter pricing when available, caches it for 6 hours, and falls back to built-in offline rates when network pricing is unavailable. |
52 | 124 |
|
53 | | -[](https://github.com/hanbu97/tokenusage) |
54 | | -[](https://github.com/hanbu97/tokenusage) |
55 | | -[](https://github.com/hanbu97/tokenusage) |
56 | | -[](https://github.com/hanbu97/tokenusage) |
57 | | -[](https://github.com/hanbu97/tokenusage) |
| 125 | +### Is my data private? |
58 | 126 |
|
59 | | -## Why `tu` |
| 127 | +Yes for usage logs: parsing is local. `tu` only requests pricing metadata unless you run `--offline`. |
60 | 128 |
|
61 | | -- Real-world benchmark vs `ccusage` on local Codex logs: |
62 | | -- About **34.5x faster (cold)** and **131.1x faster (warm)** |
63 | | -- Rust-native startup, parallel parsing, incremental cache reuse |
| 129 | +## Benchmark Details |
64 | 130 |
|
65 | | -## Data Sources (default) |
| 131 | +Benchmark setup: |
66 | 132 |
|
67 | | -- Claude: |
68 | | -- `~/.config/claude/projects` |
69 | | -- `~/.claude/projects` |
70 | | -- Codex: |
71 | | -- `~/.codex/sessions` |
72 | | -- `~/.config/codex/sessions` |
| 133 | +- Machine: Apple M3 Max, macOS 15.6.1 |
| 134 | +- Dataset: `~/.codex/sessions` (71 JSONL files, ~537 MB), date range `2025-09-01` to `2026-02-28` |
| 135 | +- `tu` version: `1.1.2` |
| 136 | +- `@ccusage/codex` version: `18.0.8` |
| 137 | +- Both in default mode (online pricing behavior, network enabled) |
73 | 138 |
|
74 | | -You can override with: |
| 139 | +Results: |
75 | 140 |
|
76 | | -- `--claude-projects-dir <PATH>` (repeatable) |
77 | | -- `--codex-sessions-dir <PATH>` (repeatable) |
| 141 | +| Tool | Command | Time | |
| 142 | +|---|---|---:| |
| 143 | +| `tu` (cold, rebuild cache) | `tu codex --rebuild-cache -s 2025-09-01 -u 2026-02-28` | **0.19s** | |
| 144 | +| `@ccusage/codex` (single run) | `ccusage-codex daily -s 2025-09-01 -u 2026-02-28` | **6.56s** | |
| 145 | +| `tu` (warm, avg of 10 runs) | `tu codex -s 2025-09-01 -u 2026-02-28` | **0.052s** | |
| 146 | +| `@ccusage/codex` (warm, avg of 10 runs) | `ccusage-codex daily -s 2025-09-01 -u 2026-02-28` | **6.819s** | |
78 | 147 |
|
79 | | -## Config |
| 148 | +- Cold-run speedup: about **34.5x** |
| 149 | +- Warm-run speedup: about **131.1x** |
80 | 150 |
|
81 | | -Default config search: |
| 151 | +> Notes: results vary by hardware, filesystem cache state, and log volume. |
82 | 152 |
|
| 153 | +## Command Overview |
| 154 | + |
| 155 | +```text |
| 156 | +tu [daily|codex|claude|monthly|weekly|img|session|blocks|live|statusline|gui] |
| 157 | +``` |
| 158 | + |
| 159 | +Useful commands: |
| 160 | +- `tu daily --tui` |
| 161 | +- `tu daily --json` |
| 162 | +- `tu daily --jq '.rows[0]'` |
| 163 | +- `tu blocks --active` |
| 164 | +- `tu blocks --live` |
| 165 | +- `tu live` |
| 166 | +- `tu img --output tokenusage-share.png` (today, hourly) |
| 167 | +- `tu img --period weekly --output tokenusage-week.png` (7 days, daily) |
| 168 | +- `tu img --logo ./logo.png --brand-url tokenusage.dev` |
| 169 | +- `tu statusline` |
| 170 | + |
| 171 | +## Config File |
| 172 | + |
| 173 | +Config search order: |
83 | 174 | 1. `./.tu/tu.json` |
84 | 175 | 2. `~/.config/tu/tu.json` |
85 | 176 | 3. `~/.config/tokenusage/tokenusage.json` |
86 | 177 |
|
87 | | -Explicit config: |
| 178 | +Use an explicit config file: |
88 | 179 |
|
89 | 180 | ```bash |
90 | 181 | tu --config /path/to/tu.json |
91 | 182 | ``` |
92 | 183 |
|
| 184 | +Example: |
| 185 | + |
| 186 | +```json |
| 187 | +{ |
| 188 | + "defaults": { |
| 189 | + "timezone": "Asia/Shanghai", |
| 190 | + "workers": 16, |
| 191 | + "compact": false |
| 192 | + }, |
| 193 | + "commands": { |
| 194 | + "daily": { |
| 195 | + "instances": true |
| 196 | + }, |
| 197 | + "live": { |
| 198 | + "sessionLength": 5, |
| 199 | + "refreshInterval": 1 |
| 200 | + }, |
| 201 | + "img": { |
| 202 | + "period": "daily", |
| 203 | + "bars": 24, |
| 204 | + "brand": "tokenusage", |
| 205 | + "brandUrl": "https://github.com/hanbu97/tokenusage" |
| 206 | + }, |
| 207 | + "weekly": { |
| 208 | + "startOfWeek": "monday" |
| 209 | + } |
| 210 | + } |
| 211 | +} |
| 212 | +``` |
| 213 | + |
| 214 | +## Pricing |
| 215 | + |
| 216 | +```bash |
| 217 | +tu --pricing-file ./pricing.json |
| 218 | +``` |
| 219 | + |
| 220 | +Offline-only mode: |
| 221 | + |
| 222 | +```bash |
| 223 | +tu --offline |
| 224 | +``` |
| 225 | + |
| 226 | +## Demo Dataset (No Real Data) |
| 227 | + |
| 228 | +```bash |
| 229 | +python3 examples/demo/generate_demo_data.py |
| 230 | +tu daily --config ./examples/demo/tu.demo.json --since 2026-02-09 --until 2026-02-28 |
| 231 | +tu live --config ./examples/demo/tu.demo.json |
| 232 | +tu gui --config ./examples/demo/tu.demo.json --since 2026-02-09 --until 2026-02-28 |
| 233 | +tu img --config ./examples/demo/tu.demo.json --since 2026-02-28 --until 2026-02-28 --output ./docs/images/share-demo.png |
| 234 | +tu img --config ./examples/demo/tu.demo.json --period weekly --since 2026-02-22 --until 2026-02-28 --output ./docs/images/share-week-demo.png |
| 235 | +``` |
| 236 | + |
| 237 | +## Development |
| 238 | + |
| 239 | +```bash |
| 240 | +cargo fmt |
| 241 | +cargo clippy --all-targets --all-features |
| 242 | +cargo check |
| 243 | +``` |
| 244 | + |
93 | 245 | ## License |
94 | 246 |
|
95 | | -MIT |
| 247 | +MIT. See [LICENSE](https://github.com/hanbu97/tokenusage/blob/main/LICENSE). |
0 commit comments