ircbits.com

Docs / IRC bots: from eggdrop to your first ten lines of Python

IRC bots: from eggdrop to your first ten lines of Python

Updated June 4, 2026

Half of IRC's character comes from its bots: channel guards, loggers, quiz games, URL-title fetchers, bridges to other platforms. And because the protocol is plain text over a socket, writing one remains the classic weekend project.

The established bot software

eggdrop is the ancestor — running since 1993, scriptable in Tcl, still maintained, still guarding channels whose founders have grandchildren.

Limnoria (the maintained fork of Supybot) is the Python plugin framework: dozens of stock plugins, sane permissions, the sensible default if you want a capable channel bot without writing everything yourself.

Sopel is the lighter Python alternative, popular for simple utility-and-fun bots.

Matterbridge, while not only an IRC bot, is the standard answer for bridging an IRC channel with Discord, Matrix, Slack and others.

The rules changed: bot etiquette now has teeth

The old etiquette — ask the channel operators before bringing a bot — has been hardening into policy. Libera.Chat's 2026 policy update made operator permission a requirement, not a guideline, with particular attention to LLM-driven bots joining channels uninvited. The practical rules:

  • Get op permission before your bot joins any channel you do not run.
  • Mark it as a bot — set IRCv3 bot mode so clients and the network can tell.
  • Never let it respond to everything. Prefix-triggered commands only; nothing that talks unprompted.
  • Rate-limit your sends or the server will do it for you, with prejudice.

A minimal bot in Python

Ten lines to understand everything; libraries like irc or Limnoria for anything real:

import socket

s = socket.create_connection(("irc.libera.chat", 6667))
s.sendall(b"NICK demobot\r\nUSER demobot 0 * :demo bot\r\n")
buf = b""
while True:
    buf += s.recv(4096)
    while b"\r\n" in buf:
        line, buf = buf.split(b"\r\n", 1)
        if line.startswith(b"PING"):
            s.sendall(line.replace(b"PING", b"PONG") + b"\r\n")
        elif b" 376 " in line:                      # end of MOTD
            s.sendall(b"JOIN #demobot-test\r\n")

That is the whole protocol dance: register, answer PINGs, join. (For real use: TLS on port 6697 and SASL — the plaintext port is for one-evening experiments.) Send a message with PRIVMSG #channel :hello.

Ideas that channels actually appreciate

Loggers (with the channel's consent), build/CI notifiers for project channels, URL title fetchers, factoid bots ("!faq install"), and games — trivia bots have kept channels alive for twenty years. Whatever you build, test it in your own channel first; #demobot-test exists for a reason, and so does the etiquette article.