A native macOS menu bar app that tracks your Claude Code usage windows and running sessions across all surfaces — the desktop app, terminal (iTerm), and the VS Code extension.
Note
ClaudeBar is an unofficial, independent project — not affiliated with or endorsed by Anthropic. It only reads the local files Claude Code already writes, plus one optional usage endpoint you authorize.
Homebrew (recommended):
brew install --cask nerlichman/tap/claudebarOr download directly: grab the latest ClaudeBar.dmg from the Releases page, open it, and drag ClaudeBar into Applications.
The release DMG is signed with a Developer ID and notarized by Apple, so ClaudeBar installs with no Gatekeeper warning (Homebrew installs that same notarized build). To compile it yourself instead, see Build & run.
- Menu bar: your 5-hour window utilization (e.g.
42%), with a ✋ icon when any session is waiting for your input and a⚠️ icon above 90%. The label style is configurable (Icon + %, % only, Icon only) via the Settings popover; compact styles expand back to the full label whenever something needs attention. Right-click (or control-click) the status icon for a quick menu — Open / Refresh / Quit. - Dropdown:
- Usage windows as titled cards with capsule progress bars and reset countdowns: Current Session (5-hour), All Models (weekly), a Sonnet weekly card (shown only once there's Sonnet usage), and a Usage Credits card with your authoritative dollar spend when the account has a credit balance.
- Every running Claude Code session with its title, project name (worktrees displayed nicely), git branch, surface icon (terminal / desktop / VS Code), and live state — Active (generating), Waiting (blocked on a permission prompt or your input), or Idle.
- Click a session to jump to it: terminal sessions select the exact iTerm tab (matched by the claude process's controlling tty), desktop sessions deep-link to the exact session view (
claude://claude.ai/claude-code-desktop/<id>, falling back to activating the app), VS Code sessions open the workspace window. The first terminal jump triggers a one-time Automation permission prompt. - Expandable rows: each session shows its token count and API-equivalent cost inline; expanding reveals today vs lifetime breakdowns.
- Sessions idle for 60+ minutes collapse into a dormant group; sessions that ended collapse into an earlier today group.
- Today and This week token totals with the API-equivalent cost (informational for subscription plans). Headline token figures count input + output only — matching Claude's own usage view — with cache reads/writes broken out separately below. Cost still includes cache, since usage credits bill it at standard API rates.
- Notifications: when the 5-hour or weekly window crosses 75% / 90% (once per window), and — opt-in, off by default — when a session starts waiting for your input (the desktop app and terminal already surface that, and Claude re-enters waiting every turn). Delivered as
osascriptbanners (Script Editor icon) — nativeUNUserNotificationCenterbanners require provisioned signing (Developer ID or an embedded provisioning profile; an Apple Development cert alone is not enough — verified empirically). The app auto-upgrades to native banners if it ever runs with such a signature. A Settings-popover toggle turns notifications off entirely.
Everything except the usage windows comes from local files Claude Code already writes — no credentials, no network. The usage windows optionally call one Anthropic endpoint with a token you authorize (see Authentication).
| Data | Source |
|---|---|
| Running sessions + waiting state | ~/.claude/sessions/{pid}.json (PID liveness validated via the kernel to filter stale files) |
| Working set vs dormant | Claude Code lifecycle hooks (SessionStart/UserPromptSubmit/Stop/Notification/SessionEnd → claudebar-hook.sh → events/{session_id}.json) plus transcript activity; idle sessions untouched for 60+ min collapse into a "dormant" group, and SessionEnd hides a session even if its process lingers |
| Session titles | Desktop app session metadata, falling back to the transcript slug |
| Activity (generating vs idle) | mtime of ~/.claude/projects/*/{sessionId}.jsonl |
| Usage windows (5h / weekly) | Two sources, freshest wins: (a) the OAuth usage endpoint api.anthropic.com/api/oauth/usage polled every ~3 min with a token ClaudeBar holds (see Authentication) — exact data; (b) a statusline hook capturing the rate_limits JSON Claude Code pushes to statusline scripts (credential-free fallback, only refreshes on terminal interactions — the desktop app does not invoke statuslines) |
| Token/cost stats (per session and per day) | Incremental tail-parsing of the transcript .jsonl files |
Important
The only network call is the usage poll (plus OAuth sign-in/refresh). ClaudeBar never writes to or deletes anything inside ~/.claude — the statusline/hooks config in ~/.claude/settings.json is the one exception, added with your consent.
The last good API reading is cached across relaunches, and 429 responses trigger an exponential cooldown (5 min doubling up to 30 min, surfaced in the dropdown).
The usage windows need an OAuth access token; everything else works without one. Pick whichever path fits — all are optional, and the statusline fallback keeps working regardless.
| Method | Auto-refresh | Needs the terminal? | Keychain item |
|---|---|---|---|
| In-app sign-in (recommended) | ✅ | No | ClaudeBar-credentials |
| Keychain token | ✅ | Once, to claude login |
Claude Code-credentials |
| Manual paste (legacy) | ❌ | For the copy command | — |
-
In-app sign-in (recommended — no terminal needed). Settings → Sign in to Claude… runs a standard OAuth Authorization Code + PKCE flow in your browser; you copy the code the callback page shows back into Paste sign-in code from clipboard. ClaudeBar stores the result in its own Keychain item (
ClaudeBar-credentials) and refreshes it indefinitely using the stored refresh token (rotated token written back each time). After one sign-in the token never goes stale — you never have to touch the terminal. -
Keychain token (for terminal users). The Use Keychain token for usage toggle reads the Claude Code CLI's own Keychain item (
Claude Code-credentials). That item only exists once you've runclaudeand logged in at least once, but from then on ClaudeBar keeps it fresh on its own — the same auto-refresh as path 1. Good if you live in the terminal and would rather not do a separate in-app sign-in. ClaudeBar's own item (path 1) takes precedence when both exist.
3. Manual paste (legacy fallback)
Copy the token by hand and click Paste usage token…:
security find-generic-password -s "Claude Code-credentials" -w | jq -r '.claudeAiOauth.accessToken' | pbcopyThis one does not auto-refresh — when the token rotates the dropdown shows "usage token expired" and you re-paste. Superseded by paths 1 and 2, kept for flexibility.
Note
Why both 1 and 2 exist: the Claude Code-credentials Keychain item is only refreshed while the CLI is running, so desktop-only use let its access token expire (the original staleness bug). ClaudeBar now refreshes whichever item it's using via the OAuth refresh token, so neither path goes stale — path 1 just removes the one-time CLI login too.
| Requirement | |
|---|---|
| Platform | macOS 14 (Sonoma) or later |
| Toolchain | Xcode command line tools · Swift 5.10+ |
| Dependencies | Sparkle 2 (auto-updates), fetched via SwiftPM — otherwise Apple frameworks only |
| Command | What it does |
|---|---|
make run |
Build, bundle, sign, and launch from build/ |
make install |
Build + install to ~/Applications and launch |
make dmg |
Build a shareable (unsigned) build/ClaudeBar.dmg |
make dist |
Build a signed, notarized, stapled build/ClaudeBar.dmg for release |
make appcast |
Regenerate the Sparkle update feed (appcast.xml) from appcast-archives/ |
make install-hook |
(Re)install the statusline capture hook |
make verify |
End-to-end smoke test |
make logs |
Tail ~/Library/Logs/ClaudeBar/claudebar.log |
make stop |
Quit the app |
The Claude Code hooks (statusline capture + lifecycle events) can be installed two ways:
- From the app: Settings popover → Install Claude Code hooks. The scripts are bundled inside the .app, so this works from a shared .dmg without the repo. It backs up
~/.claude/settings.json(settings.json.claudebar-backup) before registering, never removes existing entries, and preserves a pre-existing statusline command by delegating to it. - From the repo:
make install-hookcopies the scripts; add the registration to~/.claude/settings.jsonyourself:
"statusLine": {
"type": "command",
"command": "bash \"$HOME/Library/Application Support/ClaudeBar/statusline-hook.sh\""
}Either way the hook delegates to your original statusline (captured command or ~/.claude/statusline.sh), so the terminal statusline looks exactly as before. The scripts have no dependencies beyond stock macOS.
scripts/make-app.sh signs local builds with an Apple Development certificate by default (override with CODESIGN_IDENTITY=..., falls back to ad-hoc if the identity isn't in the keychain). A real signature keeps the app's code-signing identity stable across rebuilds, so TCC Automation grants survive.
make dmg— a quick drag-to-Applications image (unsigned / dev-signed) for sharing with people who can approve it themselves once via System Settings → Privacy & Security → "Open Anyway".make dist— the public release path: a Developer ID–signed, notarized, and stapled DMG that installs with no Gatekeeper prompt. Requires aDeveloper ID Applicationidentity and a notarytool keychain profile — seescripts/dist.shfor the one-time setup.
Both images are fully self-contained — recipients install the Claude Code hooks from the Settings popover, no repo needed. The notarized make dist build additionally delivers native UNUserNotificationCenter banners (it carries a Developer ID signature); other builds fall back to osascript banners. Building from source (make install) also skips the Gatekeeper step for anyone with the Xcode command line tools.
Notarized release builds update themselves via Sparkle: the app polls an appcast feed and prompts the user when a newer version is available, verifying the download against an EdDSA signature. Updates are gated to Developer ID–signed .apps only — local make run / dev builds never self-update (the "Check for Updates…" menu item and the Settings toggle are hidden), so there's nothing to configure for development. scripts/make-app.sh embeds and signs Sparkle.framework into the bundle automatically.
One-time setup — generate the EdDSA signing keys:
swift build # so the Sparkle tools exist under .build/artifacts
.build/artifacts/sparkle/Sparkle/bin/generate_keysThis stores the private key in your login Keychain and prints the public key. Paste the public key into Resources/Info.plist as SUPublicEDKey. Back it up off-machine (generate_keys -x sparkle_private_key.pem) — losing the private key means no future build can be delivered as an update.
Per release:
- Bump the version in
Resources/Info.plist(CFBundleShortVersionString+CFBundleVersion) and the launch log line inSources/ClaudeBar/ClaudeBarApp.swift.CFBundleVersionmust strictly increase — Sparkle compares it to decide whether an update exists. CODESIGN_IDENTITY="Developer ID Application: …" make dist→ notarizedbuild/ClaudeBar.dmg.- Stage it for the feed:
cp build/ClaudeBar.dmg appcast-archives/ClaudeBar-<version>.dmg(keeping past DMGs lets Sparkle build delta updates). - Publish the DMG to the GitHub release it's downloaded from (the
appcasttag keeps the download URL stable across versions):gh release upload appcast appcast-archives/ClaudeBar-<version>.dmg. make appcast— signs each archive with the Keychain key and regeneratesappcast.xml.git add appcast.xml && git commit && git push— the feed goes live at theSUFeedURL.
- Launch at login: toggle in the Settings popover (SMAppService). Flip it from the installed copy (
make install), so the login item points at~/Applications/ClaudeBar.apprather than a build directory. - Threshold testing:
defaults write com.nerlichman.claudebar debugThresholds -array 1makes the next evaluation fire at any usage level;defaults delete com.nerlichman.claudebar debugThresholdsrestores 75/90. - Cost figures use current Claude API per-MTok prices (cache reads at 0.1×, cache writes at 1.25×/2×) — they show what your usage would cost at API rates, which is informational if you're on a subscription plan.
MIT © 2026 Nicolas Erlichman
