Skip to main content

Real-time budget monitor dashboard for Claude Code token usage

Project description

BudMon — Budget Monitor for Claude Code

Real-time desktop dashboard that monitors your Claude Code token usage, quota utilization, burn rate, and costs.

BudMon Dashboard

Why BudMon?

Claude Code users on the Max plan have a token budget that resets every 5 hours and every 7 days. Exceeding the budget means being rate-limited or blocked. The problem: Claude Code shows no real-time feedback on how fast you are consuming your budget.

BudMon fills this gap. It captures the rate-limit headers from every API response and visualizes them as a live dashboard. You can see at a glance:

  • How much of your 5h and 7d quota is used
  • How fast you are burning through it
  • When the quota resets
  • Whether you will run out before the reset
  • How much you are spending in dollars

BudMon runs as a standalone window alongside Claude Code. It requires no API keys, no network access, and no external services. All data is read locally from files that Claude Code writes during operation.

Features

  • 5h / 7d Quota Bars — progress bars with configurable warning (default 75%) and alarm (default 90%) thresholds
  • Burn Rate — consumption rate in %/hour (5h) or %/day (7d), color-coded
  • Expiry Estimate — predicted time when the quota runs out, with date for 7d
  • Reserve — time difference between predicted expiry and next reset (positive = safe, negative = will run out)
  • Countdown Ring — circular timer showing either time to reset or time to expiry (whichever comes first)
  • Last Request / Total Requests — token breakdown per turn and cumulative (input, output, cache create, cache read)
  • Cost Display — dollar cost per request and cumulative, based on model-specific token prices
  • Cache Ratio Sparkline — historical graph of cache hit ratio with average
  • Multi-language — German and English, switchable at runtime, auto-detects system language
  • Model Presets — Opus, Sonnet, Haiku token prices, or custom
  • Dark Theme — terminal-inspired dark color scheme, consistent across all UI elements
  • HiDPI / 4K Support — automatic DPI scaling on Windows, Linux, and macOS
  • Window Position Memory — remembers its last position, reopens there (with screen bounds check)
  • Configurable — all thresholds, prices, language, and refresh rate via INI file

Supported Platforms

Platform Status Notes
Linux (X11) Full support Primary development platform. Tested on Ubuntu 24.04.
Linux (Wayland) Should work tkinter runs under XWayland. Screenshot tools may differ.
macOS Should work Retina scaling handled natively by tk.
Windows Should work DPI awareness via ctypes/shcore. Wrapper is .cmd instead of shell alias.

Requirements

  • Python 3.10+ with tkinter
  • Claude Code (CLI version, installed via npm)
  • Node.js (comes with Claude Code)

Installing tkinter

tkinter is included with most Python installations. If missing:

OS Command
Ubuntu / Debian sudo apt install python3-tk
Fedora sudo dnf install python3-tkinter
Arch sudo pacman -S tk
macOS (Homebrew) brew install python-tk
Windows Reinstall Python with "tcl/tk" option checked

Installation

From PyPI (recommended)

pip install budmon

From source

git clone https://github.com/weilhalt/budmon.git
cd budmon
pip install .

Development install

git clone https://github.com/weilhalt/budmon.git
cd budmon
pip install -e .

Setup

BudMon needs a small interceptor to capture rate-limit data from Claude Code's API responses. Run the setup once after installation:

budmon --setup

This does three things:

  1. Installs the interceptor (~/.claude/budmon-interceptor.mjs) — a read-only Node.js fetch wrapper that captures response headers and token usage. It never modifies outgoing requests.

  2. Creates the claude-budmon command:

    • Linux/macOS: shell alias in .bashrc/.zshrc + wrapper in ~/.local/bin/
    • Windows: .cmd wrapper in a PATH directory
  3. Creates a desktop entry (Linux only) so BudMon appears in your application menu.

If you already have an interceptor

If you are already using cache-fix-preload.mjs or a similar community interceptor that writes ~/.claude/usage-limits.json, BudMon will detect it automatically. No additional setup needed — just run budmon.

Usage

Step 1: Start Claude Code with the interceptor

claude-budmon

This is identical to running claude, but with the interceptor loaded. Use it exactly as you would use claude — all arguments are passed through.

Step 2: Start the dashboard

In a second terminal (or from your application menu):

budmon

The dashboard opens and starts polling for data every second. On first start without data, it will offer to run the setup automatically.

Day-to-day workflow

  1. Always start Claude Code via claude-budmon instead of claude
  2. Start budmon whenever you want to monitor your budget
  3. BudMon runs independently — you can start and stop it at any time

What each display shows

Quota Bars (5h and 7d)

Two horizontal progress bars showing your current quota utilization as a percentage. Threshold markers at the configurable warn and alarm levels.

  • Green — below warning threshold (default <75%)
  • Yellow — between warning and alarm (default 75-90%)
  • Red — above alarm threshold (default >90%)

Reset

The time when your quota window resets, with a countdown. For 7d, includes the date (e.g. "Fri. 04.04. 13:00").

Expiry

Estimated time when your quota will run out at the current burn rate. Shown in cyan (normal), yellow (warning), or red (alarm).

Reserve

The difference between expiry and reset. Positive means you have time to spare. Negative means you will hit the limit before the reset.

  • +2 h 30 min — safe, 2.5 hours of headroom
  • -45 min — will run out 45 minutes before reset

Burn Rate

Your consumption speed. For 5h: percent per hour. For 7d: percent per day. Displayed in white text.

Countdown Ring

A circular timer positioned over the 5h quota bar. Shows either:

  • RESET (green) — counting down to quota reset
  • EXPIRY (yellow/red) — counting down to quota exhaustion (if earlier than reset)

Last Request / Total Requests

Two columns showing token breakdown:

  • Requests — number of API turns
  • Since — when the session or tracking started
  • input — input tokens (user messages, system prompts)
  • output — output tokens (assistant responses)
  • cache_c — cache creation tokens (first time a prompt is cached)
  • cache_r — cache read tokens (subsequent uses of cached prompts)
  • Cost — dollar amount based on model prices

Cache Ratio Sparkline

A line graph showing the historical cache hit ratio. Higher is better (and cheaper).

  • The current ratio is shown as a large percentage
  • The average is shown next to it
  • A dashed line marks the 50% threshold
  • The dot at the end of the line is color-coded (green/yellow/red)

CLI Options

budmon                  Start the dashboard
budmon --setup          Install the Claude Code interceptor
budmon --uninstall      Remove the interceptor and aliases
budmon --statusline     Output for Claude Code status line
budmon --statusline on  Activate status line in Claude Code
budmon --statusline off Deactivate status line
budmon --version        Show version number
budmon --help           Show usage information

Status Line

BudMon can display a compact status line at the bottom of Claude Code, showing quota usage, burn rate, and costs — using the same data and calculations as the GUI dashboard.

Activate

budmon --statusline on

This writes a statusLine entry to ~/.claude/settings.json. Restart Claude Code to apply.

Deactivate

budmon --statusline off

Configure

The status line elements, their order, and the maximum width are configurable in ~/.claude/budmon.ini:

[statusline]
# Elements shown left to right. Those that don't fit are dropped.
elements = cwd, model_info, 5h_bar, 7d_bar, countdown_5h, reserve

# Maximum character width
max_width = 80

Available elements:

Key Example Description
cwd ~/.DEV/.BUDMON Working directory
model_info [Opus 4.6 (1M context)] Active model from Claude Code
5h_bar 5h ████░░░░ 47% 5h quota bar with percentage
7d_bar 7d ██░░░░░░ 23% 7d quota bar with percentage
countdown_5h ↓2h14m Time until 5h reset
countdown_7d ↓3d12h Time until 7d reset
cost $1.42 Session cost in USD
burn_5h ⚡18%/h 5h burn rate per hour
burn_7d ⚡42%/d 7d burn rate per day
reserve +1h12m Time margin before quota reset
cache ⊞72% Average cache hit ratio
tokens_in →125k Cumulative input tokens
tokens_out ←42k Cumulative output tokens
requests #28 Total request count
model opus Active model from config

Colors are used sparingly: yellow at the warning threshold (default 75%), red at the alarm threshold (default 90%). All other text is neutral to blend with any Claude Code /color setting.

Configuration

All settings are stored in ~/.claude/budmon.ini. This file is created automatically on first run with commented defaults. You can edit it:

  • Via the dashboard: Settings > INI
  • Or manually with any text editor

Config file structure

[general]
# Language: "auto" (detect from system), "de", "en"
language = auto

# Dashboard refresh interval in milliseconds
refresh_ms = 1000

[model]
# Model determines token prices: opus, sonnet, haiku, custom
model = opus

[prices]
# Only used when model = custom. Uncomment to activate.
# Prices per 1M tokens in USD.
#
# price_input = 15.0
# price_output = 75.0
# price_cache_read = 1.5
# price_cache_create = 18.75

[thresholds]
# Quota warning/alarm (percent)
quota_warn_pct = 75.0
quota_alarm_pct = 90.0

# Cache ratio warning/alarm (0.0 - 1.0)
cache_warn_ratio = 0.50
cache_alarm_ratio = 0.20

# Burn rate safe/warning (percent per hour)
burn_safe_pct_h = 15.0
burn_warn_pct_h = 25.0

[window]
# Window position (managed automatically)
geometry =

Model presets

Model Input Output Cache Read Cache Create
Opus $15.00 $75.00 $1.50 $18.75
Sonnet $3.00 $15.00 $0.30 $3.75
Haiku $0.80 $4.00 $0.08 $1.00

Prices per 1M tokens in USD. Select via Settings > Model or in the INI file. For custom prices, set model = custom and uncomment the values in [prices].

Menu

Logs

  • Session Log — opens the current session's per-turn token log
  • History Log — opens the persistent history across all sessions
  • Folder — opens the log directory in the file manager

Settings

  • Language — switch between German and English (rebuilds UI)
  • Model — select Opus, Sonnet, Haiku, or Custom (updates prices immediately)
  • INI — open the configuration file in the system text editor

Help

  • User Guide — opens the built-in help file (in the current language)
  • About — version, author, license, homepage, runtime info

How it works

BudMon consists of two independent parts:

1. Interceptor (budmon-interceptor.mjs) — headers only

A Node.js module loaded via NODE_OPTIONS="--import ..." when starting Claude Code. It hooks into the global fetch() function and:

  • Captures rate-limit headers from every /v1/messages API response (e.g. anthropic-ratelimit-unified-5h-utilization)
  • Writes headers to a local JSON file — never sends data anywhere

The interceptor is strictly header-only (since v1.1.0): it returns the original Response object unmodified. It never accesses, wraps, or transforms the response body or stream.

2. Transcript reader

Claude Code writes a JSONL transcript file for each session at ~/.claude/projects/<project-hash>/<session-id>.jsonl. BudMon reads the token usage data (message.usage) from these files:

  • Per-turn token counts (input, output, cache create, cache read)
  • Cumulative totals (summed incrementally)
  • Session start time and turn count

This is completely non-invasive — BudMon reads files that Claude Code writes anyway, without any interception or modification.

3. Dashboard (budmon)

A Python/tkinter desktop application that:

  • Combines header data (quota) with transcript data (tokens)
  • Calculates burn rate, expiry time, and reserve
  • Renders all data as a dark-themed GUI with progress bars, sparklines, and a countdown ring
  • Falls back gracefully if either source is unavailable

Data files

All data is stored in ~/.claude/:

File Written by Content
usage-limits.json Interceptor Rate-limit headers (quota percentages, reset timestamps)
projects/<hash>/<id>.jsonl Claude Code Transcript with per-turn token usage (message.usage)
budmon.ini BudMon Configuration

Privacy

BudMon captures only technical metadata from Claude Code API responses:

  • Rate-limit headers (quota percentages, reset timestamps)
  • Token counts (input, output, cache read, cache create)
  • Timestamps of API calls

BudMon does not capture:

  • Message content (prompts, responses, tool calls)
  • API keys or authentication tokens
  • Personal information
  • File contents or code

All data stays local in ~/.claude/. BudMon has no network access — it never connects to any server, sends no telemetry, no analytics, no crash reports. The interceptor operates entirely within the Claude Code Node.js process and writes only to local files.

The interceptor source code is included in the package (budmon/interceptor.mjs) and can be audited at any time.

Security

The interceptor is header-only (since v1.1.0). It hooks into globalThis.fetch to read rate-limit headers, but:

  • It never accesses the response body or stream
  • It never modifies outgoing requests (no payload changes, no header injection)
  • It never blocks or delays requests or responses
  • It returns the original Response object — no wrapping, no cloning
  • It fails open — any error in the interceptor is silently caught, ensuring Claude Code continues to work normally

Token usage is read from Claude Code's own transcript files, which Claude Code writes independently. BudMon never interferes with Claude Code's data processing.

The interceptor is loaded via Node.js NODE_OPTIONS="--import ...", a standard mechanism. It only runs when you explicitly start Claude Code via claude-budmon.

Compatibility

BudMon reads rate-limit headers from the Anthropic API, which follow a stable documented format (anthropic-ratelimit-unified-*). Token usage is read from Claude Code's own transcript JSONL files (message.usage).

When Claude Code updates: The interceptor (headers) should continue to work as long as Anthropic does not change their API header format. The transcript reader depends on Claude Code's internal JSONL format — if this changes, token details may be unavailable while quota bars continue to work.

  1. Check if ~/.claude/usage-limits.json is still being written (headers)
  2. Check if transcript JSONL files exist in ~/.claude/projects/
  3. Try budmon --uninstall followed by budmon --setup to reinstall
  4. File an issue at the project repository

When Anthropic changes quota windows: The 5h and 7d windows are read from the API headers, not hardcoded. If Anthropic changes the window sizes, BudMon will adapt automatically.

Troubleshooting

Status "WAIT", all values "--", footer shows "Waiting for data..."

This is the normal startup state. BudMon is waiting for Claude Code to deliver data. This is not an error if BudMon was started before Claude Code.

If the state persists after Claude Code is running:

  1. Was budmon --setup run? Check: does ~/.claude/budmon-interceptor.mjs exist? If not: run budmon --setup.

  2. Was Claude Code started via claude-budmon? Only claude-budmon loads the interceptor. A plain claude does not write data for BudMon.

  3. Was at least one message sent? The interceptor writes on the first API response. Before the first turn, the data file does not exist yet.

  4. Does the data file exist? Check: ls -la ~/.claude/usage-limits.json If it exists but is old: Claude Code was likely started without the interceptor. Restart via claude-budmon.

  5. Had data before but not anymore? The Claude Code session was ended. Start a new session via claude-budmon.

Token details show "--" but quota bars work

Quota bars come from the interceptor (rate-limit headers). Token details come from Claude Code's transcript JSONL files. If the transcript cannot be found (e.g. the project directory name convention changed), token details are unavailable while quota monitoring continues to work.

Dashboard shows quota bars but token details are "--"

This is normal for a brief moment. Rate-limit headers are written immediately when the API responds, but token counts are written after the streaming response completes. There is a short window where quota bars work but token details have not arrived yet.

If it persists: Claude Code must have been started via claude-budmon. A regular claude session does not load the interceptor.

Burn rate / expiry / reserve show "--"

Burn rate requires two things:

  • The quota percentage must be above ~0.01% (no calculation if nothing was consumed)
  • The reset timestamp must be present in the API headers

If reset is shown but burn rate is not: the quota utilization is too low to calculate a meaningful rate. This resolves itself after more usage.

Window opens at wrong position

  • Delete the geometry line in ~/.claude/budmon.ini to reset to center
  • Or edit it via Settings > INI

Setup says "Compatible interceptor found"

  • You already have a working interceptor (e.g. cache-fix-preload.mjs)
  • No additional setup needed — just run budmon

Uninstall

budmon --uninstall
pip uninstall budmon

budmon --uninstall removes:

  • ~/.claude/budmon-interceptor.mjs
  • The claude-budmon alias from .bashrc/.zshrc
  • The wrapper script in ~/.local/bin/
  • The .desktop file (Linux)

Data files in ~/.claude/ are not removed.

Project structure

budmon/
  __init__.py         Package + version
  __main__.py         Entry point for python -m budmon
  cli.py              CLI argument handling (--setup, --statusline, etc.)
  config.py           INI-based configuration singleton (section-aware)
  dashboard.py        Main tkinter GUI class
  data.py             Data loading, calculations, formatting
  i18n.py             Internationalization (JSON language files)
  interceptor.mjs     Node.js fetch interceptor (installed by --setup)
  models.py           Constants, dataclasses, color functions
  platform.py         HiDPI detection, file viewer
  setup.py            Setup/uninstall logic + status line activation
  statusline.py       Compact ANSI output for Claude Code status line (15 elements)
  transcript.py       Reads token data from Claude Code transcript JSONL
  widgets.py          Canvas drawing, UI builder functions
  budmon.default.ini  Default configuration template
  lang/
    de.json           German strings
    en.json           English strings
  help/
    help_de.md        German user guide
    help_en.md        English user guide
  icons/
    budmon.svg        Application icon (Lucide "activity", MIT)
    budmon-*.png      Pre-rendered icon sizes (16-256px)

Contributing

Contributions are welcome. Please:

  1. Fork the repository
  2. Create a feature branch
  3. Run pytest before submitting
  4. Open a pull request with a clear description

Code style: Python 3.10+, type hints, no external dependencies (stdlib only).

Credits

  • Icon: Lucide "activity" icon (MIT License — compatible with GPL-3.0, included with permission)
  • Interceptor approach inspired by community work on claude-code#42052

License

GPL-3.0 — see LICENSE

Copyright (c) 2026 weilhalt

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

budmon-1.1.0.tar.gz (85.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

budmon-1.1.0-py3-none-any.whl (73.4 kB view details)

Uploaded Python 3

File details

Details for the file budmon-1.1.0.tar.gz.

File metadata

  • Download URL: budmon-1.1.0.tar.gz
  • Upload date:
  • Size: 85.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for budmon-1.1.0.tar.gz
Algorithm Hash digest
SHA256 740d7e0f2979af7d6f048b613ab34f69a3e2631928125f18f6bb29ec728231a7
MD5 b5a9703dc3e90e482d4a3bb1c2695124
BLAKE2b-256 bf01388b4b7d71bb9116f7a66ee445d87da58db212b20d19c3c6acc8b35bfa74

See more details on using hashes here.

File details

Details for the file budmon-1.1.0-py3-none-any.whl.

File metadata

  • Download URL: budmon-1.1.0-py3-none-any.whl
  • Upload date:
  • Size: 73.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for budmon-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3db8b3bc619dafb0577eb4f07d0364a8e89967d7333b46a662152e2b7e73c206
MD5 c6f7df1cf8661f422723d41c2adb839f
BLAKE2b-256 c59439de4b428528ea89a5150fb5067f8b0f561d139a70ba6993b451e54db3d1

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page