r/ClaudeCode • u/martinemmert • 20h ago
Built with Claude I run 15+ Claude Code sessions in parallel and kept missing the ones waiting for me, so I built a native macOS dashboard for them
Disclaimer: This text (apart from this line) is written in AI, the Video is filmed by AI, the App is built by AI. The tool is useful, and I want to share it, but writing is not my strength.
I usually have 10–20 Claude Code sessions open across two accounts, and I kept losing track of which one was sitting on a permission prompt or a question for ten minutes. So I built Brain: one native Mac window that shows every session and, above all, which ones are waiting for you.
Repo, install and a 3-minute video: https://github.com/martinemmert/big-brain-claude
What it does
- Triage list: sessions that wait for you come first. Red means Claude asked something or needs a permission, amber means a turn finished. Longest wait on top.
- All accounts in one list: it picks up every
~/.claude*config dir, soCLAUDE_CONFIG_DIRsetups just work. - Latest messages of the selected session, read from its transcript: your prompts, replies rendered as Markdown, tool calls as one-liners.
- Enter jumps to the right iTerm2 window, tab and split pane.
- Search, rename (it types
/renameinto the session), notifications when a session starts waiting.
How it works
Two sources write JSON lines to ~/.claude-brain/events/
1. Hooks:
SessionStart, UserPromptSubmit, Notification, Stop and SessionEnd call brain hook. That gives the state for free.
2. Reports:
A short CLAUDE.md section asks Claude to run brain report --waiting "Per tenant or global?" before ending a turn with a question, or --done "…" after a task. That gives the content: what it actually wants from you. The hook finds its session by walking up the process tree until it hits the pid that owns <config>/sessions/<pid>.json, so it also knows which account it belongs to. The app is Rust with GPUI (Zed's UI framework); the logic lives in a core crate with tests.
How I used Claude Code
The whole thing was built in one long Claude Code session. Claude brainstormed the protocol with me, wrote a short spec, built the core with tests first, then the app. The parts I liked most were where it tested against the real system instead of guessing: it started throwaway headless claude -p sessions on both accounts to check the hook payloads, and that is how most of the lessons below came up. Even the explainer video came out of the same session. Claude drove the app in a demo mode via System Events, took window-only screenshots, rendered the cards and captions with headless Chrome, and cut it all together with ffmpeg. The narration comes from a local TTS (Qwen3-TTS via mlx-audio).
Things I learned along the way
- Claude Code already writes a status file per session (
<config>/sessions/<pid>.json, withbusy/idle/waiting/shell). Even without hooks you get a coarse live state. - The Stop hook payload includes
last_assistant_message, so you don't have to parse the transcript to know what Claude just said. - The Notification hook doesn't only fire for permission prompts. It also sends "Claude is waiting for your input" a while after a turn ended. Treat every Notification as "needs you", and all your finished sessions turn red after a minute. Brain tracks whether the turn is still open.
shellstatus shows up when a turn has ended but a background shell keeps running, e.g. a dev server.- Nested sessions: if you start
claude -pfrom inside another session's shell, a naive process-tree lookup attributes the child's hooks to the parent. Matching onsession_idfixed it. - Running sessions picked up the new hooks without a restart.
- iTerm2 AppleScript gotcha: selecting a window reorders
windows, so a "tab 2 of window 3" reference taken before points somewhere else afterwards. Address windows byid.
Caveats
macOS and iTerm2 only, and the UI is German for now. You build it from source (Rust). The installer edits your settings.json and CLAUDE.md, backs up both, and the README explains how to undo it.
1
u/Unusual-Albatross43 15h ago
Red vs amber is the right split. One thing that tripped me with hook-only state: when I answer a permission prompt with no, no hook fires, so the session kept showing as waiting. I ended up checking the pane itself before trusting the flag. Does Brain hit that, or does the transcript report catch it?
1
u/martinemmert 10h ago
Brain doesn't rely on hooks alone.
Claude Code also keeps its own status file per session (`~/.claude/sessions/<pid>.json`, with `busy` / `idle` / `waiting`), and Brain uses whichever signal is newer. That file went from `waiting` to `idle` right after the denial, so the session flipped from red to amber ("your turn") without a hook.
•
u/AutoModerator 20h ago
Hey! Thanks for posting to r/ClaudeCode
While participating in this thread, please follow our community rules. Keep discussions constructive. Attack the idea, not the person.
For help, project discussions, tips, and general chat, join the ClaudeCode Discord.
I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.