Skip to content

Repository files navigation

ccmetr — two Claude quotas in your menu bar

macOS 14+ Swift 6 MIT

Install

brew trust fixcik/tap          # once, Homebrew asks this for third-party taps
brew install fixcik/tap/ccmetr

Or grab the build from Releases, unzip and drag ccmetr.app to /Applications. Going that route the build is ad-hoc signed, so Gatekeeper blocks the first launch — right-click → OpenOpen, or:

xattr -dr com.apple.quarantine /Applications/ccmetr.app

On first launch macOS asks whether ccmetr may read the Claude token from your login keychain. You can say no — see below. Updates arrive through Sparkle.

The ccmetr popover

Two ways to get the numbers

Keychain Claude CLI
What it does reads the token Claude Code stored, calls the usage endpoint directly runs claude -p "/usage" and reads its answer
Access to secrets needs the keychain prompt once none at all
Cost per refresh one HTTP request ~5 s and ~0.5 GB peak while claude runs
Refresh interval 3 min 10 min
Per-model limits yes only what /usage prints

The CLI path is the default, because the keychain one cannot stay quiet — see below. It costs no quota either (/usage performs no inference — measured at 0 input and 0 output tokens), but every refresh spawns a real claude process that takes a few seconds and half a gigabyte of memory while it lives; the memory is released as soon as it exits.

Pick the keychain path if you'd rather have cheap refreshes, per-model numbers and don't mind re-approving access now and then.

You can switch at any time under Data source in the gear menu.

Privacy

The app exists to read one number, so it touches as little as possible:

  • It reads a single keychain item — Claude Code-credentials, the one Claude Code itself creates — and never writes to the keychain. On the CLI path it reads nothing at all.
  • The token goes to exactly one address: https://api.anthropic.com/api/oauth/usage. It is never logged, never written to disk, and re-read from the keychain before each request rather than kept around.
  • History stays on your Mac: ~/Library/Application Support/ccmetr/history.json holds percentages and timestamps, nothing else. Settings live in standard user defaults.
  • No telemetry, no analytics, no account, no crash reporting. Sparkle contacts GitHub to check for updates and system profiling is explicitly disabled.
  • The usage endpoint is undocumented. It may change or disappear without notice, which is also why polling is kept at 3 minutes.

Every release is built by the workflow in this repository — the logs, the archive and its SHA-256 are public.

Why the keychain keeps asking

Two separate reasons, and only one of them is ours.

The keychain item belongs to Claude Code. Its OAuth token lives about eight hours, and every time Claude Code refreshes it — including right after your Mac wakes up — it rewrites the item along with its access control list. Dumping the ACL shows exactly one trusted application afterwards: Claude Code itself. Whatever you approved is gone, so the prompt comes back roughly once per token lifetime. Nothing in ccmetr can prevent that; the item isn't ours to fix. That is why the CLI path is the default.

Signatures. macOS binds "Always Allow" to the app's designated requirement. An ad-hoc build has no stable identity, so its requirement is the hash of that exact binary — rebuild and the system sees a stranger. Releases are signed with one certificate, making the requirement identifier "com.ccmetr.app" and certificate leaf = H"…", which survives updates. Building locally, run ./scripts/signing-cert.sh once and pass CCMETR_SIGN_IDENTITY, otherwise every rebuild asks again.

Notes

  • It calls the same endpoint Claude Code's own /usage uses. That endpoint rate-limits hard and buckets requests by User-Agent — without claude-code/<version> you land in a punishing bucket and stay on 429 for a long while, so ccmetr sends the header and detects your installed version automatically. A 429 puts it into backoff instead of an error state; the last known numbers stay on screen.
  • The API returns no history, so the 7-day chart is built from samples the app collects itself. A fresh install starts with an empty chart.
  • Interval, launch at login, what to show in the bar and a below-10% alert live in the gear menu.

Build

macOS 14+ and a Swift 6 toolchain; Xcode isn't needed.

./scripts/build-app.sh      # → build/ccmetr.app
./scripts/make-assets.sh    # regenerates every image in docs/

Images aren't drawn by hand — the app renders them from its own UI (--export-hero, --export-popover, --export-bar-preview, --export-icon).

To ship updates: generate a Sparkle key pair once with ./scripts/sparkle-keys.sh, commit sparkle-public-key.txt, put the private key into the SPARKLE_PRIVATE_KEY secret. Create a signing certificate with ./scripts/signing-cert.sh and put it into MACOS_CERT_P12 / MACOS_CERT_PASSWORD so published builds keep one identity. Then push a v* tag — the release workflow builds, signs and publishes the appcast.

License

MIT

About

Claude usage limits in the macOS menu bar

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages