RoninForge / BudgetClaw

~1.5k tokens | View as Markdown |

BudgetClaw

v1.7.30

Local spend monitor for Claude Code. Tracks cost per project and git branch, warns before you hit a cap, and kills the process when you blow past it.

Zero keys. Zero prompts. Zero latency added. Reads the JSONL session logs Claude Code already writes locally, and prices every event point-in-time so historical spend stays accurate across Anthropic price changes.

What it does

Per-project, per-branch caps

Set daily, weekly, or monthly limits scoped to a project, a specific git branch, or all projects at once. The tool attributes every Claude Code token to the branch that was checked out when the tool call happened.

Hard kill on breach

Two actions: warn pings your phone via ntfy. kill sends SIGTERM to the Claude Code process and writes a lockfile that catches silent relaunches.

Phone alerts via ntfy

Install the ntfy mobile app, subscribe to a topic, run budgetclaw alerts setup. No signups, no vendor lock-in, BYO server if you want.

Zero network calls by default

Reads ~/.claude/projects/*.jsonl via filesystem watch. No API keys. No prompts sent anywhere. No telemetry. Out of the box the only outbound traffic is your own phone push. Two things can add traffic, and both are off until you turn them on: pricing auto on fetches the signed public price table, and sync sends rollups to Goei. Fully offline stays a supported mode, not a degraded one.

Single static binary

One Go binary, roughly 5 MB. No Node, no Python, no background daemon installer, no launchd entries. Uninstall = rm.

Claude Code plugin

Ships with an optional Claude Code plugin that adds a /spend slash command and a session-start hook. Install separately if you want in-editor status.

Point-in-time pricing

Prices come from the open AI Price Index dataset (CC BY 4.0), embedded in the binary at build time so pricing works offline by default. The dataset carries every rate change with its effective date, so each event is priced at the rate that was live when it ran. A later Anthropic price change does not rewrite your past spend. New models and rate changes land in the dataset within 24 hours, and rate values are verified by hand because a wrong rate would compromise the kill action. A model released after your build is never lost either way: the event is stored with its full token counts and prices itself once the table learns the model, whether that arrives with your next upgrade or, if you opt in, over the network.

Most cost trackers ship a single current-price table, so every price change silently restates their whole history. See what that costs you, with real numbers from a Claude 3.5 Haiku session that three different tools price three different ways.

Optional Goei sync

Run budgetclaw sync to push locally-computed spend rollups to a Goei dashboard at goei.roninforge.org. Only aggregate dollar and token totals leave the machine, never prompts or keys. Opt-in and off by default.

How it works

  1. 1 Watch. A filesystem watcher tails new lines appended to ~/.claude/projects/*.jsonl.
  2. 2 Parse. Each tool-call log carries usage.input_tokens, cache_creation_input_tokens, cache_read_input_tokens, cwd, gitBranch, model, timestamp.
  3. 3 Attribute. Tag the log entry with its project (the cwd basename) and the gitBranch Claude Code already records on the line. No filesystem walk.
  4. 4 Price. Map token counts to cost using the open ai-price-index dataset, embedded at build time. Each event is priced at the rate in effect on its own date, so a later price change never rewrites past spend. Rollups land in a local SQLite file.
  5. 5 Enforce. On cap breach, the configured action fires: notify, or SIGTERM plus lockfile so a silent restart is caught.
$ budgetclaw status

PROJECT     BRANCH        TODAY    WEEK
myapp       main          $4.85    $28.30
myapp       feature/auth  $1.20    $3.20
side-proj   main          $0.00    $0.50
TOTAL                     $6.05    $32.00

$ budgetclaw limit list

#  PROJECT  PERIOD  CAP      ACTION
1  *        daily   $10.00   warn
2  myapp    daily   $5.00    kill

What it will not do

No API keys

BudgetClaw never asks for an Anthropic key and cannot log in to your account. It only reads files you already own.

No prompts captured

Only token counts, cost, project name, and branch name are written to local SQLite. Prompt and response text are ignored.

No proxy, no middle

Not an API proxy. Not a process injector. Claude Code's traffic is completely untouched. Source is MIT, auditable, 100% Go.

Why it exists

After April 2026, a solo developer on raw API billing has no first-party way to cap Claude Code spend per project or per branch. The controls that exist are account-wide, and they arrive as an invoice.

That gap is expensive in a specific way. An agent that gets stuck in a retry loop on a feature branch does not stop to ask. It burns through hundreds of dollars while you are in a meeting, and the first signal is the bill. Claude Code's own /cost reports what already happened, accurately and too late.

BudgetClaw is built around the opposite order: know the number as it moves, and put a hard stop in front of it. A cap is scoped to a project and a branch, so the experiment you expect to be expensive can be capped separately from the work you cannot afford to interrupt. When a cap is breached the matching claude process is sent SIGTERM and a lockfile prevents a silent relaunch, so the stop holds until you lift it.

For the step-by-step version, see How to set a hard spend cap on Claude Code and How to minimize Claude Code costs.

BudgetClaw and ccusage

BudgetClaw covers the same ground as ccusage. Both read the local session logs Claude Code already writes, both turn them into cost and token-usage numbers, and neither asks for an API key or sits between your editor and the API.

It goes further in two directions. The first is enforcement: a hard cap with SIGTERM on breach, rather than a report you read afterwards. A tracker tells you that you spent $400 on Tuesday. BudgetClaw is what stops Tuesday at $50.

The second is point-in-time pricing. Most trackers carry one current-price table, so the day Anthropic changes a rate, every historical total silently changes with it. BudgetClaw prices each event at the rate that was live when it ran, so your March number stays your March number. What that difference looks like in dollars, on a real session three tools price three different ways.

Use it as a ccusage alternative on one machine, or alongside it to keep a shared dashboard current. The side-by-side breakdown lives at Goei vs ccusage.

When a model is too new to price

Anthropic ships models faster than any tool can ship releases, so every local cost tracker eventually meets a model it has no rate for. What it does next is the whole question.

BudgetClaw stores the event either way. An event whose model the pricing table does not recognise keeps its full token counts, is marked unpriced, and prices itself the moment the table learns the model, at the rate effective on its own date. Nothing has to be run and no flag has to be remembered. This matters more than it sounds: the alternative is discarding the event, and the only way back from that is re-reading Claude Code's session logs, which are pruned after roughly a month. A gap noticed in week six would be unrecoverable.

A gap is also never silent. budgetclaw status marks any total covering unpriced events with a trailing +, meaning at least this much, and names the models involved with their event counts. It will not invent a dollar figure for a model it has no rate for.

Closing the gap faster

A daily scheduled job diffs Anthropic's model list against the shipped table to catch new model IDs, and cross-checks every embedded rate against community-maintained pricing data to catch changes to existing ones. Both land in one report, because a new launch usually coincides with a price cut on the tier below it. Detection is automated; the rate value stays a human step, because a wrong auto-merged price could fire a kill too early or too late.

If you would rather not wait for a release, budgetclaw pricing auto on opts in to fetching the published price table directly, which shrinks the window from your next upgrade to about a minute. It is off by default, and fully offline operation stays a supported mode rather than a degraded one.

Opting in sends nothing: no key, no token, no identifier, no usage data, no query string, no cookie. The request carries a user agent and a cache header, and that is the complete list. The one thing it unavoidably reveals is your IP address, to our server, which is true of any request and worth saying plainly rather than glossing.

A downloaded table is only used if its Ed25519 signature verifies against a key compiled into your binary and the contents pass plausibility checks: rates inside a sane per-million-token range, no tenfold jump on a model you already price, no mass disappearance of models, and no going backwards to an older dataset. Anything else is discarded and the table already in force is kept, which is stale but never wrong. The same file is verifiable by hand with the standard minisign tool.

What not to run

A price correction needs no rebuild. Because pricing is point-in-time, a corrected rate adds a new interval rather than rewriting rows already priced at their then-effective rate, and anything stored unpriced settles itself on the next command.

budgetclaw backfill --rebuild is not the tool for it. A rebuild wipes the database and replays from Claude Code's session logs, and those are pruned after about a month while the database keeps everything, so a rebuild can quietly discard months of spend. It now refuses when it would and reports exactly what would be lost, and needs --force to override. Its remaining purpose is repairing a database written by a pre-dedupe binary.

Roll out to a whole team

Each developer installs BudgetClaw on their own machine and runs budgetclaw sync. Goei dedupes every machine and teammate into one rollup, attributed per project, per developer, per git branch. Only aggregate dollar and token totals leave a machine, never prompts and never keys, and no API key changes hands at any point.

That last part is the reason this works in a team at all. The usual way to get shared cost visibility is a gateway everyone routes through, which means someone holds everyone's traffic. Here each machine computes its own numbers locally and sends only the totals, so the shared dashboard never becomes a shared secret. The full walkthrough is at Track Claude Code spend across a team.

Cost visibility inside the editor

To put the number in front of people while they work rather than on a dashboard they have to open, commit the companion claude-code-cost plugin to a repository's .claude/settings.json:

{
  "extraKnownMarketplaces": {
    "roninforge": { "source": { "source": "github", "repo": "RoninForge/claude-code-cost" } }
  },
  "enabledPlugins": {
    "claude-code-cost@roninforge": true
  }
}

This registers the plugin, not the CLI. On the next session in that repository each teammate is prompted once to install it, on Claude Code v2.1.195 or newer. Nothing installs silently.

Upgrading from a pre-machine version

Sync stamps each record with a machine identity so spend from two laptops stays separate instead of merging. That identity is your OS hostname by default, which is not a secret, so sync stays zero-key and zero-prompt. Override it with --machine, the GOEI_MACHINE environment variable, or [goei].machine in config.

If you synced with a version from before that existed, your first sync after upgrading shows a one-time double-count over the re-synced window, 30 days by default. The reason is deliberate: the server now keeps per-machine rows separate and no longer deletes the untagged rows it stored previously, because deleting them would lose data as soon as you sync from a second machine. The old untagged rows and the new machine-tagged rows briefly coexist and add up.

This is a one-time step rather than an ongoing error. It does not grow with each sync, it self-limits as older days age out of the window, and it clears once every machine on the account has upgraded and re-synced, after which the stale untagged rows can be removed. It may trip one spurious budget alert while it settles. New installs are unaffected.

Commands

CommandPurpose
budgetclaw initCreate ~/.budgetclaw/config.toml with sensible defaults.
budgetclaw watchStart the foreground watcher. Run it in a terminal tab or inside a launchd / systemd user service.
budgetclaw statusShow today and this week's spend grouped by project and branch.
budgetclaw limit setAdd a cap: scope, period, amount, action (warn or kill).
budgetclaw limit listList every configured cap and its current consumption.
budgetclaw alerts setupConfigure ntfy topic and test a push end-to-end.
budgetclaw backfillScan historical JSONL logs once to seed the database.
budgetclaw pricing diagnoseList the models your logs contain and whether each one has a rate, so a gap is a fact rather than a suspicion.
budgetclaw pricing auto onOpt in to fetching the signed price table over the network. Off by default; prints exactly what is sent, which is nothing.
budgetclaw pricing refreshFetch and verify the price table now. Requires the opt-in above, or --force for one fetch without changing the setting.
budgetclaw syncPush aggregate spend rollups to a Goei dashboard. Opt-in, dollar and token totals only.

Frequently asked questions

How does BudgetClaw track Claude Code spending? +

BudgetClaw reads the JSONL session log files that Claude Code already writes to ~/.claude/projects/ on your machine. It parses token counts and prices each event point-in-time, at the Anthropic rate that was in effect when the event ran, using the open ai-price-index dataset embedded at build time. Cost per project and git branch stays accurate even after a price change. It never touches API traffic, never sees your prompts, and never requires API keys.

What happens when I hit a budget limit? +

You configure limits with actions: "warn" sends a phone notification via ntfy, "kill" sends SIGTERM to the Claude Code process and writes a lockfile that prevents silent relaunches. You can set different limits per project, per branch, and per time period (daily, weekly, monthly).

Does BudgetClaw work with Claude Max plan or only API usage? +

BudgetClaw works with any Claude Code setup that writes local JSONL session logs. For API-billed usage, exact dollar costs are calculated from token counts. For Pro and Max subscriptions where billing is flat-rate, token consumption is still tracked as a usage metric so you can see which projects are burning the most of your plan.

Is BudgetClaw a proxy? Does it intercept API calls? +

No. BudgetClaw is a local telemetry reader, not a proxy. It never sits between your code editor and the Anthropic API. It reads log files that already exist on your filesystem. Zero keys, zero prompts, zero latency added.

Where does BudgetClaw store its data? +

Locally in ~/.budgetclaw/ as a single SQLite file. Config is at ~/.budgetclaw/config.toml. No network calls except optional phone alerts to your chosen ntfy server.

How do I install BudgetClaw? +

Run curl -fsSL roninforge.org/get | sh. This downloads a single Go binary (about 5 MB) with no runtime dependencies. Supports macOS (arm64, amd64) and Linux (amd64, arm64). Or use Homebrew: brew install roninforge/tap/budgetclaw. Prefer a manual download? Grab a binary from the latest release.

How do I uninstall BudgetClaw? +

Delete the binary (usually /usr/local/bin/budgetclaw or ~/.local/bin/budgetclaw) and remove ~/.budgetclaw/. That's it. No background daemons to stop, no launchd entries, no cron jobs.

How does BudgetClaw stay up to date when Anthropic ships a new model or changes prices? +

Pricing is sourced from the open ai-price-index dataset (CC BY 4.0), embedded in the binary at build time. The dataset carries every rate change with its effective date, so BudgetClaw prices each event at the rate that was live when it ran rather than today's rate. New models and rate changes land in the dataset within 24 hours, verified by hand against the Anthropic pricing page. Detection is automated; the rate value stays a human step because a wrong rate could fire a kill too early or too late. Nothing needs running after a correction lands: an event whose model the table does not know is stored with its full token counts rather than discarded, and it prices itself as soon as the table learns the model. Do not reach for backfill --rebuild here. It wipes the database and replays from Claude Code's session logs, which are pruned after roughly a month, so it can destroy spend the database still holds. It refuses when it would.

BudgetClaw is one of several tools from RoninForge.org: Hanko validates Claude Code plugin manifests, Tsuba scaffolds plugins and skills, and Goei rolls spend up across machines and teammates.