If you use Claude Code seriously, you probably don't run one session. You run three. A refactor grinding away in one terminal, a bug investigation in another, maybe a docs pass in a third. The agents are fine. They're patient, they're parallel, they never complain.
The bottleneck is you.
At some point one of those sessions finishes and asks a question — "should I also update the tests?" — and then it just... sits there. Silently. Behind four other windows. Twenty minutes later you tab over and realize the expensive AI coworker you're paying for has been waiting for a yes/no answer since before your coffee went cold. Multiply that by a few sessions a day and you are the slowest component in the pipeline.
I got tired of being the bottleneck, so I built MenubarCC: a tiny macOS menu bar app where an animated pixel-art crab named Clawd shows the live status of every Claude Code session at a glance. Think RunCat, except instead of telling you your CPU is busy, it tells you when your AI needs you.
One crab, four states
Clawd has exactly four animations, and each one maps to an aggregate state across all your sessions:
- Walking — Claude is working. Leave it alone. Go do something else.
- Bouncing — a session finished and is waiting for your input. This is the one that matters, so it takes priority over everything else.
- Pulsing — a session has been busy with no progress past a configurable threshold (5–60 minutes). Something is probably stuck in a loop or hung on a command.
- Static — everything is idle. Peace.
The priority order is deliberate: waiting > stuck > active > idle. A walking crab means "all good"; a bouncing crab means "you are currently blocking a robot." After a couple of days it becomes reflexive — bounce appears in peripheral vision, you go answer the question, the crab starts walking again.
Clicking the crab drops a menu that lists every session grouped by state — STUCK, ACTIVE, WAITING, IDLE — each with its project folder and how long it's been in that state:
And if you're not even looking at the menu bar, MenubarCC fires native macOS banner notifications headlined with the project name — "MenubarCC: response finished", "dotfiles: permission requested" — so you know which session wants you without opening anything. Sounds and banners are separate toggles, and you can assign a custom sound (mp3/wav/m4a, whatever) per event type. My permission requests go "ding", my finished responses go "pop". It's silly and it works.
Install
Homebrew:
brew tap ksterx/tap && brew install --cask menubarcc
Or grab the DMG from the releases page and drag it into Applications. On first launch, the app offers to install the Claude Code hook for you — one click, and one click to uninstall it later if you want. Requirements: macOS 13+, Apple Silicon.
The app is Developer ID signed and Apple-notarized, so there's no "unidentified developer" dance. It's MIT-licensed and the whole thing is on GitHub.
How it works
There's no magic and no cloud. Three moving parts:
- Claude Code hooks. Claude Code has a hooks system that fires on lifecycle events — session start, stop, notification, permission request. MenubarCC installs a small Python bridge script into your hook config that records "this session is waiting for input" flags and event metadata.
-
Local state files. Session status lands in JSON files under
~/.claude/sessions/. The app polls them every 10 seconds and derives each session's state from status + waiting flag + elapsed time. That's the entire "protocol": files on disk. - A native Swift/AppKit app. No Electron, no Python runtime, no frameworks. The crab animation frames are generated at runtime with CoreGraphics from a single PNG. The download is about 150 KB — smaller than most favicons' node_modules.
Everything stays on your machine. The only network call the app ever makes is checking GitHub releases for updates (there's a built-in auto-updater, because asking people to re-download DMGs is rude).
The war story: macOS 26 ate my Python app
Here's the part fellow developers usually enjoy.
MenubarCC v1.x was a Python app built on rumps, packaged with py2app. It worked great — until macOS 26 Tahoe.
Tahoe shipped the new Liquid Glass menu bar, and with it, my status item simply stopped rendering. Fine, I thought, some py2app/PyObjC incompatibility, I'll debug it. But it got weirder: macOS now caches NSStatusItem positions per bundle ID, and my app had gotten itself cached into an invisible slot. Even after I fixed the rendering path, the icon stayed gone — the system remembered where my status item "belonged" and that place happened to be nowhere. Nuking preferences didn't help. The bundle ID itself was poisoned.
I tried a native Objective-C launcher shim around the Python core. I tried increasingly cursed workarounds. Eventually I accepted the obvious: fighting a new OS through three layers of Python packaging glue was a losing game. v2.0 became a ground-up rewrite in Swift and AppKit — with a new bundle ID, because the old one was permanently haunted.
The rewrite hurt for about two days and paid for itself immediately. The Python version was a ~30 MB app bundle dragging a full interpreter around; the Swift version is 150 KB, launches instantly, animates smoothly, and talks to NSStatusItem like a first-class citizen instead of through a séance. If you maintain a menu bar app in a non-native stack, consider this your friendly heads-up about Tahoe.
Try it
MenubarCC is free and open source:
brew tap ksterx/tap && brew install --cask menubarcc
If you run multiple Claude Code sessions and have ever discovered one waiting on you for half an hour, give Clawd a spot in your menu bar. Stars are appreciated, and issues are very welcome — feature requests, bug reports, or strong opinions about crab animation frame rates all count.
This is an English adaptation of my original Japanese article on Zenn.


Top comments (0)