Switchboard

On this page
  1. What it is
  2. Automations
  3. Now playing
  4. The division of labour
  5. What the memory files remember

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 streaming control hub built on Tauri 2: one tray-resident app driving OBS (Open Broadcaster Software), Twitch, Spotify, Discord and Home Assistant, with browser-source overlays and an event → action rules engine tying it together. Full feature tour, screenshots and architecture live on the project page.

Automations

The rules engine is what turns "control panel" into "automation," and the first rule I actually trusted was Song announcements: triggered on Spotify: Song changed, gated on Spotify is playing on This machine, it posts a templated Discord message. Building the template editor meant it had to prove itself live — type ♫ Now playing: {artists} — {title_no_feat}, watch it preview against whatever's actually spinning. Midnight City came on mid-build, and the preview showed the exact string about to post before the rule ever fired for real.

M83 — Midnight City, gated on This machine: the exact line about to post, previewed before the rule fires.

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.

M83 — Midnight City, 1:24 of 4:04.

The division of labour

The honest headline: the vast 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 + 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

The AppImage packaging bugs, the Twitch/OBS protocol quirks, the Linux port-squatting failure mode — the full technical detail on those now lives as engineering notes on the project page. One story earns its place here, because it's the cleanest argument for why the memory files exist at all.

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 renders a blank webview that looks exactly like a rendering bug. It cost a day the first time. Now it's one paragraph in a memory file, and it can never cost a day again.

twotter died because I could invent faster than I could build. Switchboard hasn't hit that wall — not because the idea list got any shorter, but because the bottleneck moved: planning, review and judgment are still entirely mine, and everything downstream of them just happens. That's the actual lesson, more than any single bug fix: agentic coding doesn't win because Claude writes code well, it wins because it changes which constraint you're optimizing for.