Burnfolio collects local AI coding-agent usage data and summarizes token burn by date, CLI type, and model.
The hosted app runs on Cloudflare Workers at https://burnfolio.ai, with D1 for
storage and Cloudflare Email Service for optional magic-link sign-in.
Current collectors:
- Claude Code:
~/.config/claude/projectsand~/.claude/projects - Codex:
${CODEX_HOME:-~/.codex}/sessionsandarchived_sessions - OpenCode:
${OPENCODE_DATA_DIR:-~/.local/share/opencode} - Pi:
${PI_AGENT_DIR:-~/.pi/agent/sessions} - Amp:
${AMP_DATA_DIR:-~/.local/share/amp} - Droid:
${DROID_SESSIONS_DIR:-~/.factory/sessions} - Codebuff:
${CODEBUFF_DATA_DIR}or~/.config/manicode* - Hermes Agent:
${HERMES_HOME:-~/.hermes}/state.db - Goose: local
sessions.dbroots orGOOSE_PATH_ROOT - Kilo:
${KILO_DATA_DIR:-~/.local/share/kilo}/kilo.db - Kimi:
${KIMI_DATA_DIR:-~/.kimi} - OpenClaw:
~/.openclaw,~/.clawdbot,~/.moltbot,~/.moldbot - Qwen Code:
${QWEN_DATA_DIR:-~/.qwen} - GitHub Copilot CLI:
~/.copilot/otel/*.jsonlorCOPILOT_OTEL_FILE_EXPORTER_PATH - Gemini CLI:
${GEMINI_DATA_DIR:-~/.gemini/tmp}
curl -fsSL https://raw.githubusercontent.com/nbitslabs/burnfolio/main/install.sh | bashBurnfolio publishes pre-built pyro binaries for every release tag on GitHub:
- Linux:
amd64,arm64 - macOS:
amd64,arm64 - Windows:
amd64,arm64
Release assets are available at
https://github.com/nbitslabs/burnfolio/releases.
The installer downloads the latest release binary, installs it to
/usr/local/bin or ~/.local/bin, writes ~/.pyro/config.json, and can
optionally run an immediate sync.
If you already have a Burnfolio machine token, you can either pass it with
--profile and --machine or let the interactive installer prompt for it.
For a new machine token from the dashboard, copy the generated one-liner:
curl -fsSL https://raw.githubusercontent.com/nbitslabs/burnfolio/main/install.sh | bash -s -- --profile <account-number-or-username> --machine <machine-token>The dashboard keeps a copy-ready install command on each machine row. For older machines where Burnfolio only has the token hash, the row action creates a replacement token and copies a complete install command.
The installer asks whether to set up automatic sync with cron: none, hourly,
or daily. For non-interactive setup, pass the schedule explicitly:
curl -fsSL https://raw.githubusercontent.com/nbitslabs/burnfolio/main/install.sh | bash -s -- \
--profile <account-number-or-username> \
--machine <machine-token> \
--schedule dailyUseful installer flags:
--profile <account-or-username>
--machine <machine-token>
--schedule <none|hourly|daily>
--providers amp,claude,codebuff,codex,copilot,droid,gemini,goose,hermes,kilo,kimi,openclaw,opencode,pi,qwen
--openrouter-key <management-key>
--openrouter-profile <account-or-org>
--openrouter-since 2020-01-01
--server https://burnfolio.ai
--install-dir ~/.local/bin
--version v0.1.2Uninstall disables Burnfolio cron sync and marks the local install as
uninstalled in ~/.pyro/config.json. It leaves the .pyro folder and saved
machine config in place so you can reinstall or inspect status later:
curl -fsSL https://raw.githubusercontent.com/nbitslabs/burnfolio/main/uninstall.sh | bashUseful uninstaller flags:
--profile <account-or-username>
--install-dir ~/.local/bin
--remove-binary
--keep-cron
--yesShow local install state:
pyro statusRun a local summary and automatically sync when ~/.pyro/config.json has an
active profile and machine token:
pyroUseful CLI flags:
pyro --providers claude,codex,opencode,pi
pyro --json
pyro --no-sync
pyro --home /path/to/home
pyro --profile bf_ab12cd34 --machine bfm_...
pyro --profile bf_ab12cd34 --machine bfm_... --openrouter-key sk-or-v1-... --openrouter-profile bf_ab12cd34
pyro install --profile bf_ab12cd34 --machine bfm_...
pyro uninstallBuild from source for local development:
make build
./bin/pyro
go install ./cmd/pyro
pyroThe table output is grouped by date, CLI, and model. JSON output includes provider totals plus the same date/CLI/model segments for the future server API.
When --profile and --machine are provided, the CLI uploads all local history to
Burnfolio as one idempotent total per day. Re-running the same command
replaces each machine/day row instead of double-counting it.
Burnfolio can import OpenRouter account usage from an OpenRouter management key. Management keys are not inference keys, but they can read account analytics.
Local import keeps the OpenRouter key on your machine and uploads only daily token totals:
pyro install \
--profile <account-or-username> \
--machine <machine-token> \
--openrouter-key <openrouter-management-key> \
--openrouter-profile <account-or-org>
pyroYou can also connect a management key in the Burnfolio dashboard for your personal profile or from an organization management page. Server-side connections are encrypted and fetched hourly.
OpenRouter data is stored separately from local machine inference data and is deduplicated by target profile, OpenRouter key fingerprint, and day. If the same key is synced from multiple machines or from both Pyro and the dashboard, the same daily rows are updated instead of added twice.
Create an anonymous account at https://burnfolio.ai. Signup returns an account
number, account key, machine token, and a ready-to-run sync command. Save the
account key: it is the private credential used with the public account number to
sign back in before adding an email or username.
Run the generated install + sync command locally:
curl -fsSL https://raw.githubusercontent.com/nbitslabs/burnfolio/main/install.sh | bash -s -- --profile <account-number-or-username> --machine <machine-token>From the dashboard you can claim a username, attach an optional email for magic
links, create personal or organization machine tokens, create the nbitslabs
org, and add users as members or admins. Public user and org pages expose the
same burn graph plus iframe and SVG embed snippets.
The smoke test creates throwaway timestamped accounts on the configured server and verifies anonymous login, CLI sync, dedupe, multi-machine aggregation, org rollup, and embed output.
scripts/smoke-live.shBy default it uses https://burnfolio.ai and the pi collector to keep the
test lightweight. Override with BURNFOLIO_SERVER or
BURNFOLIO_SMOKE_PROVIDERS when needed.
For a real account acceptance pass, set the profile and machine token generated by the dashboard:
BURNFOLIO_PROFILE=<account-or-username> \
BURNFOLIO_MACHINE=<machine-token> \
scripts/verify-account.shOptional checks can verify a fresh second machine and an org profile:
BURNFOLIO_PROFILE=<account-or-username> \
BURNFOLIO_MACHINE=<machine-token> \
BURNFOLIO_SECOND_MACHINE=<second-machine-token> \
BURNFOLIO_EXPECT_SECOND_INCREASE=1 \
BURNFOLIO_ORG=nbitslabs \
BURNFOLIO_EXPECT_ORG_MATCH=1 \
scripts/verify-account.shProfiles expose both iframe and SVG embeds:
<script src="https://burnfolio.ai/embed/<profile>/script.js"></script>
<img src="https://burnfolio.ai/embed/<profile>.svg" alt="Burnfolio token burn graph">See examples/embed.html for a complete third-party page template.
The Cloudflare Worker keeps its UI code in worker/index.js and its stylesheet
in worker/styles.css. Tailwind processes and minifies the stylesheet, then the
build step writes the deployable Worker to dist/worker/index.js.
npm install
npm run build:uimake deploy runs the UI build before wrangler deploy, so production deploys
use the generated Worker bundle.