Busabase
Busabase is an open-source (MIT) database and workspace for AI agents — data, docs, skills, and apps in one place. Run it locally, self-host it inside your network, or use Busabase Cloud, and turn age
Receipts for every branch and a guard that acts mid-session, computed from the agent logs on your own machine. Nothing leaves it.
DataJavaScript · SwiftGitHub @vimoxshahOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
See where your AI tokens actually go. Local-first, provider-agnostic analytics for Claude Code, Codex, Cursor, Cline and gateways. Zero dependencies.
Taken from the repository README
Loading the full README. The saved excerpt is shown below.
See where your AI tokens actually go.
Local-first analytics for tokens spent across Claude Code, Codex, OpenCode, Cline,
Cursor, Hermes — or anything you can point it at.
Every screenshot here is the real dashboard on synthetic demo data, which is
why each one carries its own DEMO DATA banner. Run npm run demo and you get this exact
page.
Left: filtering is a date button, a + Filter button and chips for
whatever is on. Picking two models narrows every number on the page, and the insight at the top
rewrites itself. Right: the command palette, grouped, with your recents on an empty query.Read the full README ↗
How deep it goes
| Layer | What's inside |
|---|---|
| Ingestion | 11 adapters (Anthropic, OpenAI/Codex, OpenCode, Hermes, Cline, Cursor, Headroom gateway, git, OpenTelemetry/GenAI (otel), generic CSV/JSONL/SQLite import, demo). Incremental byte-offset resumes, re-read windows for upserted rows, budgeted refresh that stops cleanly mid-corpus |
| Correctness | Cache read/write/input kept as mutually exclusive buckets; vendor convention differences handled; streaming re-reports collapsed to max-of-run; null never coerced to 0; measured gateway cost kept separate from estimates |
| Costing | Versioned price table with per-entry source URLs and fetch dates; service-tier multipliers; long-TTL cache-write tier priced separately; unpriced models surface as null with a configure action — never silent $0 |
| Analytics | 21 views: overview KPIs with a story strip, receipts per branch and pull request, cost per ticket, session anatomy, live, composition, provider/model intelligence, interfaces, hour×weekday heatmap + calendar, peaks, efficiency ratios, cache health, cost with coverage, model what-if, git correlations (labelled), rhythm and focus, period compare, compare branches, searchable data explorer, annotations, per-field data health |
| Integrations | A GitHub Action and a self-hosted GitHub App (your App, your server, our code) that put a receipt comment and a budget check run on every pull request; receipts as git notes that travel with the code; an MCP server so the agent can read its own bill; a FOCUS-shaped export for a FinOps tool; org policy pulled from a team server you run |
| Live mode | Watcher daemon, native Swift menu bar app (live sessions, today's receipts, guard state, provider/source/model breakdowns, capacity meters with reset countdowns & ETAs, forecast with stated confidence, MAD-based anomaly alerts, per-source sparklines, appearance toggle), SwiftBar/xbar plugin |
| Engineering | Zero runtime dependencies · 841 tests · lint invariants (e.g. "no || 0 on a token field") · tsc-clean JSDoc types · CI on macOS/Linux/Windows × Node 22/24 |
Zero runtime dependencies. Nothing leaves your machine. No API keys, no accounts, no telemetry.
# macOS app
brew uninstall --cask tokenflow # if installed via the tap
# otherwise: quit TokenFlow, drag /Applications/TokenFlow.app to Trash
# CLI / npm
npm uninstall -g @vimoxshah/tokenflow # if installed globally
# data (everything local: config, records, digests, state)
rm -rf ~/.tokenflow
# optional extras you may have installed
launchctl unload ~/Library/LaunchAgents/app.tokenflow.digest.plist 2>/dev/null
rm -f ~/Library/LaunchAgents/app.tokenflow.digest.plist
launchctl unload ~/Library/LaunchAgents/app.tokenflow.bar.plist 2>/dev/null
rm -f ~/Library/LaunchAgents/app.tokenflow.bar.plist
Nothing is stored anywhere else. Deleting ~/.tokenflow and the app removes every trace.
Homebrew (macOS) — the one-liner:
brew tap vimoxshah/tap https://github.com/vimoxshah/tokenflow
brew install --cask tokenflow
npm (macOS, Linux, Windows) — CLI + dashboard, no app bundle:
npx @vimoxshah/tokenflow@latest setup
macOS app (manual) — download TokenFlow-*.dmg from the
latest release (each release also
carries tokenflow-dashboard-demo.html, an offline demo dashboard that opens in any browser).
Open the DMG, drag TokenFlow.app to Applications, launch from Launchpad.
The build is unsigned (no Apple Developer account), so macOS blocks the first launch. This is expected and one-time only:
- Open System Settings → Privacy & Security → scroll to Security.
- Click Open Anyway next to the "TokenFlow was blocked" message.
- Confirm Open.
Alternatively right-click the app → Open → Open.
TokenFlow has no Dock icon and no window — it lives in the menu bar as TF. The first launch
opens its panel by itself so you can see where it is, and adds TokenFlow to Login Items so it
comes back after a restart (turn that off any time in System Settings → General → Login
Items). Click Run setup, which detects your installed tools and writes
~/.tokenflow/config.yaml. The watcher refreshes every two minutes after that.
From source (macOS, Linux, Windows — needs Node 22.5+, nothing else):
git clone https://github.com/vimoxshah/tokenflow.git && cd tokenflow
npm run setup # detect Claude Code, Codex, OpenCode, Cursor, Cline…
npm start # ingest what's new, then open the dashboard
No npm run install needed — zero dependencies. If nothing is detected, node bin/tokenflow.js providers tells you what it looked for and where.
Just want a look first? npm run demo generates clearly-labelled synthetic data and opens the
dashboard.
| Question | Where |
|---|---|
| What did this branch or pull request cost? | Receipts — spend per repository and branch, context share, copy as a PR comment |
| What did this ticket cost, across every branch that touched it? | Tickets: cost per Jira/Linear/GitHub key, from branch names and merged PR titles |
| How much AI did I use, and how has that changed? | Overview — the three insights that matter, then KPIs, daily series, trend |
| Input vs output vs cache? | Token composition — four buckets that sum to the total |
| Which provider and model do I rely on? | Provider & model share, growth, per-model efficiency |
| When do I use AI most? | Time patterns — hour/weekday profiles, heatmap, calendar |
| What does it cost? | Cost — estimated from a versioned price table with stated coverage |
| Does usage track shipped work? | Productivity — correlations with git activity, labelled as correlations |
| What changed between two periods? | Compare — any two windows, metric by metric |
| Can I trust these numbers? | Data health — per-field availability, per-adapter coverage |
Overview · Receipts · Tickets · Session anatomy · Live · Token composition · Providers & models ·
Interfaces · Time patterns · Peaks · Efficiency · Cache health · Cost · What-if · Productivity ·
Rhythm · Compare · Compare branches · Data explorer (searchable/sortable/exportable) ·
Annotations · Data health. Twenty-one in all, in a left sidebar grouped by topic (it collapses to
a rail, resizes by dragging, and becomes a drawer below 900 pixels).
Deep-link any of them: #tab=receipts&skin=terminal&mode=light.
Press ⌘K (or Ctrl+K) anywhere in the dashboard for the command palette: jump to a tab, change the range, skin or mode, export, refresh or clear filters without touching the mouse. The first time the live dashboard opens it explains what was found on this machine and what was not, and why.
Every screenshot uses npm run demo data, which the UI labels as synthetic.
tokenflow team serve, with no CI job and no third party in the
path. We host nothing: the receipt is read, posted back to the repository it came from, and
dropped. See github-app.md.tokenflow tickets. Matching is a convention, so a
branch that names no key stays unattributed rather than guessed. See tickets.md.tokenflow export --focus and tokenflow team --focus write this machine's
estimates onto the FinOps FOCUS column names, so they can sit beside a real cloud bill. Still an
estimate at list price, never an invoice. See focus-export.md.tokenflow mcp gives the agent four read-only tools: what this branch has
cost, the caps in force here, recent totals, the monthly budget. The thing spending the money can
finally see the bill. Local stdio, no network. See mcp.md.1.3.1 and 1.3.2 fixed the interface defects that only real mouse and keyboard input could find, including a closed command palette that stayed on the page. See the changelog.
| Adapter | Source | Reports |
|---|---|---|
anthropic | ~/.claude*/projects/**/*.jsonl | per-request input, output, cache read/write, thinking |
openai | ~/.codex/sessions/**/*.jsonl | per-turn fresh/cached input, cache write, output, reasoning |
opencode | opencode.db (XDG data dir) | per-request fresh input, cache read/write, output |
hermes | ~/.hermes/state.db | per-session-per-model tokens, measured cost when recorded |
cline | ~/.cline/data/sessions/** | sessions + model only — this source has no token counts |
cursor | cursor ai-code-tracking db | AI-authored edits per commit |
headroom | ~/.headroom/savings_events.jsonl | measured cost + compression delta from a local gateway (overlay) |
git | any repository | commits, churn — independent work signal |
generic | CSV / TSV / JSON / JSONL / SQLite | anything via a saved field mapping |
mock | — | deterministic demo data, always labelled |
New adapters drop into src/providers/<id>/index.js or $TOKENFLOW_HOME/providers/*.js; new
providers and models appear in every chart automatically. See docs/providers.md.
The parts most token dashboards get wrong:
cache_read, cache_write and output are
mutually exclusive and sum to the total; long-TTL refreshes and reasoning are subsets, never
added again.input_tokens. Anthropic excludes cache; OpenAI includes cached input.
The OpenAI adapter subtracts so nothing counts twice.null, never coerced to 0; sums skip nulls and
report coverage.null cost and are listed for configuration — never
silently $0.Transcripts are append-only, so the store tracks each file's {size, mtime, offset}: unchanged
files are skipped entirely, grown files resume at their byte offset, rewrites are superseded and
compacted. On a real 1.5 GB / 5,110-file corpus: ~15 s first ingest, ~2 s no-op refresh.
refresh --budget 30 stops cleanly on a file boundary and resumes later — big ingests fit inside
CI steps or browser requests.
node bin/tokenflow.js setup # detect tools, write ~/.tokenflow/config.yaml
node bin/tokenflow.js refresh # incremental ingest (--full re-reads everything)
node bin/tokenflow.js status # current numbers, same modules the dashboard calls
node bin/tokenflow.js providers # what was detected, where
node bin/tokenflow.js dashboard # live UI at http://127.0.0.1:7799 (loopback only)
node bin/tokenflow.js watch # auto-refresh every N seconds (default 120)
node bin/tokenflow.js import f.csv # CSV/JSONL/SQLite via saved field mapping
node bin/tokenflow.js export --csv # --all for everything; --html for offline snapshot
node bin/tokenflow.js digest # shareable weekly digest (--format text, --from/--to, --out f.md)
node bin/tokenflow.js week # this week's spend vs last week (--svg/--png card, --json)
node bin/tokenflow.js models-compare # cost/usage efficiency per model — your data
node bin/tokenflow.js budget --set 200 # monthly cap + forecast alerts (fires once per state/month)
node bin/tokenflow.js schedule --install --at "Monday 09:00" # weekly digest via launchd
node bin/tokenflow.js diagnostics # local observability — nothing transmitted
node bin/tokenflow.js team # per-developer team view (needs sync + opt-in names)
node bin/tokenflow.js team serve # self-hosted team server (LAN/Docker), no shared folder needed
node bin/tokenflow.js team check # is that server reachable, and is this token accepted?
node bin/tokenflow.js sync --to <url> --token <t> # push this machine's rollups to a team server
node bin/tokenflow.js receipt --repo . --gh # what each branch / merged PR cost (sees through worktrees)
node bin/tokenflow.js receipt --sessions # where the money goes: concentration, context vs work, marginal cost/turn
node bin/tokenflow.js receipt --csv # one row per branch, every repository
node bin/tokenflow.js hooks install # pre-push git hook: attach a receipt note, never blocks
node bin/tokenflow.js guard --install # Claude Code hook: warn/block a session against caps you declare
node bin/tokenflow.js guard --install --codex # same circuit breaker for Codex CLI (warns only)
node bin/tokenflow.js tickets # cost per ticket key, from branch names and merged PR titles
node bin/tokenflow.js policy show # the caps in force here: personal, then repo, then org ceiling
node bin/tokenflow.js export --focus # FOCUS-shaped CSV for a FinOps tool that already reads it
node bin/tokenflow.js mcp # MCP server on stdio, so the agent can read its own bill
node bin/tokenflow.js pricing diff table.json --apply # merge a candidate price table in
node bin/tokenflow.js doctor # environment, store, adapters, and a data-quality audit
node bin/tokenflow.js up # refresh → rebuild offline HTML → serve + open
npm link # optional: global `tokenflow` command
Every command is documented in docs/cli.md; every config field in docs/configuration.md.
node bin/tokenflow.js menubar --app # builds & launches the native app
A small native Swift app compiled on your machine (no Electron): status item shows spend today or
limit pressure (▲ 82%, ✗ 105%), with a dropdown covering today/week/month, per-provider rows,
per-source and per-model usage, capacity meters with reset countdowns, forecast, anomaly alerts,
and an appearance toggle (system → light → dark, persisted)
(light / dark). Declare caps yourself:
limits:
- id: anthropic-monthly
provider: anthropic
scope: month
metric: tokens # or cost / requests / input / output
cap: 120000000
Quotas exist because you declared them — none are invented. Details:
docs/live-mode.md. SwiftBar users: menubar --swiftbar --out <dir>.
Three skins (Aurora default, Terminal, Editorial) × dark/light, persisted via ui.skin /
ui.mode. Series colours belong to the mode, not the skin, validated for colour-blind separation —
switching themes never changes what a colour means.
export --html produces one self-contained offline file (CSS + analytics + data inline) that opens
from file:// with no server. A full CSV export doubles as a portable dataset:
tokenflow restore <file>.csv --yes rebuilds a store on another machine without the raw vendor logs.
npm test # 841 tests: normalization, adapters, analytics, store, receipts, guard
npm run lint # project invariants (incl. "no || 0 on a token field")
npm run typecheck # tsc over JSDoc types — must be zero errors
npm run validate # self-check: runtime, adapters, store↔cube agreement
npm run design # recompile design tokens into every surface
npm run media # reshoot the README and landing-page screenshots
npm run media drives a real headless browser against a throwaway synthetic store and rewrites
docs/media. Run it whenever the interface changes: for a whole release these images showed a
filter wall and a tab bar that no longer existed, because nothing rebuilt them and nothing
checked. test/media.test.js now fails if an image is referenced but missing, shipped but unused,
or linked with no way to regenerate it. It cannot tell whether a screenshot is current, so look at
what comes out.
Read CONTRIBUTING.md first — it states the five invariants that keep this honest (missing is not zero; measured and estimated never mix; a streamed usage block is a snapshot; tokens are not productivity; nothing leaves the machine).
Easiest contribution: an adapter (src/providers/<id>/index.js) plus a fixture under
test/fixtures/, stating in its header comment what each vendor field means.
Local data → local normalization → local analytics → local dashboard. The dashboard binds to
127.0.0.1. No prompt text, code, or file content is ever stored — adapters read token counts and
discard the rest. No telemetry, no pricing service, no update check.
Every network path there is, in full. Each one is off until you turn it on, and each one goes to an address you chose.
Outbound, only when you opt in:
sync: in config) exchanges daily totals (date, tokens, requests,
est. cost) through a folder you own (iCloud/Dropbox/Syncthing). Never prompts, code or
credentials. Default is OFF; nothing leaves this machine until you set sync.enabled: true.sync.to in config, or tokenflow sync --to <url>) sends those same two
sync files to a server you run with tokenflow team serve, behind a bearer token. Nothing else.tokenflow hooks install) push refs/notes/tokenflow to your own git
remote, alongside the branch you were already pushing. The receipt holds counts and dollars, and
no prompt or code content.tokenflow policy pull, and the cache refresh tokenflow refresh runs)
reads GET <sync.to>/api/policy from your team server. It only reads; it sends no usage.tokenflow team check) asks that same server whether it is healthy.delivery: in config) sends the digest you generate to your own Telegram
chat, email, or webhook. Credentials live only in ~/.tokenflow/config.yaml.map.showMyLocation: true) is one cached IP geolocation of this machine, to
place "you" on the Global activity map. The IP itself is never stored.Inbound, only on a server you run: tokenflow team serve receives the rollups your machines
push, and, when you configure your own GitHub App on it, deliveries at POST /github/webhook
verified by GitHub's signature over the raw body. There is no hosted TokenFlow service to receive
anything: that process is yours, on your machine, and it keeps no copy of a receipt it posts back.
Neither: tokenflow mcp is local stdio, with no socket and no network call. Building a ticket
URL is string work and never contacts your tracker. tokenflow receipt --gh shells out to the
GitHub CLI you already authenticated.
Two more privacy defaults worth knowing:
tokenflow team) shows per-developer usage from the shared folder. A name appears
next to a machine only if its owner set sync.developerName themselves; machines without it stay
anonymous and are excluded from per-person rows.promptAnalytics: in config) is OFF by default; even when enabled, only
one-way prompt hashes and keyword categories are stored. Raw text requires a separate opt-in.Everything lives in ~/.tokenflow/.
SECURITY.md covers the threat model and private vulnerability reporting.
MIT — see LICENSE.
+ Filter