Wicket is a multi-user, multi-network IRC bouncer written in Python. It stays connected to IRC for you, stores history while you're away, and serves per-device backscroll to each client that reconnects.
- Multi-user, multi-network. One Wicket instance can host any number of users, each with any number of upstream networks.
- Per-device backscroll. Clients identify themselves with a name in the password string; Wicket tracks read positions per device, so each phone, laptop, or IRC client only replays what it hasn't seen yet.
- Persistent SQLite history. PRIVMSGs and NOTICEs are stored on disk
and survive restarts; on reconnect each device replays only the messages
it hasn't seen yet. Channel events (JOIN/PART/KICK/MODE/NICK/QUIT) are
also recorded and surfaced via opt-in
replay_activityor the on-demandACTIVITYcommand — delivered as text summaries (not real protocol events) so they don't desync your client's channel state. - Cascading configuration. Set defaults at the top level, override per
user, override again per network —
nick,realname, rate limits, capabilities, replay behavior, etc. - IRCv3 capability negotiation. Bouncer↔server and client↔bouncer cap
sets are negotiated independently. Capability-dependent message formats
(like
extended-join) are downgraded for clients that didn't request them. - SASL (PLAIN, EXTERNAL) for upstream authentication.
- TLS for both the listen socket and upstream connections (optional — plaintext is supported on either side if you'd rather terminate TLS elsewhere or just don't need it).
- Built-in ident server (RFC 1413) so you don't get the
~prefix on networks that check ident. - Per-server rate limiting to avoid Excess Flood disconnects.
- Auto-reconnect with multi-server failover.
- Live rehash. Reload the config file without dropping connections.
- In-band control. Manage the bouncer over IRC by messaging
*wicket. - Activity replay. Optionally replay channel JOINs/PARTs/KICKs/MODEs/ NICKs/QUITs that happened while you were away, with per-channel overrides.
-
Install dependencies:
pip install -r requirements.txt -
Copy and edit the example config:
cp config.example.yaml config.yamlAt minimum, set a user, a password, and one network.
-
Hash your password (recommended over plaintext):
python bouncer.py -c config.yaml --set-password Bob hunter2 -
Start the bouncer:
python bouncer.py -c config.yaml -
Point your IRC client at it. Use the password format below.
Configure your IRC client to connect to Wicket's host/port and send a server password in this format:
username[@clientname]/network:password
username— the user defined inconfig.yaml@clientname— optional device/client identifier for per-device backscroll. If you connect from mIRC as@mircand from your phone as@phone, each gets its own read position. Defaults to*if omitted.network— which configured network to attach topassword— the user's password (matched against the bcrypt hash or plaintext inconfig.yaml)
Examples:
Bob@laptop/libera:hunter2
Bob@phone/libera:hunter2
Bob/oftc:hunter2
To attach the same client to multiple networks, open one connection per network from your client.
Send these as a /msg *wicket <command> (or to your configured server_name
if delivery_source: server):
HELP— list available commandsSTATUS— connection status and client count for each networkLISTNETWORKS— list configured networksCONNECT <network>— connect (or reconnect) to a networkDISCONNECT <network>— cleanly disconnect from a networkSETPASSWORD <newpass>— change your password (bcrypt-hashed and saved)REHASH— reloadconfig.yamlfrom diskACTIVITY [#chan ...]— replay recent JOIN/PART/KICK/MODE/NICK/QUIT events from history
See DOCS.md for the full reference: configuration, cascading, per-device replay, IRCv3 caps, SASL, ident, deployment, and troubleshooting.
Note that currently the bouncer seems to have a bug where if joining channels is throttled due to 'target change too fast' (I get this on Undernet sometimes), and there's a number of channels in the line-up, it'll keep cycling through them one every couple of seconds and the target change wait time will never go down. It's hard to debug because I have to wait till I land on a server that has this join throttling again with the new log output enabled.
I think it also might have a bug where the client thinks it's in a channel named after your "real name" because Wicket is using an ircv3 "extended join" cap when the client doesn't support it, or something like that, even though Claude insists that the bug has been fixed. But it's not necessarily still a bug, I could have just still been caught in a cycle of clients and bouncers autojoining the "real name" channel because bouncer and client instances kept telling each other to join.
MIT