Skip to content

Take upstream changes#1

Open
simoncoles wants to merge 164 commits into
amphora:dockerfrom
Maciek-roboblog:main
Open

Take upstream changes#1
simoncoles wants to merge 164 commits into
amphora:dockerfrom
Maciek-roboblog:main

Conversation

@simoncoles

Copy link
Copy Markdown

No description provided.

Maciek-roboblog and others added 21 commits June 19, 2025 12:13
Add modern Python packaging with uv tool installation support:

- Add pyproject.toml with console script entry points (ccusage-monitor, claude-monitor)

- Update README.md to prioritize uv installation over legacy methods

- Add CLAUDE.md development documentation

- Add comprehensive .gitignore for Python project

Users can now install with: uv tool install claude-usage-monitor

Maintains full backwards compatibility with existing installation methods
Update installation docs to use local directory instead of PyPI:

- Change from 'uv tool install claude-usage-monitor' to 'uv tool install .'

- Add git clone step since package not yet published to PyPI

- Clarify platform-specific uv installation commands

Fixes installation errors for users trying to install from PyPI
feat: add uv package manager support
- Add comprehensive .ruff.toml configuration with essential linting rules
- Set up pre-commit hooks for automated code quality checks
- Create GitHub Actions CI workflow for ruff validation
- Configure VS Code settings for real-time ruff integration
- Format existing codebase to comply with ruff standards
- Update documentation with ruff usage instructions
- Update Python requirement from 3.6+ to 3.7+ (ruff minimum)
- Replace outdated tools (black, flake8) with modern ruff tooling

Resolves #15
feat: integrate ruff for code quality and formatting
Information about CLAUDE_CONFIG_DIR added
Update README.md with CLAUDE_CONFIG_DIR path
@simoncoles simoncoles self-assigned this Jun 20, 2025
coygeek and others added 8 commits June 20, 2025 21:49
Hi there,

I noticed that many popular open-source projects include a star history chart in their README to visualize community growth and engagement. I thought it would be a great addition to this project as well.

This PR adds a dynamic Star History chart to the end of the `README.md`.
Docs: Add Star History chart to README.md
New CLI flag to hide the model distribution bar in the live view. Threaded as a pydantic Settings field through to_namespace and the display controller; both render sites (Model Distribution and Model Usage) honor it.

Closes #161
Two new CLI flags for the live view: --no-header hides the header banner, --no-emoji renders plain output with emoji stripped. Implemented as positive pydantic Settings fields (header/emoji, default on) so pydantic-settings' BooleanOptionalAction generates the --no-* forms; mapped to the renderer through the display controller.

Closes #57
The opus family fallback was $15/$75 (Opus-3 era), so current Opus 4.5+ usage was billed 3x too high, and Haiku 4.5 was billed at the old $0.25 Haiku-3 rate. Family fallbacks now reflect current rates (Opus $5/$25, Haiku $1/$5, Sonnet $3/$15, Fable 5 $10/$50); models priced differently by version (Opus 3/4.0/4.1, Haiku 3/3.5) are pinned as explicit overrides. Rates verified against Anthropic's published pricing.

Closes #182
- settings: recognize the --flag=value form so an explicit --plan=pro is no longer overwritten by a saved last_used.json plan (regression from persisting plan).

- settings: persist the 'auto' theme intent instead of the resolved light/dark value, so background auto-detection keeps running on each launch (the 'light/jasna' fix).

- pricing: price the claude-opus-4-1 / claude-opus-4-0 aliases as legacy ($15/$75) instead of falling through to the current $5/$25 Opus rate.

- cli: include CLAUDE_CONFIG_DIR-derived paths in the no-data diagnostic so the configured location is shown.
One-shot machine-readable usage output for hooks/CI/companions: --once measures usage once, prints a versioned snapshot (schema_version/source/confidence/limits/local/local_history/forecast, all local_estimate), and exits with automation codes (0/10/11/20/30). New output/snapshots.py is the single shared builder (#184 --write-state will reuse it) plus json/text formatters; the limits block mirrors the official statusline rate_limits shape so the trust keystone can fill it later without breaking consumers.

Hardened via a Codex (xhigh) adversarial review: forecast now uses an input+output burn rate matching tokens_remaining (was dimensionally invalid against the cache-inclusive rate), exit codes use the raw unrounded ratio, no-limit reports indeterminate, --custom-limit-tokens is honored, seven_day is no longer mislabeled with the local window sum, and tokenCounts=None no longer crashes.

Closes #126
New --write-state flag writes the same versioned snapshot (the one-shot builder) to a state file companions can poll — default ~/.claude-monitor/state/latest.json, override with --state-file. Writes are atomic (temp file + os.replace) so a reader never sees a partial file, and the parent directory is created. Wired into both the live loop (every refresh) and one-shot mode; a write failure is logged and never breaks monitoring.

Closes #184
Adds --compact for tmux/status-bar use: one line with usage percent,
tokens used/limit, burn rate, reset time, and session cost. Works both
live (updates in place) and one-shot via --once, built from the same
snapshot as --once so the numbers never diverge from the full views.

Also resolve the displayed token limit through a single helper so an
explicit --custom-limit-tokens is honored in the live loop too, not just
one-shot; previously the orchestrator's P90 recalculation masked it.
v4.0.0 feat: usage ops protocol, trust layer, and warehouse
Adds a Claude Code statusline hook (`claude-monitor --statusline`) that reads
the session JSON on stdin, captures the official rate_limits (5h/7d
used_percentage + resets_at) to ~/.claude-monitor/statusline/latest.json, and
prints a one-line status. When a capture is present the snapshot uses the
official percentage and reset as the source of truth (confidence: official) and
the five-hour figure drives the --once exit code; without it every number stays
a labeled local estimate.

Guards the known leak where used_percentage can carry the reset epoch, drops a
window once its reset has passed, tombstones the capture when rate_limits
disappears (plan downgrade), and keeps the hook crash-proof since it runs on
every status refresh.
The --reset-hour flag was accepted, validated, and persisted but never read by
any calculation. Wire it into the daily/monthly aggregator so the usage day
rolls over at the chosen hour (e.g. --reset-hour 4 counts 02:00 toward the
previous day) instead of always at midnight. It intentionally does not move the
rolling 5-hour window, whose reset comes from the session or official data.
When a session block contains a rate-limit message with a reset time, prefer it
over the start-plus-5h estimate for the displayed reset, so the reset matches
what Claude actually told the user. Carried on SessionBlock as
usage_limit_reset_time and emitted as usageLimitResetTime; the snapshot prefers
it for the local five-hour window, while official statusline limits still win.

Also fix the epoch parser: a numeric 'limit reached|<epoch>' timestamp was read
as local wall time and then labeled UTC, shifting the reset by the host offset
on non-UTC machines. Epochs are absolute instants and are now parsed as UTC.
…te data

- A stale official capture (older than the freshness TTL) no longer drives the
  exit status, confidence label, or display as current truth; it falls back to
  the local estimate with the stale flag kept only as a transparency signal.
  Previously only an expired window was guarded, so a stale-but-unreset capture
  at 96% still showed up as official truth.
- An official percentage now drives the exit status even when there is no local
  active block: a 98% official reading reports near_limit instead of being
  masked as 'no active session'.
- Non-finite values (JSON permits NaN/Infinity) in resets_at, captured_at, or
  used_percentage are rejected rather than crashing the reader or rendering as a
  real percentage; the --json output uses allow_nan=False so it can never emit
  invalid JSON to a consumer.
Models routed through Claude Code Router (e.g. GPT or DeepSeek) were falling
through the pricing fallback to the Sonnet rate, inflating reported cost with a
fabricated Claude price. A model that is not recognizably Anthropic now resolves
to an explicit unknown (/usr/bin/zsh) price instead; unknown but clearly-Claude models
still use the family fallback. Also backfills the changelog for the prior
official-limit hardening.
--filter-models anthropic drops entries for non-Claude models (e.g. GPT or
DeepSeek routed through Claude Code Router) at the single load chokepoint, so
they no longer count toward the Claude session's tokens, cost, or limit. It is
threaded through the live, one-shot, P90, and daily/monthly paths and defaults
to 'all' (no change). The predicate matches on claude/anthropic only, so a
foreign name like gpt-4-opus is not mistaken for Claude.

Also fix the daily reset boundary to honor the configured timezone: --reset-hour
is a local-time concept, so the rollover is now computed in the display
timezone rather than raw UTC.
local_history.total_tokens summed the per-block display-utilization value
(input + output only), so cache-heavy sessions were undercounted and disagreed
with local.tokens.total_tokens. Sum the cache-inclusive token counts instead.

Also make the environment-abort test patch through the imported module object
rather than the dotted string: claude_monitor.cli.main is shadowed by the main
function, so the string form resolves to the function (not the module) under
Python 3.9/3.10's mock and raised AttributeError.
pre-commit-uv's uv-created hook environments fail pre-commit's virtualenv health
check on Python patch versions (the runner reports 3.9.25 where 3.9 is expected),
failing the Pre-commit job for an environment reason unrelated to the hooks. Drop
the accelerator so pre-commit uses the standard virtualenv backend; all hooks
still run and pass.
- state file: write to a pid-unique temp so concurrent writers can't clobber it.
- official reader: expire a window at the reset instant (>=, not >), and guard
  capture_statusline against a non-object stdin payload.
- snapshot: emit tokens_used=null (not 0) when there is no active session, since
  utilization is unknown.
- limit reset: take the reset from the most recent limit message (latest
  timestamp), not the largest reset value.
- live loop: fall back to the last known token limit when the monitor reports
  token_limit as an explicit null.
- text protocol: escape control characters so a value with a newline cannot
  split into a second, malformed key=value line.
- one-shot --write-state: surface a failed write (exit 30) instead of silently
  swallowing it; the live loop still ignores transient write errors.
- no-active-session screen now honors --no-header and --no-emoji.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants