Building Bubble · 2026
Published · 5 min read
An agent asked me a question. I never saw it. So I built an app that hangs from the notch.
Coding agents stop and ask you things, and the question is always in the tab you're not looking at. Bubble is a macOS app that drops the question out of the notch so you can answer it without finding the tab. The decisions behind it, what it refuses to do, and what it still can't.
A coding agent runs for a few minutes and then stops. It isn't finished and it isn't broken. It's asking a question: can I run this command, can I edit this file, do you want yes or no.
The question is in a terminal tab. If I'm in another tab, another window or another app, it sits there. The agent isn't doing anything, and neither am I, because I don't know it's waiting. The only way to find out is to go and look.
Bubble is what I built so I stop going to look.
Decision 1: bring the question to me
Every fix I could think of for this was a notification. A sound, a badge, a banner. They all tell you something is waiting, and then you still have to hunt for which tab, switch to it, read the prompt and type the answer.
The notification was never the expensive part. Finding the tab was. So Bubble doesn't notify you that a prompt exists. It shows you the prompt. When a tab you aren't looking at needs you, a card opens out of the MacBook's notch with the actual question and its actual choices. Click one and Bubble types it into the right tab, and the card folds away.
If your Mac has no notch, it hangs from the top middle of the screen instead.
Decision 2: understand the prompt, don't just flag it
A card that says "something is waiting" would be a notification with extra steps. To be useful, Bubble has to know what's being asked.
It reads Claude Code's permission prompts, its multiple-choice questions and its multi-select checkboxes. It reads [y/N] and (yes/no) from any CLI. It reads the arrow-key lists and checkbox lists that tools like Inquirer, Clack and Prompts draw. And once a screen goes quiet, it reads plain questions like Project name:.
That last one is a judgment call, because a quiet screen could also be a slow build. The answer I settled on is to wait for the quiet and not guess before it. A wrong card is worse than a late one.
There's also a hole I left deliberately. Anything asking for a password stays in the terminal. Bubble never shows it, never reads it and never types it.
Decision 3: use each terminal's own door
To answer a prompt, Bubble has to read a terminal it doesn't own and type into it. How it does that depends on the terminal.
For iTerm2 and Terminal, it asks macOS for Automation permission, and the setup asks for that one permission at the moment you click the button for it, not all at once. For tmux, kitty and WezTerm it skips that and uses each one's own command line tool, which needs no macOS permission at all. tmux works in any terminal that runs it, which is how Ghostty, Warp, Alacritty and the VS Code terminal are covered. Those three can't be read from the outside, so the honest answer for them is: use tmux.
I'd rather say "not supported without tmux" than ship something that sometimes works.
Decision 4: show the real command
A card that says "Claude wants to run a command, Yes or No" is a trap. You'd learn to click Yes without reading, which is the opposite of what a permission prompt is for.
So connecting Claude Code adds two hooks to its settings, and with them the card shows the exact command or diff you're approving. Bubble also pings you when Claude finishes. The hooks are added to ~/.claude/settings.json alongside whatever you already have, and the original is backed up as settings.json.before-bubble. The integration is optional, and removing it is two entries.
Decision 5: keep everything on the Mac
Bubble reads your terminal tabs, and what's in a terminal is some of the most private text on a machine. So it reads them locally and sends them nowhere.
The usage meters follow the same rule. Bubble shows your 5-hour and weekly limits for Claude, Codex and Command Code, and to do that it reuses the logins those tools already saved on your Mac. It sends each login only to that tool's own server, making the same request the tool makes for its own usage screen, and it never changes or refreshes one. A meter you turn off is never read, so macOS never asks about it.
Decision 6: the keyboard comes first
Dragging a mouse to a notch is slower than the thing it replaces if you're already typing. So there's one shortcut, ⌃⌥Space, that puts the keyboard on the top card. 1 to 9 picks a choice, Y and N answer yes/no, and Esc hands the keyboard back to whatever you were doing. Press the shortcut again and it moves to the next card.
What it can't do
Terminal.app is the weak spot. Bubble can type a line and press Enter there, and that's all. Ticking checkboxes, typing your own reply to a Claude menu, and Claude's prompts with several questions need keys Terminal can't be sent. For those, the card has an arrow that takes you to the tab. iTerm2, tmux, kitty and WezTerm handle all of it.
It's also not notarized by Apple yet. If you download the zip in a browser, macOS will say it can't verify the app. The install command and the Homebrew cask don't show that, so that's what the README tells you to use. I'd rather you know that before you install it than after.
Where it's going
Bubble is free and MIT-licensed, it runs on macOS 14 or later on Apple silicon and Intel, and I'm launching it soon. The code and the install are on GitHub.
The agents are getting better at working alone, which means they stop less often. But every time one does stop, it's because it needs something only I can give, and that moment shouldn't depend on which tab I happened to be looking at.