cd /news/developer-tools/mac-extension-panel-pill-nub-to-show… · home topics developer-tools article
[ARTICLE · art-115539] src=github.com ↗ pub= topic=developer-tools verified=true sentiment=· neutral

Mac extension (panel/pill/nub) to show LLM usage

A new Mac utility called the LLM usage meter clips onto the screen edge to display real-time rate-limit usage for Claude Code and Codex, reading local CLI files without network calls or API keys. The tool shows a 5-hour ring, weekly meter, token counts, estimated spend, and reset countdowns, with optional Anthropic account checks for accurate Claude limits.

read6 min views5 publishedAug 30, 2026
Mac extension (panel/pill/nub) to show LLM usage
Image: Michielbdejong (auto-discovered)

An LLM usage meter that clips onto the edge of your Mac's screen. It shows how much of your Claude Code and Codex rate-limit windows you have burned, expands into a full panel on hover, and shrinks to a sliver ("work mode") when you want it gone.

state top edge side edge
resting
work mode

Hovering either one opens the same panel: a 5-hour ring, a weekly meter, tokens, estimated spend and a reset countdown per provider.

Everything below is in the menu-bar gauge icon, or in the right-click menu on the pill itself.

Display— automatic (prefers the notched built-in screen), or any connected display by name. Pick your external monitor here.** Attach to**—Top (notch),Left edgeorRight edge. Side-mounted, the pill turns into a slim vertical bar hugging the screen edge, and the panel opens inward.Position— only meaningful on the top edge: right of the notch (default), left of the notch, or centred under it. On a display without a notch these read "right/left of center" and hang below the middle of the menu bar.Drag it. Press and drag the pill to slide it along its edge; drag it into another edge's band (within 90pt) and it re-attaches there, landing under the cursor.Position ▸ Reset to default spotundoes any nudging.

The pill floats above the menu bar, but only over the pixels it actually draws: the window is deliberately larger than the pill (so the panel can animate without the window ever resizing) and stays mouse-transparent, opening up only while the cursor is over the pill itself. A window swallows every click inside its frame no matter what its views' hit tests return, so this is ignoresMouseEvents

toggled from an event monitor — nothing else can hand a click to another application.

Everything is read from files the two CLIs already write on this Mac. No API keys, no network calls, nothing leaves the machine (unless you opt into the Anthropic account check below).

Codex — reported, not guessed. Every token_count

event in ~/.codex/sessions/**/rollout-*.jsonl

carries the server's own answer:

payload.rate_limits.primary    used_percent, window_minutes 300    -> 5-hour ring
payload.rate_limits.secondary  used_percent, window_minutes 10080  -> weekly meter

The newest rollouts are tailed and the most recent event wins, so the ring matches what Codex itself would tell you as of your last Codex turn. Nothing writes to those files when you use the ChatGPT app, Codex on another machine, or the web, so the reading can trail your real usage until Codex next makes a request. Once a reading is more than five minutes old the panel says so ("as of 14:32 · 20m old"), and opening the panel forces a re-read.

Claude Code — estimated. ~/.claude/projects/**/*.jsonl

records per-message usage

(input, output, cache creation, cache read) but no plan utilisation. The provider replays those records, de-duplicates by message + request id, and buckets them into rolling 5-hour blocks anchored to the top of the hour — the same shape as Anthropic's session window. The ring compares the live block against a ceiling:

auto(default): your busiest 5-hour block on record** fixed**: a number you set, in dollars or tokens

Rows measured this way carry an est

badge. Spend is priced from the published per-model list prices in Pricing.swift

; treat it as an estimate, not a bill.

Optional: real Claude limits. Sources ▸ Use Claude account limits reads the Claude Code OAuth token from your login keychain and asks Anthropic for actual 5-hour and weekly utilisation. It is off by default. Enabling it explains itself first, then does one foreground read so the keychain prompt is visible; if access is denied it switches itself back off. After that the check runs on its own queue and never blocks the pill — the local estimate stays on screen if it fails.

The transcript folder can run to hundreds of megabytes. Lines are filtered on raw bytes before any JSON is decoded, and the extracted usage plus per-file read offsets are cached in ~/Library/Application Support/UsageNotch/claude-cache.json

. First run after install parses everything (~1s per 200MB); later launches restore from the cache and refresh in single-digit milliseconds. Providers publish independently, so a slow one never holds up the others, and one that stops answering is parked rather than freezing the panel.

Xcode is not required — SwiftPM plus a hand-assembled bundle is enough.

./run.sh

That builds build/UsageNotch.app

, replaces any running copy, and launches it. ./build.sh

builds without launching. The app is an accessory (LSUIElement

), so it has no Dock icon; the menu-bar gauge icon carries the menu.

Requires macOS 14+ and a Swift 5.9+ toolchain (Command Line Tools are fine).

./build/UsageNotch.app/Contents/MacOS/UsageNotch --dump       # what the providers see
./build/UsageNotch.app/Contents/MacOS/UsageNotch --placement  # where the pill would land, per display
./build/UsageNotch.app/Contents/MacOS/UsageNotch --render ./docs  # re-render the screenshots
USAGENOTCH_DEBUG=1 ./build/UsageNotch.app/Contents/MacOS/UsageNotch

--render

snapshots the SwiftUI tree offscreen, which is also how the UI gets checked when Screen Recording permission is unavailable. USAGENOTCH_DEBUG=1

traces placement, hit regions, mode changes and provider timings on stderr.

hover— opens the panel and re-reads the sources; leaving collapses it after a short grace period** click**— refresh now, with the spin on the refresh glyph** drag**— slide the pill along its edge, or throw it at another edge to re-attach** work mode**— the chip in the panel (or the menu) collapses the pill to a nub; hovering the nub still peeks the full panel** right-click**— the full menu, same as the menu-bar icon

main.swift              entry point, --dump / --placement / --render modes
UI/NotchController      panel + status item + refresh loop + menu + click routing
UI/NotchPanel           borderless non-activating panel above the menu bar
UI/NotchGeometry        notch metrics and per-display, per-edge placement
UI/Placement            edge + anchor -> alignment, content rect, corner radii
UI/NotchState           mini / pill / expanded, hover debounce, motion curves
UI/Interaction          hover tracking and rect reporting for AppKit hit routing
UI/NotchRootView        SwiftUI tree for the three states
Model/UsageStore        provider fan-out, deadlines, published snapshot
Providers/*             Claude Code, Codex, optional Anthropic account, cache, pricing

Two decisions are load-bearing:

The window never resizes. It is sized once for the largest state; the pill morphs inside it. Resizing a window per hover is what makes this kind of UI stutter.Clicks are routed in AppKit, not SwiftUI. The panel never becomes key, and SwiftUI gesture recognisers do not fire in a non-key panel. The hosting view dispatches presses itself: a press that travels more than 4pt is a reposition, anything shorter is a click, matched against the rects the controls report.

  • Claude percentages are an estimate until you enable the account check.
  • Codex numbers are as fresh as your last Codex turn; the panel labels a reading older than five minutes. Usage from the ChatGPT app is not visible until Codex itself makes another request.
  • Only Claude Code and Codex are wired up. Adding a provider means one file conforming to UsageProvider

plus a line inUsageStore

. - The app is ad-hoc signed, so "Open at login" may need approval in System Settings ▸ General ▸ Login Items.

MIT — see LICENSE.

── more in #developer-tools 4 stories · sorted by recency
── more on @claude code 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/mac-extension-panel-…] indexed:0 read:6min 2026-08-30 ·