Claude without leaving
I work in VS Code and Figma. Switching to a browser tab to ask Claude something breaks what I was doing. By the time I’m back, I’ve lost the thread. So I built a floating window that sits above apps and mirrors a live claude.ai conversation.
What I built
A small Electron window that floats above every other app on the Mac. Always on top, visible through fullscreen. A Chrome extension reads the claude.ai page and types into it. No API key. The same conversation you already have open, mirrored.
The Build
The version I deleted
I built the relay first because I understood it. Chrome extension reads the page, sends to Cloudflare, Cloudflare fans it out to a web panel. I finished it and then wrote down what I actually needed: something still visible when I switch to Figma.
A web page lives in a tab. It disappears the moment you leave. I had built the thing I was trying to escape.
Deleting the relay removed the public endpoint, the round trip to the internet, and the Cloudflare account. Two processes on the same machine talking to each other over localhost don’t need any of that.
The protocol stayed identical. Every message type, turn.start, turn.delta, turn.end, the same. The extension never knew where the server was. Building the wrong version first is what made the right version obvious.
What the virtualizer cost me
Claude.ai shows a moving window onto the conversation. Only the messages near your scroll position exist. I assumed the page was the conversation. It isn’t.
Seven controls, each one from a bug
I didn’t design these up front. Each appeared after something broke. Click a marker to see what the bubble looked like before the fix, and what it cost.
?q=london&units=metric
Five attempts at one bug
A week in, every reply appeared twice. Four fixes. Each one broke something new.
The background tab problem
If a conversation has context in older messages, the bubble can’t reach it. Loading older messages means scrolling the claude.ai page. But the bubble sits in the background while you use it, and Chrome suspends rendering in background tabs. The scroll lands. Nothing redraws. The context stays out of reach.
What the tab does
The tab renders, authenticates, and displays. The bubble reads what the tab produces.
What I built works. It is faster than switching tabs and stays visible through fullscreen and app switches. It fails in the ways the architecture predicts and says so when it does.