github Maciek-roboblog/Claude-Code-Usage-Monitor v4.0.0
Release v4.0.0

4 hours ago

Bug Fixes

  • Model distribution shows all families: ModelUsageBar now renders every model family — Sonnet, Opus, Haiku, and an "Other" bucket for anything else — instead of only Sonnet/Opus. Haiku and other models no longer vanish from the usage bar or skew the displayed percentages. (#124, #164)
  • Plan is now saved and restored: the selected --plan is persisted in last_used.json and reloaded on the next run; an explicit --plan on the command line still takes priority. (#162)
  • Saved theme no longer overwritten: an explicitly chosen light/dark/classic theme is preserved across runs instead of being silently replaced by background auto-detection. (#102, #200)
  • Clear message on unsupported Python: running on Python older than 3.9 now prints a clear "Python 3.9+ is required" message (with a uv install hint) instead of failing cryptically; the version check is now actually wired into startup and uses the documented 3.9 minimum. (#172)
  • Helpful "no data" diagnostic: when no Claude data directory is found, the monitor now lists the exact paths it searched and how to fix it, instead of a single terse line / blank screen. (#110)
  • CLAUDE_CONFIG_DIR is honored: when set, usage data under $CLAUDE_CONFIG_DIR/projects is discovered (comma-separated directories supported) and checked before the standard locations; path discovery also deduplicates repeated directories. (#116)
  • Up-to-date, version-specific model pricing: token costs now use current Anthropic rates — Opus 4.5+ at $5/$25 (previously billed at the legacy $15/$75, a 3x overcharge), Haiku 4.5 at $1/$5, and Fable 5 at $10/$50 — while older models (Opus 3/4.0/4.1, Haiku 3/3.5) keep their original rates. (#182)
  • --reset-hour is now actually applied: the flag was accepted and persisted but never used in any calculation. It now sets the daily rollover boundary in the daily/monthly table views, so a usage day runs from reset_hour to reset_hour (e.g. --reset-hour 4 counts 02:00 toward the previous day) instead of midnight to midnight. It deliberately does not shift the rolling 5-hour window, whose reset comes from the session/official data. (#95, #96, #106)
  • Reset time prefers what Claude reported: when a session block contains a rate-limit message with a reset time, that time is shown as the reset instead of the start-plus-5h estimate, so the displayed reset matches what Claude actually told you. Official statusline limits still take precedence when available. (#114, #106)
  • Epoch reset timestamps parsed in UTC: a numeric reset timestamp from a limit reached|<epoch> message was parsed as local wall time and then mislabeled as UTC, shifting the shown reset by the host's offset on non-UTC machines (e.g. two hours off in Central Europe). Epochs are now interpreted as the absolute UTC instant they are. (#106, #220)
  • Windows and local timezone detection now use IANA zones: Windows auto-detection now uses tzlocal and refuses to return raw tzutil labels such as Eastern Standard Time as if they were valid pytz zones; the accepted --timezone local alias now resolves before display code runs. Added regression coverage for Istanbul reset display so reset times do not drift by an extra hour. (#188, #98, #121, #220)
  • Non-Anthropic models are no longer priced as Claude: a model routed through Claude Code Router (e.g. a GPT or DeepSeek model) was silently billed at the Sonnet rate, inflating reported cost. Models that are not recognizably Anthropic now report as unpriced ($0) instead of a fabricated Claude cost; unknown but clearly-Claude models still use the family fallback. (#217, #199)
  • Official limits hardened against stale and malformed captures: a statusline capture older than the freshness window no longer drives the displayed reset, status, or confidence: official label (it falls back to the local estimate, flagged stale); an official percentage drives the exit code even with no local session; and non-finite values (NaN/Infinity) in a capture are rejected instead of crashing the reader or emitting invalid JSON. (#119, #108)
  • Rich TUI now uses official-aware limit overlays: the interactive live view and rich --once output now route token usage through the same snapshot used by compact/state/export surfaces, so fresh statusline limits can drive the displayed five-hour percentage with an explicit official label instead of showing a conflicting local-estimate bar.
  • Time-to-reset alignment and Windows glyph fallback: progress rows now pad by terminal display width using wcwidth, so clock emoji no longer shift the "Time to Reset" bar. Startup forces UTF-8 output where possible and enables an ASCII fallback for non-UTF-8 Windows streams. (#144, #160)

Features

  • --hide-model-distribution: new flag to hide the model distribution bar in the live view. (#161)
  • --no-header / --no-emoji: hide the header banner, or render the live view without emoji (plain output). (#57)
  • --once --output {rich,json,text}: one-shot, machine-readable usage snapshot for hooks/CI/companions instead of parsing the live TUI. Emits a versioned schema (schema_version, source, confidence, limits, local, local_history, forecast) with every number labeled local_estimate, plus automation exit codes (0 ok, 10 near limit, 11 limit hit, 20 indeterminate, 30 no data). Official account/weekly limits are shaped in but deferred until the statusline reader lands. (#126)
  • --write-state: continuously write the same versioned snapshot to a state file (default ~/.claude-monitor/state/latest.json, override with --state-file) that status bars, tray apps, and dashboards can poll. Writes are atomic (temp file + replace) so a reader never sees a partial file; reuses the one-shot builder. (#184)
  • --compact: single-line output for tmux/status bars — usage percent, tokens used/limit, burn rate, reset time, and session cost on one line. Works both live (updates in place) and one-shot with --once. Built from the same snapshot as --once, so the numbers never diverge from the full views. (#65, #17, #111)
  • --set-terminal-title: opt-in terminal title updates from the canonical snapshot, with a validated --title-format template (pct, plan, used, limit, cost, reset) so live mode and --once use the same values as state/export surfaces. (#142)
  • Pace, official weekly, and forecast labels in snapshot outputs: snapshots now include a source-labeled pace indicator based on the active five-hour reset, local history is explicitly labeled as history, and forecast displays use Today/Tomorrow/date context with an estimated tag. --compact adds one pace=... token and only renders 7d when the official seven_day statusline block is present. Forecasts now stop instead of predicting beyond a hit limit. (#216, #183, #128)
  • --data-paths multi-source substrate: the reader, live mode, table views, and one-shot snapshot path now accept multiple Claude data directories without collapsing to the first path. Entries are deduplicated across directories, tagged with source.kind and account path, and split into separate 5-hour blocks per source so multiple profiles/accounts do not merge into one limit window. WSL Claude data paths are discovered additively when available. (#196, #92, #127, #94)
  • --warehouse persistent usage store: opt-in versioned JSON usage warehouse with atomic writes, retention pruning, per source/account/project/model/day records, and daily dimension queries. The default stays off; --warehouse-file and --warehouse-retention-days control location and retention. Daily/monthly tables also keep --date-format and --abbreviate-tokens, with sparklines available only behind --sparklines. (#145, #175, #8, #43, #120)
  • Warehouse reports and exports: --view entries|sessions|burn-rate --output json|csv now exports warehouse-backed reports with source/provenance fields, valid CSV/JSON, session counts, P50/P90/P95 metrics, sessions ended by detected limits, burn-rate rows, and plan recommendations explicitly labeled as estimates. (#8, #120, #80, #43)
  • Team plan label and experimental usage API: --plan team is accepted as an unverified estimate label with guidance to prefer official statusline data or --plan custom, and --api adds an opt-in experimental Anthropic OAuth usage reader with TTL cache and Retry-After backoff. Experimental API limits are labeled confidence: experimental and never override fresh official statusline limits. (#195, #202, #193, #157)
  • Related Tools and adapter boundary: README now shows the Awesome Claude Code badge, documents external companion tools that should consume --write-state / --once --output json, and codifies that provider adapters must use separate source.kind values instead of auto-merging non-Claude data into the Claude 5-hour subscription window. Cursor and Claude Desktop are documented as out of scope unless they expose a local usage/limit signal. (#219, #109, #177, #146, #198, #178, #176, #133, #166, #24, #25)
  • --filter-models anthropic: count only Claude models, excluding non-Anthropic ones (e.g. GPT or DeepSeek routed through Claude Code Router) from the usage, cost, and limit math so they no longer pollute the Claude session reading. Applies consistently to the live view, one-shot/state output, and the daily/monthly tables; defaults to all (no change). (#113)
  • Official limits via the statusline (--statusline): a Claude Code statusline hook that reads the session JSON on stdin, captures the official rate_limits (5-hour and 7-day used_percentage + resets_at, Pro/Max on Claude Code 2.1.80+), and prints a one-line status. Add "statusLine": {"type": "command", "command": "claude-monitor --statusline"} to Claude Code's settings. When a capture is present, the monitor uses the official percentage and reset as the source of truth (confidence: official) and labels it as such; the 5-hour figure also drives the --once exit code. Without it, every number stays a clearly-labeled local estimate. Captures older than 10 minutes are flagged stale. The known leak where used_percentage can carry the reset epoch is guarded against. (#119, #108, #104, #97, #150, #152)

Don't miss a new Claude-Code-Usage-Monitor release

NewReleases is sending notifications on new releases.