Inspiration

IRC, created in 1988, gave the internet its first chat rooms. Most communities later moved to closed, account-based apps. For the Resurrection category we wanted to bring the open protocol back with modern tools.

What it does

  • A real IRC server on port 6667: classic clients such as Irssi, HexChat or WeeChat connect with NICK, USER and JOIN.
  • A browser client that joins the same channels with only a nickname. A message typed in the browser arrives as a real PRIVMSG line, and the other way around.
  • Ghost, a bot that is just another IRC user in the channel: !ask answers questions, !summary and !tldr read back recent history. The live demo runs Ghost with a built-in mock provider; any OpenAI-compatible API key can be plugged in.
  • Chat history is stored in SQLite.
  • Channel operators: the first user in a channel gets ops (shown with @), and ops can use MODE +o/-o and KICK. This was added by the Kiro task 5.2 run and is in the repo; the live demo still runs the earlier build.

How we built it

One Node.js + TypeScript process. TCP clients, WebSocket clients and Ghost all exchange parsed IRC messages through one ChatHub, so a browser user and an Irssi user see exactly the same channel. Runtime dependency: ws only; storage uses the built-in node:sqlite. Deployed with Docker on a VPS.

How Kiro was used

The repository has a /.kiro folder at its root with steering files (product, tech, structure, security), three specs (irc-core, web-client, ai-ghost, each with requirements, design and tasks) and hooks (type-check on save, run tests when the agent stops, and an optional protocol-review agent hook). The project is opened in the Kiro IDE, which shows the specs in its Requirements / Design / Task list view. Honest note: these .kiro files were drafted outside Kiro as a starting point, and tasks 1-4 are checked because that code already existed. We then ran spec task 5.2 (channel operators and KICK) for real in Kiro IDE 1.4.62 on the free plan with "Start task": in about 3 minutes the agent edited hub.ts, numerics.ts and hub.test.ts, adding ops with the @ prefix, MODE +o/-o and KICK with proper error numerics, plus 10 new tests; it ran npm test itself and all 51 tests passed. The hooks loaded in Kiro, but we did not observe the run-tests-on-stop hook firing, so we don't claim it ran. Details are in the README section "How Kiro was used".

Challenges we ran into

Keeping both worlds safe and identical: enforcing the 512-byte IRC line limit, stripping CR/LF/NUL, flood control for both TCP and WebSocket clients, and an Origin check on the WebSocket door.

Accomplishments that we're proud of

An unmodified 1988-style IRC session and a browser tab chatting in the same channel, with an AI participant both can talk to.

What we learned

How small and durable the IRC protocol is, and how far a single shared message hub goes.

What's next for Seance Relay Chat

Optional TLS listener on 6697 (spec task 5.1), deploying the new operator and KICK code to the live demo, and running Ghost on a real model.

Share this project:

Updates

Submission history