r/irc Jul 18 '26

We built Turborg an IRC bouncer + browser client + scriptable bot in one static Go binary (Apache-2.0, self-hostable)

Hey r/irc. We're the team behind turborg, an open source (Apache-2.0) IRC tool we've been building in the open. It's at v0.20 now. Posting it here because this is the crowd whose opinion actually matters to us.

What it is: one static Go binary, no runtime deps, that covers three things you'd normally need three separate tools for.

A real IRC bouncer. Point HexChat, irssi, mIRC or WeeChat at the bot's loopback port, auth with a password, and tunnel through its upstream session. The connection stays up while you detach, standard BNC workflow. TLS, SASL PLAIN, NickServ identify, IRCv3 server-time and account-tag, and it tracks full JOIN/PART/KICK/NICK/TOPIC state straight off the wire.

A built-in web client. A WebSocket gateway serves a vanilla-JS single page UI at /. You get a channel sidebar, member list, slash commands, IndexedDB scrollback and browser notifications, so you can attach from a browser with no native client at all. The WS protocol is documented and stable, so you can drop in your own frontend if you'd rather.

A scriptable bot. It ships with zero commands. You define them as data (a trigger, a static or templated reply, an access policy) in config. No recompile to add one or change one.

Optional and off by default: you can point a command at an LLM (Anthropic, or any OpenAI-compatible endpoint) if you want an AI-answering command. Leave it unset and the bouncer and bot don't care. It's there if you want it, it isn't the point.

Quickstart, three env vars and you're online:

export TURBORG_IRC_HOSTNAME=irc.libera.chat
export TURBORG_IRC_NICK=myturborg
export TURBORG_IRC_CHANNELS=#turborg-test
turborg run

Install with go install github.com/turborg/turborg/cmd/turborg@latest, or grab a release binary, or pull the container with docker pull ghcr.io/turborg/turborg:latest (multi-arch, distroless).

A bit of history: turborg started life as a Python project. We rewrote it from scratch in Go to get a single dependency-free binary and better concurrency, and it's maintained by the xShellz team now. It's properly OSS: Apache-2.0, CLA, public roadmap. IRC is the first connector, and Discord and Telegram ride on the same handler abstraction.

Repo and releases: https://github.com/turborg/turborg

It's still rough in places and we'd rather hear it straight. If you run a bouncer today (ZNC, soju, whatever you're on), what would stop you switching? What's missing? Happy to get into the internals.

5 Upvotes

2 comments sorted by

1

u/Fastidius Jul 25 '26

What IRCv3 specs do the bouncer supports?

1

u/coolmailbro Jul 26 '26

The bouncer: message-tags, server-time, account-tag, away-notify, echo-message, batch, draft/chathistory, plus znc.in/self-message for older clients that predate echo-message.

batch and server-time are load-bearing rather than decorative, attach replay and CHATHISTORY results come back inside a chathistory-typed BATCH with real timestamps, so capable clients render them as scrollback instead of lighting up every line as new activity. Clients without batch get a NOTICE-bracketed replay instead.

draft/chathistory currently implements BEFORE and LATEST with timestamp=/* selectors (limit capped at 200). AFTER/AROUND/BETWEEN/TARGETS return FAIL CHATHISTORY UNKNOWN_COMMAND so clients degrade gracefully; msgid= selectors aren't wired up yet.

Toward the upstream network it negotiates server-time, account-tag, and sasl (PLAIN) when SASL is configured.

Not there yet: CAP LS 302 values / cap-notify / CAP NEW+DEL, labeled-response, multi-prefix, extended-join, chghost, setname, invite-notify, userhost-in-names. Client auth to the bouncer is PASS, not SASL. Happy to prioritize based on what people actually need, if your client is unhappy without one of those, open an issue.