Switchboard
Years ago I built twotter, an Electron app for controlling my Twitch streams. I wrote every line myself, and that's exactly why it died: I kept inventing new ideas faster than I could build them. The backlog only ever grew, motivation only ever shrank.
Switchboard is the rebuild — and this time the equation is different. The idea list is still never-ending; the difference is that AI (Artificial Intelligence) now does the implementation, so the list is actually tractable.
What it is
A cross-platform (Linux/Windows/macOS) streaming control hub built on Tauri 2: one tray-resident app that drives any number of OBS (Open Broadcaster Software) instances and Twitch accounts, bridges Spotify, Discord and Home Assistant, serves seven browser-source overlays from an embedded web server, and glues it all together with an event → action rules engine. Multiple machines pair into a LAN (Local Area Network) mesh over TLS (Transport Layer Security), so a rule firing on my streaming PC (Personal Computer) can flip lights through the Home Assistant instance my other machine talks to.
The dashboard
The dashboard is what "everything's fine" looks like in practice: Streaming MAC two hours forty-seven minutes into Live — Gameplay, Gaming PC (Personal Computer) recording a 30-second-delayed backup, Twitch reading 42 watching and 9 in chat, Spotify mid-track on Midnight City, and a recent-activity feed logging every automation fire down to the second.
Automations
The rules engine is the part that turns "control panel" into "automation" — triggers, conditions, action sequences and templating, each with its own run history so a rule that silently stopped firing is visible instead of just suspicious. The Follow alert rule below only fires while Streaming MAC is streaming, and its last run (fired 20:03:02) shows exactly why that guard matters — a follow that lands after the stream ends shouldn't pop an on-screen alert to nobody.
Song announcements is the one running live in that same list, and opening it for editing is where the template actually gets built: triggered on Spotify: Song changed, gated on Spotify is playing on This machine, it posts a templated Discord message. The editor shows the exact template, ♫ Now playing: {artists} — {title_no_feat}, live-previewing beneath it as ♫ Now playing: M83 — Midnight City against whatever's actually spinning — so nobody has to guess what the mustache-style variables resolve to before the rule ever fires for real.
Now playing
The now-playing overlay is the one I actually watch live — a plain browser source pointed at the embedded web server, updated the instant the Spotify bridge sees a track change, no polling on either end. It's the same Midnight City the automation editor was templating against a moment earlier, just rendered the way the audience sees it: track and artist on one line, a progress bar and elapsed/total time on the next.
Under the hood
Architecturally it's deliberately backend-heavy: ~30k lines of Rust own every connection, scheduler and state machine in long-running tokio tasks that survive the window closing to tray. The React frontend is a thin, event-driven client — no polling, no SQL (Structured Query Language) in the webview, secrets only in the OS (Operating System) keyring. And there are zero app secrets: Twitch uses Device Code Grant (they stopped allowing http://localhost redirect URIs, which made the choice easy), Spotify uses PKCE (Proof Key for Code Exchange). The public repo and the shipped binaries contain nothing sensitive.
The division of labour
The honest headline: the overwhelming majority of Switchboard's code was written by Claude. My hands-on share of the code is maybe 1–5% — I did the planning and brainstorming, wrote the GitLab CI (Continuous Integration) myself, reviewed every change, and tested everything on real hardware (EndeavourOS and macOS). Product owner and lead architect, not typist.
The numbers from the first ~11 weeks: 837 commits, 97 CalVer (Calendar Versioning) releases, milestones M0 through M9 shipped in about six weeks. On day one, the gap between "scaffold" and "working multi-instance OBS (Open Broadcaster Software) + Twitch UI (User Interface)" was fifteen minutes of commit history. That pace is only sustainable because of process: a PLAN.md written in a three-hour planning session before the first commit, DONE.md/TODO.md as single-source status ledgers, and — the piece I'd recommend to anyone doing this — a persistent agent memory: 63 committed files of gotchas, decisions and "why it's this way", indexed and typed, so every future session (and every future agent) inherits what previous ones learned the hard way.
What the memory files remember
A sampling of what's in there, because this is the stuff that actually costs days:
AppImage packaging is a bug class, not a bug. The AppImage bundled a stale libwayland that shadowed the host's and crashed GPU (Graphics Processing Unit) rendering — but only in release builds, proven by an isolated bisect; the fix strips the libs in CI (Continuous Integration) and re-signs the updater signature. The same release was silent because WebKitGTK's WebAudio needs GStreamer plugins that dependency-walking bundlers never find — fixed by bundling more, the exact opposite direction. And "open in browser" silently did nothing on KDE Plasma 6, because Tauri ships a frozen xdg-open that only knows Plasma 4 and 5 — and exits 0 on failure.
Fixed ports are a lie on Linux. Switchboard's overlay and control ports sit in the kernel's ephemeral range, which means any process's ordinary outbound connection can randomly squat them as its source port — another app's Discord plugin once held one for three hours. Related: a WebKit crash can kill the GTK main thread while tokio threads live on, producing a "headless husk" that still holds the ports while single-instance detection thinks the app is gone.
Protocols lie too. Twitch's IRC (Internet Relay Chat)-over-WebSocket bridge silently drops your session if you send CAP, NICK and JOIN in one frame — no error, just an endless reconnect loop. Neither obs-websocket nor the client library sends any keepalive, so half-open connections stay "connected" forever; Switchboard hand-rolls a heartbeat and tests it against a fake OBS (Open Broadcaster Software) server that plays dead.
And the one that cost a day: cargo build --release does not produce a release Tauri app. Without the custom-protocol feature it still loads the Vite dev URL (Uniform Resource Locator) — which in CI (Continuous Integration) renders a blank webview that looks exactly like a rendering bug.
The ecosystem
Switchboard exposes a small external API (Application Programming Interface) (WebSocket events + commands), and two first-party satellites consume it: switchboard-ha, a HACS (Home Assistant Community Store)-installable Home Assistant integration that pushes every Switchboard event onto the HA (Home Assistant) bus (it lives on GitHub purely because HACS (Home Assistant Community Store) only installs from there), and an OpenDeck plugin for Stream Deck hardware.
Who is this for? Mainly me — I use it daily on two machines. But it's MIT (Massachusetts Institute of Technology) licensed, prebuilt for all three OSes, at gitlab.com/KirboDev/agentic-coding/switchboard. Fair warning: the macOS and Windows builds are unsigned, workarounds documented in the README.