{"id":50824935,"url":"https://github.com/edihasaj/spendwatch","last_synced_at":"2026-06-13T17:33:26.786Z","repository":{"id":364159470,"uuid":"1264475831","full_name":"edihasaj/spendwatch","owner":"edihasaj","description":"Token/$ leaderboards across coding agents (Claude Code, Codex) — see which tool calls, commands, and prompts spend the most, so you know what to automate or fix.","archived":false,"fork":false,"pushed_at":"2026-06-11T21:21:06.000Z","size":58,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-06-11T23:12:14.484Z","etag":null,"topics":["bun","claude-code","cli","codex","coding-agents","cost","llm","observability","tokens"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","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/edihasaj.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-06-09T23:19:26.000Z","updated_at":"2026-06-11T21:21:10.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/edihasaj/spendwatch","commit_stats":null,"previous_names":["edihasaj/spendwatch"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/edihasaj/spendwatch","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edihasaj%2Fspendwatch","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edihasaj%2Fspendwatch/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edihasaj%2Fspendwatch/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edihasaj%2Fspendwatch/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/edihasaj","download_url":"https://codeload.github.com/edihasaj/spendwatch/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edihasaj%2Fspendwatch/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34294412,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-13T02:00:06.617Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["bun","claude-code","cli","codex","coding-agents","cost","llm","observability","tokens"],"created_at":"2026-06-13T17:33:26.174Z","updated_at":"2026-06-13T17:33:26.779Z","avatar_url":"https://github.com/edihasaj.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# spendwatch\n\n[![license: MIT](https://img.shields.io/badge/license-MIT-amber)](LICENSE) ![runtime: Bun](https://img.shields.io/badge/runtime-Bun-black) ![deps: zero](https://img.shields.io/badge/deps-zero-brightgreen)\n\nToken/$ leaderboards **across coding agents** (Claude Code, Codex, …): which **tool calls**, **shell commands**, and **prompts** spend the most — so you know what to automate (build a CLI for `ssh`/`git diff`/`docker compose`…) or fix (a tool dumping huge results into context).\n\nParses each agent's local transcripts. Zero runtime deps, Bun. Agents are split out, with a cross-agent overview on top.\n\n\u003e **Privacy:** spendwatch reads your local transcript files and writes local reports only. It makes **no network calls** and sends nothing anywhere.\n\n## Install\n\nRequires [Bun](https://bun.sh). Run from source, or compile a standalone binary:\n\n```sh\ngit clone https://github.com/edihasaj/spendwatch \u0026\u0026 cd spendwatch\nbun run report                 # run directly\nbun run build                  # → bin/spendwatch (self-contained, embeds Bun + SQLite)\ninstall -m 0755 bin/spendwatch /opt/homebrew/bin/   # optional: put on PATH\n```\n\n## Usage\n\n```sh\nbun src/cli.ts report                      # all agents, past 30 days\nbun src/cli.ts report --agent codex        # one agent (claude,codex,copilot,gemini)\nbun src/cli.ts report --project chat-sql   # filter by project substring\nbun src/cli.ts report --days 7 --json\nbun src/cli.ts report --html               # also write a standalone HTML report\nbun src/cli.ts report --open               # write HTML + open it in the browser\nbun src/cli.ts report --brief              # TL;DR: total, biggest hog, top automate targets\nbun src/cli.ts report --sqlite             # append a snapshot to spendwatch.db\nbun src/cli.ts report --account work       # filter by account (email/label)\nbun src/cli.ts watch                        # live leaderboard, refreshes as sessions write\nbin/spendwatch report                       # compiled binary (bun run build)\n```\n\n`--html [path]` writes a self-contained, shareable `index.html` (default `spendwatch-report.html`): cross-agent overview, per-agent tabs, every table with heat bars, and **click any tool/command row to drill into the actual invocations** (which files, which commands, with counts + token cost) — the \"what to automate\" view. `--open` writes it and opens it.\n\n`--sqlite [path]` appends a normalized snapshot (one run per call) so you can build spend history and query with SQL — tables: `runs`, `agent_account`, `tools`, `commands`, `prompts`, `models`, `projects`, `samples`.\n\n## Multi-account\n\nAccounts are auto-detected per agent (Claude `~/.claude.json` email, Codex auth JWT email). Reports **tag by account but sum per agent**. For multiple accounts in different config dirs, create `~/.config/spendwatch/config.json` (or `$SPENDWATCH_CONFIG`):\n\n```json\n{ \"roots\": [\n  { \"agent\": \"claude\", \"account\": \"work\",     \"path\": \"~/.claude/projects\" },\n  { \"agent\": \"claude\", \"account\": \"personal\", \"path\": \"~/personal/.claude/projects\" },\n  { \"agent\": \"codex\",  \"account\": \"work\",     \"path\": \"~/.codex/sessions\" }\n] }\n```\n\nEach account shows under **BY ACCOUNT**; the agent total (and overview) sum across them. Filter with `--account \u003csubstr\u003e`.\n\n## Sources\n\n| agent   | logs | token usage |\n|---------|------|-------------|\n| Claude Code | `~/.claude/projects/**/*.jsonl` | ✓ |\n| Codex CLI   | `~/.codex/sessions/**/rollout-*.jsonl` | ✓ |\n| Copilot CLI | `~/.config/github-copilot` | ✗ (binary Xodus store, no usage) |\n| Gemini CLI  | `~/.gemini` | ✓ when present |\n\nCopilot/Gemini are detected and reported as footnotes until parseable logs exist. Adding a new agent = one parser emitting the shared `Event` model + a `sources.ts` entry.\n\n## What to automate\n\nThe **AUTOMATE — top targets** list (top of the report, and `--brief`) ranks shell commands by **cost × frequency × friction** — the build-a-CLI/MCP shortlist. Friction is measured, not guessed: Claude `tool_result.is_error` and Codex exit codes. A `why` column tells you the driver:\n\n- `frequent + costly` — high spend, lots of calls → wrap it in one tool\n- `fails N% · flaky` — the command errors often (the agent retries, burning tokens)\n- `exit-127 · agent guessing` — command-not-found: the agent doesn't know this tool → give it a CLI/MCP\n\n\u003e **Honesty note:** spendwatch does **not** invent a \"you saved $X\" number — that's an unmeasurable counterfactual. It shows *observed* cost and *measured* friction (error/retry rate). After you automate something, its cost and error rate drop and you see it in the data.\n\n## What the numbers mean\n\n- **$** — from real per-request `usage` fields (Claude: `cache_creation`/`cache_read`; Codex: `last_token_usage`, summed — verified equal to cumulative). Prices/MTok: Fable $10/$50, Opus $5/$25, Sonnet $3/$15, Haiku $1/$5, gpt-5 tier $1.25/$10 (Codex $ is an estimate — it's largely subscription-billed). Cache: write 1.25× (5m)/2× (1h), read 0.1×.\n- **ctx $** (per tool/command) — est. cost a call's *results* impose on the session: result tokens (chars/4) × one cache write + a 0.1× reread on every later request in that session. Big outputs early in long sessions cost the most.\n- **BY COMMAND** — shell calls split by executable (`echo`, `docker`, `grep`, `ssh`…), skipping `cd X \u0026\u0026`/env/wrappers.\n- **BY COMMAND — DEEP** — executable + subcommand (`git diff`, `docker compose`, `pnpm lint`) and, for `ssh`, the remote command head. This is the \"what to build a CLI for\" list.\n- **BY PROMPT** — spend attributed to the active prompt (`⑂` = subagent / Codex task).\n\n## Layout\n\n- `src/pricing.ts` — price table + cost functions (incl. cache multipliers)\n- `src/parse.ts` — Claude JSONL → events; `commandPath()` deep shell breakdown\n- `src/codex.ts` — Codex rollout JSONL → same events\n- `src/sources.ts` — agent registry: log locations, discovery, account detection, config roots\n- `src/aggregate.ts` — per-session fold → leaderboards + per-account + drill-down samples\n- `src/db.ts` — SQLite snapshot writer (`bun:sqlite`)\n- `src/html.ts` — standalone HTML report with tabs + drill-down\n- `src/scan.ts` — file walk + incremental offsets (watch mode)\n- `src/render.ts` / `src/cli.ts` — tables, cross-agent overview, report/watch\n\n## Test\n\n```sh\nbun test   # claude + codex fixtures with hand-computed costs, deep-command,\n           # incremental append, multi-account sum/breakout, sqlite round-trip\n```\n\n## Contributing\n\nAdding another agent is one parser emitting the shared `Event` model plus a `sources.ts` entry. PRs welcome.\n\n## License\n\n[MIT](LICENSE) © Edi Hasaj\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fedihasaj%2Fspendwatch","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fedihasaj%2Fspendwatch","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fedihasaj%2Fspendwatch/lists"}