Skip to content

siropkin/budi

Repository files navigation

budi

CI Release License GitHub stars

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 init

Everything 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.

budi CLI demo

Cloud Dashboard Screenshots

Overview — team-wide cost visibility

budi dashboard — cost overview

Repos & Tickets — cost breakdown by project, branch, and ticket

budi repos

Sessions — recent sessions across the team

budi sessions

What it does

  • 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

Platforms

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).

Supported agents

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).

Ecosystem

  • 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

Contributing

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.

Install

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 init

Shell 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 | bash

Windows (PowerShell): requires PowerShell 5.1+

irm https://raw.githubusercontent.com/siropkin/budi/main/scripts/install-standalone.ps1 | iex

Windows 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.sh

Windows 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") init

Or 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.toml with openai_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.

First run checklist (5 minutes)

Use this sequence if you want the fastest "did setup really work?" path:

  1. Install and initialize
    • Homebrew: brew install siropkin/budi/budi then budi init
    • Standalone installers and ./scripts/install.sh already run budi init for you
    • budi init prompts 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)
  2. 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>
  3. 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>
  4. 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
  5. See today's cost with budi status
    • Quick snapshot: daemon/proxy state, today's cost, and active agents
  6. Import historical data (optional)
    • Run budi import to backfill from Claude Code JSONL transcripts, Codex Desktop/CLI sessions, Copilot CLI sessions, and Cursor Usage API

PATH and duplicate binary checks

If budi is "not found" or behavior looks inconsistent after an update, verify which binary is being executed:

  • macOS/Linux:
    • command -v budi
    • which -a budi
  • Windows (PowerShell):
    • Get-Command budi -All

Keep only one install source first on PATH (Homebrew or standalone path), not both.

Status line

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.

Shared status contract

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 provider

Advanced variants

Power 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.

Cursor extension

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 --force

Then reload Cursor: Cmd+Shift+PDeveloper: Reload Window.

Update

budi update                      # downloads latest release, migrates DB, restarts daemon
budi update --version 7.1.0     # update to a specific version

Works 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.

Integrations

Manage integrations anytime (especially if you skipped some during first init):

budi integrations list
budi integrations install --with cursor-extension

Restart Claude Code and Cursor after updating to pick up any changes.

Cloud sync (optional)

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://....

CLI

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 transcripts

Monitoring 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 session

Diagnostics 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 database

All data commands support --period today|week|month|all and --format json.

Tags & cost attribution

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_confidence is added when cost_cents is present.
  • speed is added only for non-standard speed modes.

Identity tag semantics:

  • platform: OS platform (macos, linux, windows)
  • machine: host/machine name
  • user: local OS username
  • git_user: Git identity (user.name/user.email fallback)

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*"

Session health

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 /compact resets 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 health runs 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.

Privacy

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.

How it works

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.

Details

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-sys SQLCipher build),
    • or place the budi data directory on an encrypted volume (FileVault, LUKS, BitLocker).
  • 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.

Troubleshooting

No data after setup:

  1. Run budi status to check daemon, proxy, and today's cost
  2. Verify auto-proxy config with budi doctor (shell profile + Cursor/Codex settings)
  3. If budi doctor reports proxy env vars not set in current shell, restart your terminal or use budi launch <agent> for immediate routing
  4. Send a prompt and check budi stats for non-zero usage
  5. For historical data: budi import (one-time backfill from Claude Code JSONL, Codex sessions, Copilot CLI sessions, Cursor Usage API)

Daemon won't start:

  1. Check if port 7878 is in use: lsof -i :7878
  2. Kill stale processes: pkill -f "budi-daemon serve"
  3. Restart: budi init

Windows equivalent:

  1. Check listeners: Get-NetTCPConnection -LocalPort 7878 -State Listen
  2. Kill stale daemon: taskkill /IM budi-daemon.exe /F
  3. 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):

  1. Run budi doctor to check proxy health
  2. Check if port 9878 is in use by another process: lsof -i :9878
  3. Restart with budi init

Status line not showing:

  1. Restart Claude Code after budi init
  2. Check: budi statusline should output cost data

Cursor extension status bar shows offline (red dot) or stays quiet (yellow):

  1. Run budi doctor to verify daemon + proxy health.
  2. In Cursor, run Budi: Refresh Status.
  3. If needed, reload Cursor window (Developer: Reload Window) after budi init or daemon URL changes.
  4. Confirm Override OpenAI Base URL is set to http://localhost:9878 (Cursor Settings → Models) so Cursor traffic routes through the budi proxy.

Uninstall

budi uninstall          # stops daemon, removes autostart service, status line, config, and data

budi 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 | iex

Options: --keep-data to preserve the analytics database and config, --yes to skip confirmation.

Exit codes

budi init returns 0 on success, 2 on partial success (init completed with warnings), 1 on hard error.

License

MIT

About

Local-first cost analytics for AI coding agents. See where your tokens and money go across Claude Code, Cursor, and more.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages