I'm building a companion island for my desktop AI assistant: approvals, a mascot, and a 14px wake strip A developer is building a companion "island" UI for the Ankita desktop AI assistant that surfaces pending approval requests in an always-on-top pill when the main window is hidden, using a 14-pixel wake strip and an ApprovalRegistry that stores pending requests on the entry itself so late subscribers can list them. The island hosts a mascot animation engine ported from Coucou's MIT-licensed Mochi engine, and its geometry module has zero Electron imports so it can be unit-tested with node:test. The work ships alongside unreleased OAuth loopback redirect changes and a deprecation window for COMPOSIO_API_KEY. I'm building a desktop AI assistant, and it has a permission problem that no amount of prompt engineering fixes. Ankita asks for approval before it does anything irreversible — sends a message, runs a script, opens a browser session. That's the right behaviour. The problem is where that question appears: in the main chat window. Minimise the app, hide it to the tray, alt-tab to your IDE — and the approval request sits there in a hidden window, waiting on you, while the agent sits there waiting on the request. Nobody is wrong here. But nothing happens. So I'm building a companion island: a small always-on-top pill pinned to the top edge of the screen that only exists when the main window is gone. It's the one UI element the assistant is allowed to keep while it's otherwise out of your way. The island has three views, and the sizes are deliberate constants, not vibes: There's also a tucked view, which parks the tab just above the screen edge so only a 14-pixel strip shows. Fourteen pixels is the whole product thesis: just enough to notice peripherally, just enough to click to wake it. Hover it and it peeks out; click it and the main window comes back. All of this geometry lives in a module with zero Electron imports, on purpose. islandSizeFor view, approvalCount clamps everything to the known presets — the comment in the code says it plainly: "a bad caller can never stretch the window." Positions, mode transitions, edge margins 8px so narrow displays never clip it — all of it is unit-testable with plain node:test . I test desktop geometry the same way I test server code, because desktop geometry is the thing that breaks on everyone else's machine. The interesting bit isn't the pill — it's the plumbing behind it. The ApprovalRegistry stores every pending request on the entry itself , not just as an emitted event. The code comment calls the island out by name: "a late subscriber such as the island can list what is still pending." The island subscribes late — it might be created after a request went out — and still gets the full list. The expanded view shows the tool name and what it wants to do, and you approve or deny from there without ever restoring the main window. That's the design decision I'm proudest of: the island is not a second chat window. It doesn't let you talk to the agent. It does exactly two things — show status, and clear approvals. One job, no scope creep. The island hosts a small companion mascot with states idle, working, thinking , emotes, eye shapes, and cursor-follow — it glances toward your pointer. The animation engine is ported from Coucou's open-source Mochi engine MIT licensed , re-skinned as Ankita's own character with original sound cues left out rather than ripped off. States are driven by tweens with easing functions, and the engine reports a busy flag so the renderer knows when everything has settled. Is a mascot frivolous in a tool that runs shell commands for you? Maybe. But the island only earns its screen space if you leave it visible, and a tiny face that looks at you when you approve things is weirdly effective at that. The island is riding along with two unreleased changes I'm finishing at the same time: http://127.0.0.1: