Do you remember IRC? Ever want to run your own server? I've wanted to write one since I first connected in 1988. I watched the fall of the USSR happen on IRC. I met my SO on IRC a year before I moved to Seattle. The protocol hasn't changed since 1993. The clients still work. Nobody is trying to enshittify it because there's nothing to monetize. I wrote this server in probably half an hour of wall time while doing other things, mass-producing code with Claude while the coffee got cold.
The prompt that started it:
"Do you think you could vibe together a complete and compliant IRC server in Go, just using the stdlib and well-known packages?"
Yes. Let's find out.
Why This Is Different
Every IRC server I've run has been someone else's code. ircd, ircd-hybrid, charybdis, inspircd. Configuration files I half-understood, behaviors I couldn't change without forking. This one is mine. I can read every line because I talked through every line.
Modern IRC means TLS only, UTF-8 by default, IRCv3 capability negotiation. Throw away the rest. The first version was one file, ~1,100 lines. Actor model with one goroutine per channel.
But the interesting part isn't the IRC compliance. It's federation.
Federation via Git
IRC servers traditionally find each other via static config or DNS. Manual, fragile, requires trust decisions made outside the protocol.
MeshIRCd servers poll a GitHub repo for their peers. Join the network: open a PR adding your server's hostname and Ed25519 pubkey. Revocation: delete the entry. Key rotation: coordinate in PR comments, then merge. Git history preserves who was there and when. PRs as trust decisions. Merge as deployment.
Server-to-server is TLS 1.3 with mutual auth, newline-delimited JSON, Lamport clocks for ordering. Conflicts resolved by (seq, origin) tuple, lower wins. Deterministic, no NTP trust needed.
Two protocols, sharp boundary: client-to-server is standard IRC (connect with irssi, weechat, Textual), server-to-server is ours. Your client doesn't know anything changed.
Optional Identity
Users can attach Decentralized Identifiers to their IRC presence. did:key:... is self-certifying, derived from a public key. did:web:example.com resolves to a DID document the server fetches. Challenge-response proves you control the key. Identity propagates across federation. Shows in WHOIS.
You don't have to use it. NickServ still works. But if you want cryptographic proof that you're you across every server in the mesh, it's there.
What I Hit
Apple's crypto stack is frozen circa 2018. macOS Secure Transport doesn't support Ed25519 TLS certificates. Fix: dual keys, ECDSA P-256 for TLS, Ed25519 for federation signing.
Clients query ban lists on join. Textual and irssi send MODE #channel b to get the ban list. Server was treating it as a mode change requiring op. One conditional to detect list-only queries.
Flood control is 15 lines. Token bucket, stdlib only.
The Conversation Pattern
This wasn't written from a spec. It was talked into existence. "What if servers found peers via GitHub?" Okay, what's the failure mode when GitHub is down? Work through it, decide, move on. "Can we solve ordering with some kind of crypto clock?" Lamport clocks. Does this break the IRC protocol? No, S2S is separate. Okay.
The conversation was the spec doc. 8,042 lines of Go across 8 source files. Four spec documents. Two repos: code and network.
Thirty-six years after I first typed /join, I finally have my own server. Connect at irc.reviewcommit.com. Start up a container and send me a PR to add your server to the network.
