================================================================ One Frozen Gopher API, Native Clients from Mac OS 9 to Android 2026-07-19 · gopher, rust, retro-computing, mac-os-9, powerpc, spotify, protocols, self-hosted, homelab, objective-c, android, claude ================================================================ Here is the whole idea in one sentence: I control Spotify from a Mac OS 9 machine, over the Gopher protocol. [img: Casquinha on Mac OS 9.2 — now playing, search, and a queue, all driven over Gopher] This is a real System 9 desktop. The now-playing, the search, the queue — all of it is plain Gopher menus going to a box in my closet. That screenshot is the fun part. The load-bearing part is duller and more useful, and it's the reason a 2001 Power Mac and a 2024 Android phone can both talk to the same server without sharing a single line of code. The seam: a frozen text API =========================== A while back I put the live CTA 'L' trains on Gopher[2], and then that gopherhole grew a whole neighborhood[3] — a phlog, a tarot reader, a shared Rust core. The trains taught me something I keep re-learning: Gopher's constraint is the feature. A menu line is just type · label · selector · host · port. There is nowhere to hide a framework. So when I wanted to drive Spotify from old machines, I didn't build an app with an SDK. I built a machine-readable Gopher API — /spot/api/1 — and then I froze it. Ask for now-playing, get back a handful of keyvalue lines. Send a transport command as a selector. That's the entire contract, and it's written down as a client pattern in fhb[4] so future-me can't drift it. The backend (gopher-spot[5]) is a small Rust binary that geomyidae execs per connection. It holds the Spotify Connect session; audio flows separately as librespot → ffmpeg → Icecast, so the ancient clients just decode an MP3 stream. Credentials live in a chmod 600 file (or a Kubernetes Secret built straight from it) and never leave the box. The whole thing is LAN-only. No client ever sees a token. The payoff: writing a new client is a weekend, not a project. There's no OAuth, no SDK to port to a dead platform, no TLS stack to babysit. If your machine can open a TCP socket and read tab-separated text, it can be a Spotify remote. The clients: four platforms, ~24 years apart ============================================ So I wrote four native Gopher clients. Three of them double as Spotify remotes — the radinhos — and each one is written the way its era wanted, not the way 2026 wants: • Casquinha[6] — Mac OS 9.2, plain C99, Open Transport for the socket, minimp3 decoding the stream in-app, classic Toolbox UI. The oldest machine yet. (the build diary[7]) • DeGelato[8] — Mac OS X 10.5 on a Power Mac G5 (PowerPC, 32-bit), Cocoa/Objective-C with no ARC and no blocks, GCC 4.2, CoreAudio on the Icecast stream. • DeToca[9] — Mac OS X 10.6 (Snow Leopard), Cocoa/Objective-C again, plus a 256-color ANSI/braille renderer for the rest of gopherspace. • DeBurrow[10] — the modern bookend: an Android Gopher client in Kotlin + Compose. Here's DeGelato on the G5, driving the player and browsing gopher.debene.dev (the CTA map is in that black window) at the same time: [img: DeGelato on Sorbet Leopard: the player, a Gopher browser on gopher.debene.dev, and the live ANSI CTA train map] One backend, several windows: the same little server is serving now-playing to the player and menus to the browser. And because someone always asks "is that really running on the old hardware or is it a skinned VM?" — no, it's the real thing. Left is a Power Mac G5 (Sorbet Leopard themed to look like Sierra); right is a MacBook2,1 on genuine 10.6.8: [img: About This Mac on the real Power Mac G5 — Dual 1.8 GHz PowerPC G5] [img: About This Mac on the real MacBook2,1 — Mac OS X 10.6.8, Intel Core 2 Duo] The thing I find quietly satisfying: none of these clients know about each other, and the server doesn't know about any of them. They agree on /spot/api/1 and nothing else. A protocol from 1991 turns out to be a great lingua franca precisely because it's too dumb to have opinions. The rest of the neighborhood ============================ The Spotify bridge is one hole in a larger constellation[14], all on the same box, all cross-linked at the protocol level (a menu line on the front door just points at another port — no proxy, no ingress): • gopher-cta[15] — live Chicago 'L' trains as a Unicode-braille map. • gopher-askthedeck[16] — an interactive tarot reading[17] drawn against the actual sky. • gopher-blog[18] — this blog, rendered to a phlog. • gopher-core[19] — the shared Rust spine underneath them. Which sets up the kicker: you can read this exact post on Gopher. It flows through gopher-blog onto the phlog, so the write-up about a quiet protocol also lives on the quiet protocol — ---------------------------------------------------------------- gopher://gopher.debene.dev:7071 ---------------------------------------------------------------- If you've got a Gopher client handy (or one of these four you can now build), point it there. If you don't, that's the whole pitch, really: the internet still has a volume knob, and it turns down further than you'd think. Code's all on GitHub[20] — start with gopher-spot[21] for the backend or fhb[22] for the client pattern. Built in the open with Claude Code. ---------------------------------------------------------------- Links [1] https://debene.dev/posts/one-frozen-gopher-api/images/casquinha-os9.png (img: Casquinha on Mac OS 9.2 — now playing, search, and a queue, all driven over Gopher) [2] https://debene.dev/posts/gopher-cta-live-trains/ [3] https://debene.dev/posts/gopher-constellation-one-day/ [4] https://github.com/felipedbene/fhb [5] https://github.com/felipedbene/gopher-spot [6] https://github.com/felipedbene/casquinha [7] https://debene.dev/posts/casquinha-macos9/ [8] https://github.com/felipedbene/degelato [9] https://github.com/felipedbene/detoca [10] https://github.com/felipedbene/deburrow [11] https://debene.dev/posts/one-frozen-gopher-api/images/degelato-leopard.png (img: DeGelato on Sorbet Leopard: the player, a Gopher browser on gopher.debene.dev, and the live ANSI CTA train map) [12] https://debene.dev/posts/one-frozen-gopher-api/images/degelato-proof.png (img: About This Mac on the real Power Mac G5 — Dual 1.8 GHz PowerPC G5) [13] https://debene.dev/posts/one-frozen-gopher-api/images/detoca-proof.png (img: About This Mac on the real MacBook2,1 — Mac OS X 10.6.8, Intel Core 2 Duo) [14] https://debene.dev/posts/gopher-constellation-one-day/ [15] https://github.com/felipedbene/gopher-cta [16] https://github.com/felipedbene/gopher-askthedeck [17] https://debene.dev/posts/askthedeck-adhd/ [18] https://github.com/felipedbene/gopher-blog [19] https://github.com/felipedbene/gopher-core [20] https://github.com/felipedbene [21] https://github.com/felipedbene/gopher-spot [22] https://github.com/felipedbene/fhb ---------------------------------------------------------------- Read on the web: https://debene.dev/posts/one-frozen-gopher-api/ Back: /posts · Root: /