A tiny always-on-top macOS HUD that shows your Claude Code usage at a glance:
the 5-hour and weekly utilization bars from the same /api/oauth/usage
endpoint that powers claude /usage.
5h ▓▓▓▓▓▓░░░░░░░░ 43% 2h17m
wk ▓▓▓▓▓░░░░░░░░░ 37% 4d12h
- Borderless, terminal-styled, pinned above other windows.
- Drag the body to move; drag the edges to resize width and height
independently. New size persists to
config.json. - Three ways to quit: right-click the HUD → Quit, click the ◧ menu-bar
icon → Quit, or
Cmd-Qwhile the HUD is focused.
The HUD reads the live 5h and weekly utilization that Anthropic exposes per
account, so there is nothing to configure. There is no "set my limit" field —
the percentages already account for your plan. The API returns utilization as
a percentage, not raw tokens, so the HUD shows percentages plus reset
countdowns (this is the same data shown by claude /usage).
- macOS (uses native Cocoa via PyObjC; no Linux/Windows support)
- Python 3.10+
- Claude Code installed and
signed in at least once (the HUD reads the OAuth token from the
Claude Code-credentialsKeychain entry that the CLI creates on first sign-in)
git clone https://github.com/Elijahtab/Claude-Counter.git
cd Claude-Counter
python3 -m pip install -r requirements.txt
./run.shOn first launch macOS will prompt for Keychain access to read the Claude Code OAuth token. Click Always Allow to silence future prompts.
The repo ships a Claude-Counter.app bundle in the project root that wraps
run.sh. Double-click it from Finder, or drag it to your Dock / Launchpad
for one-click launching. Because the bundle is unsigned, the first launch
will trigger a Gatekeeper warning — right-click the bundle → Open to
bypass it once, and subsequent double-clicks will work normally.
The bundle is an accessory app (LSUIElement), so it does not add a
Dock icon. It does add a small ◧ menu-bar icon whose menu offers
Refresh and Quit — that, the HUD's own right-click menu, and Cmd-Q are
the three ways to quit.
./install-launchagent.sh installThis writes ~/Library/LaunchAgents/com.user.claudecounter.plist with the
absolute paths of the current checkout and your python3, then loads it. The
HUD will start automatically on every login and restart if it crashes.
Pass an explicit interpreter if you don't want whatever python3 is on
$PATH:
./install-launchagent.sh install /Users/you/.pyenv/versions/3.12.10/bin/python3To remove:
./install-launchagent.sh uninstallLogs go to /tmp/claudecounter.out.log and /tmp/claudecounter.err.log.
config.json is read at startup and rewritten when you resize the window.
| key | meaning | default |
|---|---|---|
refresh_seconds |
How often to re-poll /api/oauth/usage. |
30 |
window_width |
HUD width in points. | 230 |
window_height |
HUD height in points. | 60 |
edge_margin_px |
Distance from the top-right of the screen to anchor the HUD on first launch. | 12 |
alpha |
Reserved; currently unused (alpha is baked into the palette). | 0.92 |
oauth_usage.pyshells out tosecurity find-generic-password -s "Claude Code-credentials" -wto read the OAuth access token, thenGETshttps://api.anthropic.com/api/oauth/usagewith theoauth-2025-04-20beta header and parses thefive_hour/seven_dayutilization windows.counter.pyis a single-file PyObjC app: a borderlessNSWindowatNSStatusWindowLevel, a flippedNSViewthat draws two ASCII-block bars in SF Mono, anNSTimerfor periodic refresh, and manual mouse handling for edge-drag resize + body-drag move.
⚠ counter error/Keychain entry 'Claude Code-credentials' not found— Claude Code hasn't signed in on this account yet. Runclaudeonce, sign in, then refresh the HUD (right-click → Refresh now).Keychain read timed out— macOS is showing an "allow access" dialog behind another window. Find it, click Always Allow.- HTTP 401 from
/api/oauth/usage— the cached token has expired. Open Claude Code (claude) once to refresh it; the next poll will pick it up. - Nothing happens when I run
./run.sh— make surepyobjc-framework-Cocoais installed for the interpreterrun.shends up picking. Override which Python it uses withCLAUDE_COUNTER_PYTHON=/path/to/python3 ./run.sh.