{"slug": "mac-extension-panel-pill-nub-to-show-llm-usage", "title": "Mac extension (panel/pill/nub) to show LLM usage", "summary": "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.", "body_md": "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.\n\n| state | top edge | side edge |\n|---|---|---|\n| resting | ||\n| work mode |\n\nHovering either one opens the same panel: a 5-hour ring, a weekly meter, tokens, estimated spend and a reset countdown per provider.\n\nEverything below is in the menu-bar gauge icon, or in the right-click menu on the pill itself.\n\n**Display**— automatic (prefers the notched built-in screen), or any connected display by name. Pick your external monitor here.** Attach to**—*Top (notch)*,*Left edge*or*Right 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 spot*undoes any nudging.\n\nThe pill floats above the menu bar, but only over the pixels it actually draws: the\nwindow is deliberately larger than the pill (so the panel can animate without the\nwindow ever resizing) and stays mouse-transparent, opening up only while the cursor\nis over the pill itself. A window swallows every click inside its frame no matter\nwhat its views' hit tests return, so this is `ignoresMouseEvents`\n\ntoggled from an\nevent monitor — nothing else can hand a click to another application.\n\nEverything 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).\n\n**Codex — reported, not guessed.** Every `token_count`\n\nevent in\n`~/.codex/sessions/**/rollout-*.jsonl`\n\ncarries the server's own answer:\n\n``` php\npayload.rate_limits.primary    used_percent, window_minutes 300    -> 5-hour ring\npayload.rate_limits.secondary  used_percent, window_minutes 10080  -> weekly meter\n```\n\nThe newest rollouts are tailed and the most recent event wins, so the ring matches\nwhat Codex itself would tell you *as of your last Codex turn*. Nothing writes to\nthose files when you use the ChatGPT app, Codex on another machine, or the web, so\nthe reading can trail your real usage until Codex next makes a request. Once a\nreading is more than five minutes old the panel says so (\"as of 14:32 · 20m old\"),\nand opening the panel forces a re-read.\n\n**Claude Code — estimated.** `~/.claude/projects/**/*.jsonl`\n\nrecords per-message\n`usage`\n\n(input, output, cache creation, cache read) but no plan utilisation. The\nprovider replays those records, de-duplicates by message + request id, and buckets\nthem into rolling 5-hour blocks anchored to the top of the hour — the same shape as\nAnthropic's session window. The ring compares the live block against a ceiling:\n\n**auto**(default): your busiest 5-hour block on record** fixed**: a number you set, in dollars or tokens\n\nRows measured this way carry an `est`\n\nbadge. Spend is priced from the published\nper-model list prices in `Pricing.swift`\n\n; treat it as an estimate, not a bill.\n\n**Optional: real Claude limits.** *Sources ▸ Use Claude account limits* reads the\nClaude Code OAuth token from your login keychain and asks Anthropic for actual\n5-hour and weekly utilisation. It is off by default. Enabling it explains itself\nfirst, then does one foreground read so the keychain prompt is visible; if access is\ndenied it switches itself back off. After that the check runs on its own queue and\nnever blocks the pill — the local estimate stays on screen if it fails.\n\nThe transcript folder can run to hundreds of megabytes. Lines are filtered on raw\nbytes before any JSON is decoded, and the extracted usage plus per-file read offsets\nare cached in `~/Library/Application Support/UsageNotch/claude-cache.json`\n\n. First run\nafter install parses everything (~1s per 200MB); later launches restore from the\ncache and refresh in single-digit milliseconds. Providers publish independently, so\na slow one never holds up the others, and one that stops answering is parked rather\nthan freezing the panel.\n\nXcode is not required — SwiftPM plus a hand-assembled bundle is enough.\n\n```\n./run.sh\n```\n\nThat builds `build/UsageNotch.app`\n\n, replaces any running copy, and launches it.\n`./build.sh`\n\nbuilds without launching. The app is an accessory (`LSUIElement`\n\n), so it\nhas no Dock icon; the menu-bar gauge icon carries the menu.\n\nRequires macOS 14+ and a Swift 5.9+ toolchain (Command Line Tools are fine).\n\n```\n./build/UsageNotch.app/Contents/MacOS/UsageNotch --dump       # what the providers see\n./build/UsageNotch.app/Contents/MacOS/UsageNotch --placement  # where the pill would land, per display\n./build/UsageNotch.app/Contents/MacOS/UsageNotch --render ./docs  # re-render the screenshots\nUSAGENOTCH_DEBUG=1 ./build/UsageNotch.app/Contents/MacOS/UsageNotch\n```\n\n`--render`\n\nsnapshots the SwiftUI tree offscreen, which is also how the UI gets\nchecked when Screen Recording permission is unavailable. `USAGENOTCH_DEBUG=1`\n\ntraces\nplacement, hit regions, mode changes and provider timings on stderr.\n\n**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\n\n```\nmain.swift              entry point, --dump / --placement / --render modes\nUI/NotchController      panel + status item + refresh loop + menu + click routing\nUI/NotchPanel           borderless non-activating panel above the menu bar\nUI/NotchGeometry        notch metrics and per-display, per-edge placement\nUI/Placement            edge + anchor -> alignment, content rect, corner radii\nUI/NotchState           mini / pill / expanded, hover debounce, motion curves\nUI/Interaction          hover tracking and rect reporting for AppKit hit routing\nUI/NotchRootView        SwiftUI tree for the three states\nModel/UsageStore        provider fan-out, deadlines, published snapshot\nProviders/*             Claude Code, Codex, optional Anthropic account, cache, pricing\n```\n\nTwo decisions are load-bearing:\n\n**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.\n\n- Claude percentages are an estimate until you enable the account check.\n- 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.\n- Only Claude Code and Codex are wired up. Adding a provider means one file\nconforming to\n`UsageProvider`\n\nplus a line in`UsageStore`\n\n. - The app is ad-hoc signed, so \"Open at login\" may need approval in System Settings ▸ General ▸ Login Items.\n\nMIT — see [LICENSE](/abhayKashyap03/usage-notch/blob/main/LICENSE).", "url": "https://wpnews.pro/news/mac-extension-panel-pill-nub-to-show-llm-usage", "canonical_source": "https://github.com/abhayKashyap03/usage-notch", "published_at": "2026-08-30 05:06:14+00:00", "updated_at": "2026-08-30 05:21:59.679299+00:00", "lang": "en", "topics": ["developer-tools", "ai-tools"], "entities": ["Claude Code", "Codex", "Anthropic"], "alternates": {"html": "https://wpnews.pro/news/mac-extension-panel-pill-nub-to-show-llm-usage", "markdown": "https://wpnews.pro/news/mac-extension-panel-pill-nub-to-show-llm-usage.md", "text": "https://wpnews.pro/news/mac-extension-panel-pill-nub-to-show-llm-usage.txt", "jsonld": "https://wpnews.pro/news/mac-extension-panel-pill-nub-to-show-llm-usage.jsonld"}}