A native macOS menu bar app: a little animated robot that comes alive when Claude Code is generating, plus optional ChatGPT app activity detection.
- macOS 14 (Sonoma) or later
- Xcode 15+ (or the Swift toolchain via
xcode-select --install)
Build the app bundle:
cd RobotBar
zsh Scripts/build-app.sh
open .build/RobotBar.app
That creates .build/RobotBar.app, a double-clickable menu bar app. It does
not show in the Dock; look near the clock/control center area for RB and the
small robot face.
Fastest way to run without packaging:
cd RobotBar
swift run
To develop/debug in Xcode: open the RobotBar folder. Xcode will recognize
Package.swift and let you build/run/breakpoint it like a normal app target.
No .xcodeproj needed.
Open the RobotBar menu and enable ChatGPT app activity if you want the robot to light up when the ChatGPT macOS app is frontmost. This setting is saved in UserDefaults.
Use Choose Folder under Claude Logs to select your ~/.claude folder, or a
Claude log subfolder such as sessions or projects. This is optional for
local development, but it is the right model for a Mac App Store sandboxed build
because the user explicitly grants read access.
ChatGPT activity detection is presence-based only. It does not include token counts because the ChatGPT app does not write Claude Code-style local usage JSONL files.
See AppStore/APP_STORE_CHECKLIST.md for the remaining submission steps.
RobotBar now includes AppStore/RobotBar.entitlements with App Sandbox and
read-only user-selected file access. A final App Store build still needs a real
Xcode macOS App target, app icon, Apple Developer bundle identifier, signing,
and archive/upload through Xcode.
FSEventsWatcher.swift- a thin wrapper around Core Services'FSEventStream, recursively watching the selected Claude logs folder and reporting changed file paths the moment Claude Code writes to a session log. This is event-driven, not polling.ActivityMonitor.swift- on each Claude Code change, incrementally reads only the newly-appended bytes of the changed.jsonlfile, extracts each assistant turn'smessage.usageobject, de-dupes bymessage.id, and aggregates into "today" and the current rolling 5-hour window. It also observes the frontmost macOS application so the optional ChatGPT activity mode can light up the robot when ChatGPT is active.RobotIconView.swift- a hand-drawn menu bar robot with anRBlabel so it is easier to find in a crowded menu bar.MenuBarExtra(...).menuBarExtraStyle(.window)- lets the dropdown be an arbitrary SwiftUI view instead of a plain native menu list.
Claude Code writes local JSONL transcripts under ~/.claude. Depending on the
Claude Code version and configuration, those logs may be under subfolders such
as projects or sessions.
Every assistant turn is a JSON line containing a message.usage object with
the token breakdown, and a message.model field. This is entirely local: no
API key, no network call, nothing leaves your machine.
Claude Code writes local token logs; the regular ChatGPT app, Claude Desktop chat window, and claude.ai web chat do not expose the same local usage files. RobotBar can light up for ChatGPT app focus, but token counts remain based on Claude Code logs.
Claude Desktop's Cowork/agent mode is a partial exception: it writes its own
audit log to ~/Library/Application Support/Claude/local-agent-mode-sessions/,
which could be added as a second watched path later.
- Add
~/Library/Application Support/Claude/local-agent-mode-sessions/as a second watched directory to also catch Cowork sessions. - Add similar frontmost-app toggles for other AI apps.
- Read the Claude Code OAuth token from the macOS Keychain
(service
Claude Code-credentials) to optionally show official plan/rate-limit percentage from the API, not just locally-derived totals. - Persist
seenMessageIDs/ offsets to disk so counts survive an app restart. - Support Codex/other CLI tools' local logs the way
ai-token-monitordoes, if you want this to go beyond Claude specifically later.