Local-first cost analytics for AI coding agents. See where your tokens and money go across Claude Code, Cursor, and more.
brew install siropkin/budi/budi && budi initEverything stays on your machine by default. Optional cloud sync pushes aggregated daily cost metrics to a team dashboard at app.getbudi.dev — prompts, code, and responses never leave your machine.
Cloud Dashboard Screenshots
Overview — team-wide cost visibility
Repos & Tickets — cost breakdown by project, branch, and ticket
Sessions — recent sessions across the team
- Tracks tokens, costs, and usage per message across AI coding agents
- Local proxy (port 9878) sits between your agent and the LLM provider, capturing every request in real time — streaming responses pass through with no visible lag
- Attributes cost to repos, branches, tickets, and custom tags
- Session health — detects context bloat, cache degradation, cost acceleration, and retry loops with actionable, provider-aware tips
- Cloud dashboard at
app.getbudi.dev— team-wide cost visibility across users, repos, models, branches, and tickets (daily granularity, opt-in via~/.config/budi/cloud.toml) - Provider-scoped live cost status line in Claude Code and Cursor (quiet rolling
1d/7d/30d) - One-time import of historical transcripts via
budi import(Claude Code JSONL, Codex Desktop/CLI sessions, Copilot CLI sessions, Cursor Usage API) - ~6 MB Rust binary, minimal footprint
budi targets macOS, Linux (glibc), and Windows 10+. Prebuilt release binaries are published for macOS (Intel + Apple Silicon), Linux (x86_64 + aarch64 glibc), and Windows x86_64. On Windows ARM64, the installer currently uses the x86_64 binary via emulation. Paths follow OS conventions (HOME / USERPROFILE, data under ~/.local/share/budi on Unix and %LOCALAPPDATA%\budi on Windows). Daemon port takeover after upgrade uses lsof/ps/kill on Unix and PowerShell Get-NetTCPConnection plus taskkill on Windows (requires PowerShell, which is default on supported Windows versions).
| Agent | Tier | Status | How |
|---|---|---|---|
| Claude Code | Tier 1 | Supported | Auto-configured by budi init (shell profile env block) |
| Codex CLI | Tier 1 | Supported | Auto-configured by budi init (shell profile env block + Codex Desktop config patch) |
| Cursor | Tier 2 | Supported | Auto-configured by budi init (Cursor settings.json patch) |
| Copilot CLI | Tier 2 | Supported | Auto-configured by budi init (shell profile env block) |
| Gemini CLI | Tier 3 | Deferred | Different API format; not supported in v1 proxy |
Tier 1 agents use simple env vars with high confidence. Tier 2 agents work but have onboarding caveats (GUI settings, proprietary env vars). See ADR-0082 for the full compatibility matrix.
All agents also support one-time historical import via budi import (Claude Code JSONL transcripts, Codex Desktop/CLI sessions, Copilot CLI sessions, Cursor Usage API).
- budi — The core Rust daemon and CLI tool (you are here)
- budi-cloud — Cloud dashboard and ingest API for team-wide cost visibility
- budi-cursor — VS Code/Cursor extension: a provider-scoped Cursor-only status bar (no sidebar) that mirrors the Claude Code statusline
See CONTRIBUTING.md for local setup, quality checks, and PR workflow.
Architecture and module boundaries are documented in SOUL.md.
Architecture decision records live in docs/adr/. The 8.x local-developer-first product contract (persona priority, local/cloud boundary, classification principles, statusline contract, explicit 8.2 / 9.0 deferrals) is ADR-0088.
Quick validation: cargo fmt --all && cargo clippy --workspace --all-targets --locked -- -D warnings && cargo test --workspace --locked
To report a bug or request a feature, open a GitHub issue using the repository templates so maintainers get reproducible details quickly.
Use Homebrew if you have it. Otherwise use the shell script (macOS/Linux) or PowerShell script (Windows). Build from source only if you want to contribute.
Homebrew (macOS / Linux): requires Homebrew
brew install siropkin/budi/budi && budi initShell script (macOS / Linux): requires curl and tar (glibc-based systems only; Alpine/musl users should build from source)
curl -fsSL https://raw.githubusercontent.com/siropkin/budi/main/scripts/install-standalone.sh | bashWindows (PowerShell): requires PowerShell 5.1+
irm https://raw.githubusercontent.com/siropkin/budi/main/scripts/install-standalone.ps1 | iexWindows notes: binaries install to %LOCALAPPDATA%\budi\bin. Stopping or upgrading the daemon uses taskkill (or PowerShell) instead of Unix pkill. On startup, budi-daemon asks PowerShell for listeners on its port and terminates another budi-daemon if present. PATH is updated in the user environment — restart your terminal after install.
From source: requires Rust toolchain
git clone https://github.com/siropkin/budi.git && cd budi && ./scripts/install.shWindows source build (PowerShell):
git clone https://github.com/siropkin/budi.git
cd budi
cargo build --release --locked
$BinDir = Join-Path $env:LOCALAPPDATA "budi\bin"
New-Item -ItemType Directory -Path $BinDir -Force | Out-Null
Copy-Item .\target\release\budi.exe $BinDir -Force
Copy-Item .\target\release\budi-daemon.exe $BinDir -Force
& (Join-Path $BinDir "budi.exe") initOr paste this into your AI coding agent:
Install budi from https://github.com/siropkin/budi following the install instructions in the README
budi init behavior by install method:
| Method | Runs budi init automatically? |
|---|---|
Homebrew (brew install ...) |
No — run budi init manually |
Standalone shell script (curl ... | bash) |
Yes |
Standalone PowerShell script (irm ... | iex) |
Yes |
From source (./scripts/install.sh) |
Yes |
If you install with Homebrew, run budi init right after brew install.
One install on PATH. Do not mix Homebrew with ~/.local/bin (macOS/Linux) or with %LOCALAPPDATA%\budi\bin (Windows): you can end up with different budi and budi-daemon versions and confusing restarts. Keep a single install directory ahead of others on PATH (or remove duplicates). budi init warns if it detects multiple binaries.
budi init starts the daemon (port 7878) and proxy (port 9878), and prompts you to choose which agents to track (Claude Code, Cursor, Codex CLI, Copilot CLI) and which integrations to install (statusline, extension). Agent choices are stored in ~/.config/budi/agents.toml. In non-interactive mode it uses safe defaults (all agents enabled). You can also choose integrations explicitly with flags like --with, --without, and --integrations all|none|auto.
During init, budi automatically applies proxy routing for selected agents:
- CLI agents (Claude/Codex/Copilot): injects a managed env-var block into your shell profile (
~/.zshrc,~/.bashrc, or~/.bash_profile) - Cursor: patches Cursor settings.json with the proxy base URL
- Codex Desktop: patches
~/.codex/config.tomlwithopenai_base_url
budi launch <agent> still works as an explicit fallback. For a one-off bypass, run BUDI_BYPASS=1 budi launch <agent>.
Important: After budi init or budi enable, restart your terminal so the shell-profile proxy env vars take effect for CLI agents (Claude Code, Codex, Copilot). Already-running sessions are NOT going through the proxy until the shell is restarted. For immediate proxy routing without restart, use budi launch <agent>. budi doctor detects when proxy env vars are configured but not active in the current shell. Customize ports in the repo-local config.toml under <budi-home>/repos/<repo-id>/config.toml (run budi doctor inside the repo to see the exact path).
To install a specific version, set the VERSION environment variable: VERSION=v7.1.0 curl -fsSL ... | bash (or $env:VERSION="v7.1.0" on PowerShell).
Run budi doctor to verify everything is set up correctly.
Use this sequence if you want the fastest "did setup really work?" path:
- Install and initialize
- Homebrew:
brew install siropkin/budi/budithenbudi init - Standalone installers and
./scripts/install.shalready runbudi initfor you budi initprompts for agents and integrations (defaults are safe), starts the daemon + proxy, and installs a platform-native autostart service (launchd on macOS, systemd on Linux, Task Scheduler on Windows)
- Homebrew:
- Restart your terminal (CLI agents only: Claude Code, Codex, Copilot CLI)
- Proxy env vars are written into your shell profile; already-running shells won't route through the proxy until they are reloaded
- For immediate routing without a restart, use
budi launch <agent>
- Send your first prompt
- Open your agent as usual (
claude,codex,cursor,gh copilot) and send a prompt — proxy is auto-configured - One-off bypass if needed:
BUDI_BYPASS=1 budi launch <agent>
- Open your agent as usual (
- Verify end-to-end with
budi doctor- Checks daemon, proxy, autostart, agent configuration, database, and attribution (sessions / branches / activities)
- The top of the report says "All checks passed." when first-run setup is healthy — and adds a friendly nudge if no activity has been recorded yet
- See today's cost with
budi status- Quick snapshot: daemon/proxy state, today's cost, and active agents
- Import historical data (optional)
- Run
budi importto backfill from Claude Code JSONL transcripts, Codex Desktop/CLI sessions, Copilot CLI sessions, and Cursor Usage API
- Run
If budi is "not found" or behavior looks inconsistent after an update, verify which binary is being executed:
- macOS/Linux:
command -v budiwhich -a budi
- Windows (PowerShell):
Get-Command budi -All
Keep only one install source first on PATH (Homebrew or standalone path), not both.
Budi adds a live cost display to Claude Code (optional in budi init). The default is intentionally quiet, stable, and scoped to the current agent surface — the Claude Code statusline shows Claude Code usage only (ADR-0088 §4):
budi · $1.24 1d · $8.50 7d · $32.10 30d
Rolling 1d / 7d / 30d windows are the primary signal. They tell you what you spent in the last 24 hours, the last 7 days, and the last 30 days — not calendar-today or calendar-month. budi stats keeps calendar semantics if you want those.
budi statusline --format json emits the shared provider-scoped status contract (see docs/statusline-contract.md) that the Cursor extension and cloud dashboard reuse:
budi statusline --format json # auto-scoped to claude_code for --format claude
budi statusline --format json --provider cursor # Cursor surface reuses the same shape
budi statusline --format json --provider codex # any other supported providerPower users can pick a different preset by creating ~/.config/budi/statusline.toml:
# Default quiet preset (same as no file).
slots = ["1d", "7d", "30d"]
# `coach` — show the active session's cost and health:
# budi · $1.24 session · session healthy
# preset = "coach"
# `full` — session cost + health + today's rolling 1d total:
# preset = "full"Available slots: 1d, 7d, 30d, session, branch, project, provider, health. The legacy today / week / month slot names still work — they resolve to the same rolling 1d / 7d / 30d values so existing configs keep rendering.
Budi includes a Cursor/VS Code extension that shows Cursor-only spend in a single status bar item. It can be installed during budi init and later via budi integrations install --with cursor-extension.
As of v1.1.0 the extension is intentionally statusline-only (ADR-0088 §7, #232) — no sidebar, no session list, no vitals/tips panel. The status bar renders the shared provider-scoped status contract filtered to provider=cursor and mirrors the Claude Code statusline byte-for-byte: 🟢 budi · $X 1d · $Y 7d · $Z 30d. A leading dot glyph reports health (🟢 active, 🟡 reachable but quiet, 🔴 daemon unreachable, ⚪ first run / not installed yet). Click the status bar item to open the cloud dashboard — session list when a Cursor session is active, dashboard root otherwise — matching the Claude Code click-through.
The extension also works as a first-run onboarding entry point: if you discover budi through the VS Code Marketplace before installing the CLI, the extension shows a welcome view with a pre-filled install command and hands you off to budi init in an integrated terminal. The hand-off is tracked by local-only integer counters in ~/.local/share/budi/cursor-onboarding.json (no remote telemetry, ADR-0083 privacy limits preserved) and budi doctor prints a one-line summary of those counters so install-funnel health is visible locally.
Manual install (if auto-install was skipped or you want to rebuild):
git clone https://github.com/siropkin/budi-cursor.git && cd budi-cursor
npm ci && npm run build
npx vsce package --no-dependencies -o cursor-budi.vsix
cursor --install-extension cursor-budi.vsix --forceThen reload Cursor: Cmd+Shift+P → Developer: Reload Window.
budi update # downloads latest release, migrates DB, restarts daemon
budi update --version 7.1.0 # update to a specific versionWorks for all installation methods — automatically detects Homebrew and runs brew upgrade when appropriate. Update refreshes integrations you previously enabled (stored in ~/.config/budi/integrations.toml). Agent enablement is stored separately in ~/.config/budi/agents.toml.
Manage integrations anytime (especially if you skipped some during first init):
budi integrations list
budi integrations install --with cursor-extensionRestart Claude Code and Cursor after updating to pick up any changes.
Cloud sync is disabled by default. To enable it, sign up at app.getbudi.dev, copy your API key from Settings, and create ~/.config/budi/cloud.toml:
[cloud]
enabled = true
api_key = "budi_your_key_here"The daemon picks up the config on next restart (budi init). Only pre-aggregated daily rollups are synced — prompts, code, and responses never leave your machine. See the Privacy section for full details.
Environment variable overrides: BUDI_CLOUD_ENABLED=true, BUDI_CLOUD_API_KEY=budi_..., BUDI_CLOUD_ENDPOINT=https://....
Launch and onboarding:
budi init # start daemon, configure integrations
budi launch claude # launch Claude Code through the proxy (zero config)
budi launch codex # launch Codex CLI through the proxy
budi launch copilot # launch Copilot CLI through the proxy
budi launch cursor # print Cursor proxy setup instructions (GUI only)
budi import # one-time import of historical transcriptsMonitoring and analytics:
budi status # quick overview: daemon, proxy, today's cost
budi stats # usage summary with cost breakdown
budi stats --models # model usage breakdown
budi stats --projects # repos ranked by cost
budi stats --branches # branches ranked by cost
budi stats --branch <name> # cost for a specific branch
budi stats --tickets # tickets ranked by cost (sourced from ticket_id tag)
budi stats --ticket <id> # cost for a specific ticket, with per-branch breakdown
budi stats --activities # activities ranked by cost (bugfix, refactor, …)
budi stats --activity <name> # cost for a specific activity, with per-branch breakdown
budi stats --files # files ranked by cost (repo-relative paths only — ADR-0083)
budi stats --file <path> # cost for a specific file, with per-branch + per-ticket breakdown
budi stats --provider codex # filter stats to a single provider
budi stats --tag ticket_id # cost per ticket value (raw tag view)
budi stats --tag ticket_prefix # cost per team prefix
budi sessions # list recent sessions with cost and health
budi sessions --ticket <id> # sessions tagged with a ticket id
budi sessions --activity <name> # sessions tagged with an activity (bugfix, refactor, …)
budi sessions <id> # session detail: cost, models, health, tags, work outcome
budi health # session health vitals for most recent session
budi health --session <id> # health vitals for a specific sessionDiagnostics and maintenance:
budi doctor # check health: daemon, proxy, database, config
budi doctor --deep # run full SQLite integrity_check (slower)
budi cloud status # cloud sync readiness + last-synced-at + queued records
budi cloud sync # push queued local rollups/sessions to the cloud now
budi autostart status # check daemon autostart service
budi autostart install # install the autostart service
budi autostart uninstall # remove the autostart service
budi import --force # re-ingest all data from scratch (use after upgrades)
budi repair # repair schema drift + run migration checks
budi update # check for updates (auto-detects Homebrew)
budi update --version <name> # update to a specific version
budi integrations list # show what is installed vs available
budi integrations install ... # install integrations later
budi uninstall # remove status line, config, and data
budi uninstall --keep-data # uninstall but keep analytics databaseAll data commands support --period today|week|month|all and --format json.
Assistant messages are tagged with core attribution keys: provider, model, ticket_id, ticket_prefix, ticket_source, activity, activity_source, activity_confidence, file_path, file_path_source, file_path_confidence, tool_outcome, tool_outcome_source, tool_outcome_confidence, composer_mode, permission_mode, duration, tool, tool_use_id, user_email, platform, machine, user, git_user.
Every first-class attribution dimension (ticket, activity, file, tool outcome) carries a sibling *_source tag that explains how the value was derived (branch / branch_numeric for tickets, rule for activity, tool_arg / cwd_relative for file paths, jsonl_tool_result / heuristic_retry for tool outcomes) and, where applicable, an *_confidence tag (high / medium / low). File-path attribution is strictly repo-relative: absolute paths, paths outside the repo root, file:// and other URL schemes, and .. escapes are dropped at extraction time so nothing outside the repo can land in the database (see ADR-0083).
Conditional tags:
cost_confidenceis added whencost_centsis present.speedis added only for non-standardspeed modes.
Identity tag semantics:
platform: OS platform (macos,linux,windows)machine: host/machine nameuser: local OS usernamegit_user: Git identity (user.name/user.emailfallback)
repo_id and git_branch are stored as canonical message/session fields (not tags), so repo/branch analytics stay single-source and do not double-count.
Add custom tags in ~/.config/budi/tags.toml:
[[rules]]
key = "team"
value = "platform"
match_repo = "github.com/org/repo"
[[rules]]
key = "team"
value = "backend"
match_repo = "*Backend*"Budi monitors four vitals for every active session and turns them into plain-language tips.
The scoring is intentionally conservative:
- New sessions start green — the default is always positive. Vitals only turn yellow or red when there is clear evidence of a problem.
- It measures the current working stretch, so a
/compactresets context-based checks. - It looks at the active model stretch for cache reuse, so model switches do not poison the whole session.
- Cost acceleration uses per-user-turn costs when prompt boundaries are available, and falls back to per-reply costs otherwise.
- When
budi healthruns without--session, it picks the latest session by assistant activity first, then falls back to session timestamps. - It prefers concrete next steps over internal jargon.
Tips are provider-aware: Claude Code suggestions mention /compact or /clear, Cursor suggestions point you toward a fresh composer session, and unknown providers receive neutral advice. Different providers may intentionally get different recommendations for the same health issue.
| Vital | What it detects | Yellow | Red |
|---|---|---|---|
| Context Growth | Context size is growing enough to add noise | 3x+ growth with meaningful absolute growth | 6x+ growth with large absolute context size |
| Cache Reuse | Recent cache reuse is low for the active model stretch | Below 60% recent reuse | Below 35% recent reuse |
| Cost Acceleration | Later turns/replies cost much more than earlier ones | 2x+ growth and meaningful cost per unit | 4x+ growth and high cost per unit |
| Retry Loops | Agent is stuck in a failing tool loop (disabled since 8.0 — hook-event source removed; will be re-enabled on top of R1.5 tool-outcome signals) | One suspicious retry loop | Repeated or severe retry loops |
Health state appears in the statusline's opt-in coach / full presets (see above; the default statusline is quiet and cost-only) and on the session detail page in the cloud dashboard. Yellow means "pay attention soon"; red means "intervene now or start fresh." The Cursor extension is statusline-only as of v1.1.0 and does not render per-session health.
Budi is local-first. All data stays on your machine by default (~/.local/share/budi/ on Unix, %LOCALAPPDATA%\budi on Windows). The proxy forwards your requests to the upstream LLM provider and back, but budi only stores metadata locally: timestamps, token counts, model names, and costs. Prompts, code, and AI responses pass through the proxy and are never written to disk or retained by budi.
Cloud sync (optional, disabled by default) pushes pre-aggregated daily rollups and session summaries to a team dashboard at app.getbudi.dev. Only numeric metrics cross the wire: token counts, costs, model names, hashed repo IDs, branch names, and ticket IDs. Prompts, code, responses, file paths, email addresses, raw payloads, and tag values are structurally excluded from the sync payload — there is no "full upload" mode.
Cloud sync details:
- Transport: HTTPS only — the daemon refuses to sync over plain HTTP
- Direction: Push-only — the cloud never initiates connections to your machine; there is no webhook, pull, or remote command channel
- Granularity: Daily aggregates; no per-message, per-hour, or real-time streaming views
- Retention: 90 days in the cloud alpha
- Team model: Manager/member roles for small teams (1–20 developers)
- Auth: API key auth for daemon sync; Supabase Auth (GitHub, Google, magic link) for the web dashboard. No SSO/SAML in v1
See ADR-0083 for the complete privacy contract.
A lightweight Rust daemon (port 7878) manages a single SQLite database. The daemon runs a proxy server on port 9878 that transparently forwards agent traffic to upstream providers (Anthropic, OpenAI) while capturing metadata. Streaming (SSE) responses pass through chunk-by-chunk with no buffering; token metadata is extracted from the byte stream without modifying it. Proxy traffic is attributed to repos, branches, and tickets via X-Budi-Repo/X-Budi-Branch/X-Budi-Cwd headers or automatic git resolution, with cost computed from provider pricing tables. Historical data from Claude Code JSONL transcripts and Cursor Usage API can be backfilled via budi import. The CLI is a thin HTTP client — all queries go through the daemon.
How budi compares
| budi | ccusage | Claude /cost |
|
|---|---|---|---|
| Multi-agent support | Yes (Claude Code, Codex CLI, Cursor, Copilot CLI) | Claude Code only | Claude Code only |
| Real-time cost via proxy | Yes | No | No |
| Cost history | Per-message + daily | Per-session | Current session |
| Cloud dashboard | Yes (app.getbudi.dev) | No | No |
| Status line + session health | Yes (with actionable tips) | No | No |
| Per-repo breakdown | Yes | No | No |
| Cost attribution (branch/ticket) | Yes | No | No |
| Privacy | Local-first (optional cloud sync for aggregated metrics only) | Local | Built-in |
| Setup | budi init |
npx ccusage |
Built-in |
| Built with | Rust | TypeScript | — |
Architecture
┌──────────┐ HTTP ┌──────────────┐ SQLite ┌──────────┐
│ budi CLI │ ──────────▶ │ budi-daemon │ ───────────▶ │ budi.db │
└──────────┘ │ (port 7878) │ └──────────┘
│ │ ▲
│ - analytics │ Pipeline │
│ - import │ ──────────────────┘
│ (on demand) │ Extract → Normalize
└──────────────┘ → Enrich → Load
│
┌──────────────┐
┌──────────┐ proxy │ budi proxy │ upstream
│ AI Agent │ ──────────▶ │ (port 9878) │ ──────────▶ Anthropic / OpenAI
│ (CC/CX) │ localhost │ transparent │ API calls
└──────────┘ │ pass-thru │
└──────────────┘
Historical import (budi import):
JSONL transcripts (Claude Code) ──┐
JSONL sessions (Codex) ───────────┤
JSONL sessions (Copilot CLI) ─────┼──▶ Pipeline → SQLite
Usage API (Cursor) ───────────────┘
The daemon is the single source of truth — the CLI never opens the database directly. The proxy is the sole live data source: every LLM request flows through it, capturing tokens, cost, and attribution in real time. Historical data from Claude Code JSONL transcripts, Codex Desktop/CLI sessions, Copilot CLI sessions, and Cursor Usage API can be imported via budi import for one-time backfill.
Data model — nine tables, seven data entities + two supporting:
| Table | Role |
|---|---|
| messages | Single cost entity — all token/cost data lives here (one row per API call) |
| sessions | Lifecycle context (start/end, duration, mode) without mixing cost concerns |
| proxy_events | Append-only log of proxied LLM API requests (provider, model, tokens, duration, status, repo, branch, ticket, cost) |
| tags | Flexible key-value pairs per message (repo, ticket, activity, user, etc.) |
| sync_state | Tracks incremental ingestion progress per file for progressive sync, plus cloud sync watermarks |
| message_rollups_hourly | Derived hourly aggregates (provider/model/repo/branch/role) for low-latency analytics reads |
| message_rollups_daily | Derived daily aggregates for summary/filter scans |
messages remains the source of truth; rollup tables are derived caches maintained incrementally during ingest/update/delete.
Privacy & Retention
budi is local-first, but you can now enforce tighter storage controls for raw payloads and session metadata.
Privacy mode (BUDI_PRIVACY_MODE):
| Value | Behavior |
|---|---|
full (default) |
Store raw values as-is |
hash |
Hash sensitive fields (for example user_email, cwd, and workspace paths) before storage |
omit |
Do not store sensitive raw/session fields |
Retention controls:
| Env var | Default | Scope |
|---|---|---|
BUDI_RETENTION_RAW_DAYS |
30 |
sessions.raw_json |
BUDI_RETENTION_SESSION_METADATA_DAYS |
90 |
sessions.user_email, sessions.workspace_root |
Use off to disable a retention window for a category.
Retention cleanup runs automatically after sync and queued realtime ingestion processing.
At-rest protection (SQLCipher strategy):
- Current default uses bundled SQLite (WAL) for broad compatibility and easy installs.
- If you need encrypted-at-rest local DBs (shared/managed machines), use one of these strategies:
- build budi against SQLCipher-enabled SQLite (
libsqlite3-sysSQLCipher build), - or place the budi data directory on an encrypted volume (FileVault, LUKS, BitLocker).
- build budi against SQLCipher-enabled SQLite (
- SQLCipher integration is feasible but has tradeoffs (key management UX, packaging complexity, migration path from existing plaintext DBs), so default remains plain SQLite for now.
Hooks (removed in 8.0)
Hook-based ingestion (budi hook) and the hook_events table have been removed. The proxy (port 9878) is now the sole live data source.
Cost confidence levels
Every message carries a cost_confidence tag that indicates how the cost was derived:
| Level | Source | Accuracy |
|---|---|---|
proxy_estimated |
Proxy real-time capture | Estimated from response body / SSE stream |
exact |
Cursor Usage API / Claude Code JSONL tokens | Exact tokens, calculated cost |
estimated |
JSONL tokens x model pricing | ~92-96% accurate (missing thinking tokens) |
Messages with exact confidence show exact cost in the dashboard. Estimated costs are prefixed with ~.
OpenTelemetry (removed in 8.0)
OTEL ingestion endpoints (POST /v1/logs, POST /v1/metrics) and the otel_events table have been removed. The proxy (port 9878) captures real-time cost data directly.
Daemon API
The daemon runs on http://127.0.0.1:7878 and exposes a REST API.
Privileged routes are loopback-only (127.0.0.1 / ::1): all /admin/* endpoints plus POST /sync, POST /sync/all, and POST /sync/reset.
System:
| Method | Endpoint | Description |
|---|---|---|
| GET | /health |
Health check |
| POST | /sync |
Sync recent data (last 30 days, loopback-only) |
| POST | /sync/all |
Load full transcript history (loopback-only) |
| POST | /sync/reset |
Wipe sync state + full re-sync (loopback-only) |
| GET | /sync/status |
Syncing flag + last_synced |
| GET | /health/integrations |
Statusline/extension status + DB stats |
| GET | /health/check-update |
Check for updates via GitHub |
Analytics:
| Method | Endpoint | Description |
|---|---|---|
| GET | /analytics/summary |
Cost and token totals |
| GET | /analytics/filter-options |
Filter values for providers/models/projects/branches |
| GET | /analytics/messages |
Message list (paginated, searchable) |
| GET | /analytics/messages/{message_uuid}/detail |
Full detail for a specific message |
| GET | /analytics/projects |
Repos ranked by usage |
| GET | /analytics/branches |
Cost per git branch |
| GET | /analytics/branches/{branch} |
Cost for a specific branch |
| GET | /analytics/tickets |
Cost per ticket (first-class dimension, #304) |
| GET | /analytics/tickets/{ticket_id} |
Cost for a specific ticket, with per-branch breakdown |
| GET | /analytics/activities |
Cost per activity bucket (bugfix, refactor, …) (#305) |
| GET | /analytics/activities/{name} |
Cost for a specific activity, with per-branch breakdown |
| GET | /analytics/files |
Cost per repo-relative file (#292) |
| GET | /analytics/files/{*path} |
Cost for a specific file, with per-branch + per-ticket breakdown |
| GET | /analytics/cost |
Cost breakdown |
| GET | /analytics/models |
Model usage breakdown |
| GET | /analytics/providers |
Per-provider breakdown |
| GET | /analytics/activity |
Token activity over time |
| GET | /analytics/tags |
Cost breakdown by tag |
| GET | /analytics/statusline |
Status line data |
| GET | /analytics/cache-efficiency |
Cache hit rates and savings |
| GET | /analytics/session-cost-curve |
Cost per message by session length |
| GET | /analytics/cost-confidence |
Breakdown by cost confidence level |
| GET | /analytics/subagent-cost |
Subagent vs main agent cost |
| GET | /analytics/sessions |
Session list (paginated, searchable) |
| GET | /analytics/sessions/{id} |
Session metadata and aggregate stats |
| GET | /analytics/sessions/{id}/messages |
Messages for a specific session |
| GET | /analytics/sessions/{id}/curve |
Session input token growth curve |
| GET | /analytics/sessions/{id}/tags |
Tags for a specific session |
| GET | /analytics/session-health |
Session health vitals and tips |
| GET | /analytics/session-audit |
Session attribution/linking audit stats |
| GET | /admin/providers |
Registered providers (loopback-only) |
| GET | /admin/schema |
Database schema version (loopback-only) |
| POST | /admin/migrate |
Run database migration (loopback-only) |
| POST | /admin/repair |
Repair schema drift + run migration (loopback-only) |
| POST | /admin/integrations/install |
Install/update integrations from daemon (loopback-only) |
Most endpoints accept ?since=<ISO>&until=<ISO> for date filtering.
No data after setup:
- Run
budi statusto check daemon, proxy, and today's cost - Verify auto-proxy config with
budi doctor(shell profile + Cursor/Codex settings) - If
budi doctorreports proxy env vars not set in current shell, restart your terminal or usebudi launch <agent>for immediate routing - Send a prompt and check
budi statsfor non-zero usage - For historical data:
budi import(one-time backfill from Claude Code JSONL, Codex sessions, Copilot CLI sessions, Cursor Usage API)
Daemon won't start:
- Check if port 7878 is in use:
lsof -i :7878 - Kill stale processes:
pkill -f "budi-daemon serve" - Restart:
budi init
Windows equivalent:
- Check listeners:
Get-NetTCPConnection -LocalPort 7878 -State Listen - Kill stale daemon:
taskkill /IM budi-daemon.exe /F - Restart:
budi init
Daemon doesn't survive reboots:
Run budi autostart status — if it shows "not installed", run budi autostart install to install the platform-native service (launchd on macOS, systemd on Linux, Task Scheduler on Windows). budi init also installs the autostart service.
Proxy not reachable (agent gets connection refused on port 9878):
- Run
budi doctorto check proxy health - Check if port 9878 is in use by another process:
lsof -i :9878 - Restart with
budi init
Status line not showing:
- Restart Claude Code after
budi init - Check:
budi statuslineshould output cost data
Cursor extension status bar shows offline (red dot) or stays quiet (yellow):
- Run
budi doctorto verify daemon + proxy health. - In Cursor, run Budi: Refresh Status.
- If needed, reload Cursor window (
Developer: Reload Window) afterbudi initor daemon URL changes. - Confirm
Override OpenAI Base URLis set tohttp://localhost:9878(Cursor Settings → Models) so Cursor traffic routes through the budi proxy.
budi uninstall # stops daemon, removes autostart service, status line, config, and databudi uninstall removes the autostart service, status line, config, and data but not the binaries themselves. Remove binaries separately:
# Homebrew:
brew uninstall budi
# Shell script (macOS / Linux):
rm ~/.local/bin/budi ~/.local/bin/budi-daemon
# or use the full uninstall script:
curl -fsSL https://raw.githubusercontent.com/siropkin/budi/main/scripts/uninstall.sh | bash
# From source (cargo install):
cargo uninstall budi budi-daemon
# Windows (PowerShell):
irm https://raw.githubusercontent.com/siropkin/budi/main/scripts/uninstall-standalone.ps1 | iexOptions: --keep-data to preserve the analytics database and config, --yes to skip confirmation.
budi init returns 0 on success, 2 on partial success (init completed with warnings), 1 on hard error.



