4 min read

cost-xray: What Claude Code and Codex Really Cost (GitHub, Scanned)

See what Claude Code and Codex actually send to the API on every turn, and what each part of it costs.

cost-xray repository on GitHub

cost-xray answers a question the usage dashboards cannot: not how much a Claude Code or Codex session cost, but why. It runs a local mitmproxy hop between the agent and the API, records each request, and attributes the tokens in it back to their sources: the system prompt, every tool schema, each MCP server, tool results, prior thinking, your messages. A terminal UI then lets you drill from agent to project to session to a single tool call and see its cache-read, cache-write, fresh and output dollars.

The reason that matters is the invisible prefix. Log-based tools such as ccusage read the transcript, and the transcript never contains the schemas, MCP blocks and reminders assembled at request time, which in a real session can be half the context or more. cost-xray reads the wire, so it can tell you that an MCP server you never call is costing you a fixed amount on every turn. It is small, MIT-licensed, three months old with a single maintainer, and it does one thing well.

🔍
Scan: clean, read the notes. Clean, and small enough that we read all of it. Know three things: it installs a background service and shell wrappers, it reads your existing Claude Code login token to call Anthropic's token counter, and its dependencies are unpinned.

Who it is for

Developers running Claude Code or Codex daily who want to know where the money goes, anyone with several MCP servers configured and a suspicion that some are dead weight, and teams tuning an agent setup for cost.

Getting started

1. Install (the script asks which agents to capture, then installs a local service and shell wrappers)

curl -fsSL https://raw.githubusercontent.com/tigerless-labs/cost-xray/master/install.sh | bash

2. Open a new terminal and use your agent exactly as before

claude

3. Open the live cost view, from any directory

cx

Prefer to read before running? Clone the repository and run ./install.sh from it; the script and everything it does are listed in the scan below. cx stop pauses capture and cx uninstall removes the services and wrappers.

Safety scan

We cloned tigerless-labs/cost-xray at commit 5d69deb on Sep 1, 2026 and ran the checks described on the GitHub Tools page: credential patterns, decode-and-execute code, install-time scripts, committed binaries, risky CI workflows, every host the code talks to, known vulnerabilities in pinned dependencies, and project hygiene. A person read every hit. This is what we found.

  • 65 files, about 8,000 lines of Python and 600 of shell. No secrets, no self-decoding code, no binaries, no telemetry. The only outbound calls in the package are to api.anthropic.com (count_tokens, for calibration) and raw.githubusercontent.com (a pricing table, cached for a day).
  • install.sh clones the repository, installs uv from astral.sh if you do not have it (a curl | sh inside the curl | bash), creates a virtual environment and hands over to run.sh.
  • run.sh appends claude() and codex() shell functions to your .zshrc or .bashrc between marker comments, so the agents route through the local proxy, and registers a launchd agent on macOS or a user systemd unit on Linux so capture starts at login. cx uninstall reverses both. The one sudo in the file is a printed hint about loginctl, not a command it runs.
  • The proxy binds to 127.0.0.1 and redacts Authorization, API keys, cookies and secret-looking body fields before writing anything to ~/.cost-xray. For Codex it generates a local CA that only the codex wrapper trusts; nothing is added to the system trust store.
  • To calibrate its token estimates it reads your Claude Code OAuth token from the macOS Keychain (Claude Code-credentials) or ~/.claude/.credentials.json and uses it against api.anthropic.com. That is a documented feature and the token goes nowhere else, but it is a credential being reused by a third-party tool. COST_XRAY_ANTHROPIC_API_KEY lets you give it a key of its own instead.
  • requirements.txt is three ranges (mitmproxy, tiktoken, rich) with no lockfile, so there is nothing for OSV to check and each install gets whatever is current. One contributor, 30 commits, no tagged release: young, and worth re-reading before each update.
  • One workflow with no third-party actions. Security policy, licence and contributing guide present.

What the scanner counted

CheckResult
SecretsNone found.
Suspicious code2 pattern hits found and read; every one is listed under the raw findings.
Install-time code2 installer scripts (one fetches and runs a remote script; one edits your shell profile; one can call sudo)
Committed binariesNone.
CI workflows1 workflow. None use pull_request_target. No third-party actions.
Network hosts5 distinct hosts referenced from source; most often astral.sh, api.anthropic.com, raw.githubusercontent.com, github.com. No URLs to bare IP addresses.
Known vulnerabilitiesNo lockfile to check: dependencies are declared as ranges, so what gets installed is whatever is current on the day.
Project hygieneHas security policy, licence file, contributing guide. Missing automated dependency updates, CodeQL.
OpenSSF ScorecardNot scored: the project is not in Scorecard's weekly index.

The raw findings

Every hit the scanner wrote out, with a link to the exact line at the scanned commit. Secrets candidates are redacted.

Pattern hits (2)
WhereRuleMatch
install.sh:43download-piped-to-shellcurl -LsSf https://astral.sh/uv/install.sh | sh || true
run.sh:185persistencesystemctl --user enable "$(_k_svc "$1")"
Installer scripts (2)
  • install.sh, 55 lines, fetches and runs a remote script; talks to astral.sh, github.com
  • run.sh, 577 lines, uses sudo, edits your shell profile; talks to api.anthropic.com, www.apple.com

By the numbers

Stars2,350
Forks223
Contributors1
Commits30
Open issues8
Open pull requests4
Releases0
Latest releasenone tagged
LicenceMIT
Main languagePython
Project age3 months
Last pushSep 1, 2026
Tracked files65
Lines of code51.5K
Checkout size2 MB

Lines by language: JSON 41.9K, Python 8,053, Markdown 783, Shell 632, TOML 72, YAML 44.

Questions

Does cost-xray send my data anywhere?

No. The proxy binds to 127.0.0.1, the package has no telemetry, and the only outbound calls in the code are to api.anthropic.com for token counting and to GitHub for a pricing table. Captured traffic is written to ~/.cost-xray with API keys, cookies and secret-looking fields redacted first; delete that folder to clear it.

Does cost-xray change what my agent does or costs?

No. It is a pass-through: the same bytes reach the API, so results and bills are unchanged. Analysis runs separately after the fact. If the proxy is down, the shell wrapper runs the agent directly rather than failing.

How does cost-xray count Claude tokens without Anthropic's tokenizer?

It estimates each part with tiktoken, calibrates the parts it mis-sizes most against Anthropic's count_tokens endpoint using your existing Claude Code login, and scales the split so the total matches the usage figure the API returns. The total, and so the bill, is exact; the split between sources within one request is an estimate.


This post is part of GitHub Tools, where every repository is cloned and scanned before it is written up. The scan is a snapshot of one commit on one day; the repository has moved on since, so check it before you install.