Start
How it works
One Bun process, one SQLite file and one ZNC. Zircon is the OAuth server for ChatGPT, a GitHub sign-in for people, and a ZNC administrator behind both.
The pieces
- Zircon
-
A Bun HTTP service on
127.0.0.1:3000. It serves the MCP endpoint, OAuth discovery, the sign-in and settings pages, the admin invite endpoint and the IRC API. A reverse proxy (HAProxy on the reference host) supplies public HTTPS. - ZNC
-
One ZNC process holds an account and network per Zircon user, plus a
dedicated administrator account (
zirconctlby default) with thecontrolpanelmodule. ZNC keeps the upstream IRC connections and their buffers. - SQLite
-
zircon.sqliteunder/var/lib/zirconholds users, GitHub identities, browser and agent sessions, hashed OAuth tokens, settings, channel history and the post audit. Zircon also writes a consistent copy underbackup/on startup and daily for whole-disk snapshots.
Identities
There are three, and Zircon keeps them separate.
| identity | who issues it | what it is for |
|---|---|---|
| GitHub account | GitHub | proving who a person is when they sign in |
| Zircon OAuth token | Zircon | letting a registered MCP client act for that person, scoped to
irc:read and irc:write and bound to this
server |
| ZNC account | Zircon, through controlpanel |
that person’s own IRC connection, nick and buffers |
Zircon binds a GitHub user’s numeric ID on their first sign-in, so a
renamed GitHub login stays attached to the same Zircon user. Each user’s
ZNC password is derived with HMAC-SHA256 from the host secret
ZNC_USER_SECRET and the stable Zircon user ID, so Zircon
never stores it.
Rotating ZNC_USER_SECRET changes every derived ZNC
password. Do not rotate it without a migration.
Provisioning without restarts
When a user saves /settings, or first uses the API,
Zircon logs into ZNC as the administrator and uses
controlpanel to create or update that user’s account and
network: server, nick, real name
(Zircon ChatGPT bridge for <GitHub login> by default)
and enabled channels. Zircon reconnects that ZNC network so IRC sees a
changed real name. It then runs SaveConfig. ZNC must run
with mutable = true so that saved configuration survives a
restart; Deployment covers the one-time
migration.
Zircon then attaches to the user’s ZNC account as an IRC client and
stores timestamped channel activity in SQLite. One human user has one
ZNC presence shared by all their agents. Each agent obtains its own
mailbox session from see_account_information and can
acknowledge unread activity without moving another agent’s cursor.
read_history also supports recent and last-hour reads that
do not touch any cursor. go_offline disconnects the human
account for every agent; go_online reconnects it. ChatGPT’s
event host can separately subscribe a chat to signed nick-mention
callbacks while the account stays online. Public onboarding remains
planned.
Channels: granted, then enabled
The owner lists the channels Zircon may ever offer
(ircChannels). An invitation grants a user some of those.
New accounts start with no enabled channels; the user selects them for
ChatGPT in /settings. Saving adds or removes those channels
in the user’s ZNC network immediately. Re-inviting preserves selections
that remain allowed and leaves new grants off. The API only reads and
posts in enabled channels.
Limits
- 16 users by default (
maxUsers, up to 100). The reference host has 1 GB of RAM shared with other services. - Messages are one line, 1 to 400 characters.
- 20 posts per user per minute; reads return up to 200 lines.
- 60 posts per network per minute. History defaults to 7 days or 5000 entries per user and channel.
- Request bodies are capped at 4 KiB.