Clone the repository
January 13, 2026 ยท View on GitHub
#+TITLE: CLatter - A Common Lisp IRC Client #+AUTHOR: Glenn Thompson #+OPTIONS: toc:2
- CLatter
A terminal-based IRC client written in Common Lisp using the [[https://codeberg.org/McParen/croatoan][croatoan]] ncurses library.
** Features
- Multi-Network Support - Connect to multiple IRC networks simultaneously (e.g., Libera and OFTC)
- TLS Support - Secure connections to IRC servers
- SASL Authentication - PLAIN and EXTERNAL (client certificate) authentication
- Client Certificate Auth - Authenticate using TLS client certificates
- Auto-Reconnect - Automatic reconnection with exponential backoff
- Connection Health Monitoring - Detects stale connections and reconnects
- Nick Colorization - Each nick gets a consistent color based on hash
- Nick Highlighting - Messages mentioning your nick are highlighted
- Tab Completion - Press Tab to complete nicks in the current channel
- Nick List Panel - Toggle channel member list with =Ctrl-O=
- Input Scrolling - Long input lines scroll horizontally to keep cursor visible
- Readline Keybindings - Emacs-style cursor movement (Ctrl-A/E/B/F)
- Autojoin Management - Channels are auto-added to autojoin on
/join - Multi-buffer Interface - Server, channel, and query buffers grouped by network
- Command History - Up/Down arrows to navigate input history
- Scrollback - Ctrl-U/D to scroll through message history
- Split-Pane View - View two channels side-by-side with =Ctrl-W=
- CTCP Support - Responds to VERSION, PING, TIME requests
- DCC Support - Direct client-to-client chat and file transfers
- Message Logging - Automatic logging to =~/.local/share/clatter/logs/=
- Log Search - Search through message history with
/log search - CrafterBin Integration - Upload files to pastebin with
/crafterbin - IRCv3 Capabilities - server-time, away-notify, multi-prefix, account-notify, typing, batch, chathistory, labeled-response, MONITOR
- Channel Modes Display - Shows channel modes and your status (@/+) in status bar
- Ignore List - Hide messages from specific users with
/ignore - Away Status - Set away status with
/away - Secure Password Storage - Support for authinfo.gpg, systemd-creds, and pass(1)
- Theming - Multiple built-in themes (dark, light, solarized, minimal, ascii, rounded) with
/theme - Message Search - Search buffer history with
/search - Message Filtering - Filter displayed messages with
/filter - URL Detection - Automatically tracks URLs in chat, open with
/url
** Requirements
- SBCL (Steel Bank Common Lisp)
- Quicklisp
- ncurses development libraries
- curl (for
/crafterbinuploads) - One of the following for clipboard support (optional):
- =xclip= (X11)
- =xsel= (X11)
- =wl-clipboard= (Wayland)
** Installation
#+begin_src bash
Clone the repository
git clone https://github.com/yourusername/CLatter.git cd CLatter
Build
make clean && make #+end_src
** Usage
#+begin_src bash ./clatter #+end_src
On first run, you'll be prompted for a nickname and connected to Libera.Chat.
*** Quick Start
- Launch CLatter: =./clatter=
- Join a channel: =/join #channel=
- Send messages: Just type and press Enter
- Switch buffers: =Ctrl-P= (previous) / =Ctrl-N= (next)
- Scroll history: =Ctrl-U= / =Ctrl-D=
- Tab-complete nicks: Start typing a nick and press =Tab=
- Quit: =/q= or =F10=
*** Tips
- If the display looks corrupted, press =Ctrl-L= to refresh
- Use =Ctrl-W= to toggle split-pane view for monitoring two channels
- Messages mentioning your nick are highlighted
- Logs are saved to =~/.local/share/clatter/logs/=
** Configuration
Configuration is stored in =~/.config/clatter/config.lisp=
Example: #+begin_src lisp (:clatter-config :version 1 :default-network nil :time-format "%H:%M:%S" :buflist-width 28 :networks ((:name "libera" :server "irc.libera.chat" :port 6697 :tls t :nick "yournick" :username nil :realname "Your Name" :password nil :nickserv-pw "your-password" :sasl :plain :autojoin ("#lisp" "#emacs") :autoconnect t))) #+end_src
*** UI Options
- =:time-format= - Format string for timestamps (default: ="%H:%M"=)
- =:buflist-width= - Width of the buffer list panel in characters (default: =28=). Reduce this for smaller terminal windows.
*** SASL Authentication
SASL authenticates you before your connection is visible, so your IP/hostname is cloaked from the start.
**** SASL PLAIN (password-based)
- You must have a registered nick with NickServ
- Add =:sasl :plain= to your network config
- Ensure =:nickserv-pw= contains your NickServ password (or use =:authinfo=)
**** SASL EXTERNAL (certificate-based) - UNTESTED
More secure - uses a client certificate instead of a password.
-
Generate a certificate: #+begin_src bash openssl req -x509 -new -newkey rsa:4096 -sha256 -days 3650 -nodes
-keyout ~/.config/clatter/clatter.key -out ~/.config/clatter/clatter.crt
-subj "/CN=YourNick" cat ~/.config/clatter/clatter.crt ~/.config/clatter/clatter.key > ~/.config/clatter/clatter.pem #+end_src -
Register the certificate with NickServ (connect with password first): #+begin_example /msg NickServ CERT ADD #+end_example
-
Update your config: #+begin_src lisp (:name "libera" :server "irc.libera.chat" :nick "yournick" :sasl :external :client-cert "/home/you/.config/clatter/clatter.pem" ...) #+end_src
-
You can now remove =:nickserv-pw= - the certificate handles authentication
*** Password Storage Options
CLatter supports multiple methods for storing passwords securely. These options work for both =:nickserv-pw= (NickServ/SASL password) and =:password= (server password).
**** Plain Text (not recommended)
Store the password directly in the config file:
#+begin_src lisp :nickserv-pw "your-password" #+end_src
**** Authinfo (GPG encrypted)
Use =/.authinfo= or =/.authinfo.gpg= (encrypted with GPG):
#+begin_src lisp :nickserv-pw :authinfo #+end_src
Then add an entry to your =~/.authinfo.gpg= file: #+begin_example machine irc.libera.chat login yournick password your-secret-password #+end_example
CLatter will decrypt the file using GPG and look up the password by matching the server and nick.
**** systemd-creds (encrypted with TPM/host key)
Use =systemd-creds= to create a system credential to encrypt your password. This ties the credential to your machine and doesn't require GPG. This requires root privlages.
-
Create the encrypted credential: #+begin_src bash mkdir -p ~/.config/clatter/creds read -s -p "Enter NickServ password: " pw && echo -n "$pw" |
systemd-creds encrypt - ~/.config/clatter/creds/nickserv.cred &&
echo -e "\nCredential saved" #+end_src -
Update your config: #+begin_src lisp :nickserv-pw (:systemd-cred "/home/you/.config/clatter/creds/nickserv.cred") #+end_src
CLatter will decrypt the credential file at startup using =systemd-creds decrypt=.
**** pass(1) (GPG encrypted) Use =pass(1)= the standard unix password manager, to store and encrypt your password. This works using GPG and the credential is portable.
-
Install pass using your package manager of choice (see [[https://www.passwordstore.org/][website]] for supported platforms).
-
Generate a password =pass generate=
-
Update your config: #+begin_src lisp :nickserv-pw (:pass "password-name") ; where password-name is the name of the file in pass(1) #+end_src
**** Server Password
If your IRC server requires a connection password (separate from NickServ), use the =:password= field with any of the above methods:
#+begin_src lisp :password (:systemd-cred "/home/you/.config/clatter/creds/server.cred") #+end_src
Or with authinfo/plain text: #+begin_src lisp :password :authinfo :password "plain-text-password" #+end_src
** Commands
| Command | Description |
|------------------------------+------------------------------------------|
| /join #channel [key] | Join a channel (auto-adds to autojoin) |
| /part [#channel] [msg] | Leave channel, remove from autojoin |
| /leave [#channel] [msg] | Alias for /part |
| /close | Close current buffer (use after /part) |
| /autojoin | List autojoin channels |
| /autojoin add #channel | Add channel to autojoin |
| /autojoin remove #channel | Remove channel from autojoin |
| /msg target text | Send private message |
| /me action | Send action to current channel |
| /nick newnick | Change nickname |
| /quit or /q [message] | Disconnect and exit |
| /ns command | Send to NickServ |
| /cs command | Send to ChanServ |
| /query nick | Open query with user |
| /whois nick | Query user information |
| /topic [text] | View or set channel topic |
| /kick nick [reason] | Kick user from channel (requires op) |
| /ban mask | Ban a hostmask from channel (requires op)|
| /mode [+/-modes] [args] | Set channel or user modes |
| /ctcp nick command | Send CTCP request (VERSION, PING, TIME) |
| /log | View recent logs for current buffer |
| /log search pattern | Search logs for pattern |
| /log list | List all logged targets |
| /log export [text/json/html] | Export logs to file |
| /dcc chat nick | Initiate DCC chat with user |
| /dcc send nick file | Send file via DCC |
| /dcc accept [id] | Accept pending DCC offer |
| /dcc reject [id] | Reject pending DCC offer |
| /dcc list | List DCC connections |
| /dcc close [id] | Close DCC connection |
| /crafterbin file | Upload file to CrafterBin pastebin |
| /ignore [nick] | List ignored or toggle ignore for nick |
| /unignore nick | Remove nick from ignore list |
| /away [message] | Set away status (no message = back) |
| /back | Clear away status |
| /history [count] | Request chat history (if server supports)|
| /invite nick [#channel] | Invite user to channel |
| /names [#channel] | Refresh channel member list |
| /monitor + nick1,nick2 | Add nicks to monitor list |
| /monitor - nick1,nick2 | Remove nicks from monitor list |
| /monitor l | List monitored nicks |
| /monitor s | Check status of monitored nicks |
| /monitor c | Clear monitor list |
| /list [pattern] | List channels on server |
| /who target | Query user/channel info |
| /raw line | Send raw IRC command |
| /theme [name] | List themes or switch theme |
| /search pattern | Search current buffer for messages |
| /filter pattern | Show only messages matching pattern |
| /unfilter | Clear message filter |
| /url [N\vert{}list] | Open Nth recent URL or list URLs |
| /help | Show help |
** Keybindings
| Key | Action | |-------------+---------------------------| | Tab | Nick completion | | Up/Down | Input history | | Ctrl-U/D | Scroll chat history | | Ctrl-P/N | Previous/Next buffer | | Ctrl-A | Move to start of line | | Ctrl-E | Move to end of line | | Ctrl-B | Move cursor back | | Ctrl-F | Move cursor forward | | Ctrl-L | Refresh/redraw screen | | Backspace | Delete character | | Enter | Send message/command | | Ctrl-W | Toggle split pane | | Ctrl-T | Toggle split orientation | | Ctrl-L | Force redraw | | Ctrl-R | Set right pane buffer | | Ctrl-X | Swap panes | | F10 | Quit |
** CrafterBin Integration
CLatter includes built-in support for uploading files to [[https://crafterbin.glennstack.dev][CrafterBin]], a simple pastebin service.
#+begin_src /crafterbin /path/to/file.txt #+end_src
This will:
- Upload the file to CrafterBin
- Copy the resulting URL to your clipboard (requires =xclip=, =xsel=, or =wl-copy=)
- Display the URL in the chat buffer
Useful for quickly sharing code snippets, logs, or configuration files in IRC channels.
** License
MIT
** Acknowledgments
- [[https://codeberg.org/McParen/croatoan][croatoan]] - ncurses bindings for Common Lisp
- Libera.Chat IRC network