Getting started
burn is a local HTTP proxy and a SQLite ledger. Your SDK sends requests to burn instead of the provider. burn forwards them unchanged, reads the token usage from the response, prices the request, and writes one row to a database on your machine.
Requirements
- Node 22.5 or newer. burn uses the built-in
node:sqlitemodule, so there are no runtime dependencies to install. - An API key for the provider you already use. burn does not replace or store it. The proxy forwards your authorization header to the upstream provider.
Start the proxy
You can run the package without installing it globally:
$ npx @xnah/burn proxyThe proxy prints the routes it knows and the export lines for your shell:
burn proxy listening on http://127.0.0.1:8787
providers: openai, anthropic, openrouter, deepseek, groq, gemini
export OPENAI_BASE_URL=http://127.0.0.1:8787/openai/v1
export ANTHROPIC_BASE_URL=http://127.0.0.1:8787/anthropic
point your SDK at those URLs. Ctrl+C to stop.Leave it running. If you would rather install the command once:
$ npm install -g @xnah/burnThen use burn proxy, burn today, burn ui, and the rest directly. The default proxy port is 8787. Change it with --port:
burn proxy --port 8788Point your SDK at it
For OpenAI, set the base URL to the OpenAI route. The /v1 stays on the end:
import OpenAI from 'openai';
const client = new OpenAI({
baseURL: 'http://127.0.0.1:8787/openai/v1',
});
const response = await client.chat.completions.create({
model: 'gpt-4o-mini',
messages: [{ role: 'user', content: 'Say hello in five words.' }],
});
console.log(response.choices[0].message.content);For Anthropic, set the base URL to the Anthropic route. Do not add /v1; the Anthropic SDK appends it:
import Anthropic from '@anthropic-ai/sdk';
const client = new Anthropic({
baseURL: 'http://127.0.0.1:8787/anthropic',
});
const message = await client.messages.create({
model: 'claude-sonnet-4-5',
max_tokens: 128,
messages: [{ role: 'user', content: 'Say hello in five words.' }],
});If you prefer to export the variables instead of editing code, burn env prints the same two lines that burn proxy prints:
eval "$(burn env)"That command is for a POSIX shell. In PowerShell or cmd, copy the lines from burn env and set the variables in the way that shell expects, or use burn run as described below.
See your spend
After a request completes, the row is already in the database. These commands read it:
burn today
burn by-model --since 7d
burn uiburn today prints a summary from local midnight. burn by-model --since 7d groups the last seven days by model. burn ui serves the dashboard on http://127.0.0.1:4747.
The dashboard is a local page. It does not load a CDN, a font, or anything else from the network.
The one-command version
burn run starts a proxy on a random port, sets OPENAI_BASE_URL and ANTHROPIC_BASE_URL for a child process, runs your command, then prints what that run cost:
burn run -- node ./agent.jsThe child process exits with its own exit code, and burn prints a summary like this:
that run took 12.4s and exited 0: 9 requests, $0.0841The random port is only open for the lifetime of the command. This is useful for one-off scripts and evaluations where you do not want to manage a long-running proxy.
Where data lives
Everything is under ~/.burn:
| File | What it is |
|---|---|
burn.db | The SQLite ledger. One row per request with usage was reported. |
config.json | Custom providers, price overrides, the budget, and an optional proxy port. Created when you first change one of those settings. |
prices.json | The cached price list and a fetchedAt timestamp. Refreshed when it is more than 24 hours old. |
Set BURN_HOME before starting burn to move all three somewhere else:
BURN_HOME=/tmp/burn-ledger burn uiThe proxy and the UI must use the same BURN_HOME to see the same ledger.
Next steps
- Setup: OpenAI, Anthropic, other providers,
burn run, tags, and custom providers. - CLI reference: every command and flag.
- Dashboard: ranges, panels, and demo mode.
- Pricing: where prices come from and what to do about an unpriced model.