An IRCv3-compliant IRC client for Emacs
Find a file
Trevor Arjeski 2369e80459
fix(model): give double quotes punctuation syntax
- unmatched quotes in scrollback made syntax-ppss see the input line
  inside a string, so electric-pair-mode inserted a spurious pair
  when typing a closing double quote
- text-mode-style punctuation syntax fixes pairing and skip-over
2026-09-16 12:24:28 +00:00
.github/workflows ci: use HTTPS for Melpazoid MELPA archive 2026-06-28 07:18:28 +03:00
images Add screenshot to README 2026-05-02 16:21:36 +01:00
recipes Add MIT license headers, MELPA recipe; prep 0.1.0 2026-06-13 10:44:25 +03:00
tests Merge pull request #132 from bergheim/fix/inline-timestamp-wrap 2026-09-16 15:23:47 +03:00
.envrc fix(history): restore seen message playback 2026-07-29 18:27:22 +00:00
.gitignore clatter.el - An IRCv3 Client for Emacs 2026-04-30 11:13:17 +01:00
clatter-actions.el fix(replies): render correct parent context 2026-09-02 12:11:15 +00:00
clatter-cap.el fix(sasl): refuse SASL PLAIN on plaintext connections 2026-08-23 00:08:23 +03:00
clatter-chathistory.el Add chathistory targets browser 2026-09-15 07:51:00 +00:00
clatter-commands.el fix(ui): regroup messages when fools toggle 2026-09-03 07:47:26 +00:00
clatter-completion.el feat(commands): add /whoami command 2026-08-28 17:28:06 +00:00
clatter-config.el feat(ui): merge inline and divider timestamps 2026-08-28 06:46:13 +00:00
clatter-connection.el fix(sasl): refuse SASL PLAIN on plaintext connections 2026-08-23 00:08:23 +03:00
clatter-dcc.el fix(dcc): strip directory components from sender filenames 2026-08-23 00:04:28 +03:00
clatter-evil.el fix(feed): rename and harden aggregate feed 2026-08-28 06:53:24 +00:00
clatter-feed.el fix(feed): rename and harden aggregate feed 2026-08-28 06:53:24 +00:00
clatter-format.el feat(input): render IRC formatting while editing 2026-09-03 06:35:08 +00:00
clatter-handlers.el fix(connection): re-establish after suspend and clarify disconnect messages 2026-08-16 15:36:10 +00:00
clatter-hl-nicks.el feat(ui): link quoted Elisp symbols 2026-08-23 19:54:35 +00:00
clatter-image.el fix(security): restrict curl scheme and redirects in remote fetchers 2026-08-23 00:09:03 +03:00
clatter-list.el Merge pull request #44 from fmqa/clatter-list-fixes 2026-06-28 09:30:17 +03:00
clatter-log.el fix(notice): route query NOTICEs to the sender's buffer 2026-07-30 11:37:30 +00:00
clatter-model.el fix(model): give double quotes punctuation syntax 2026-09-16 12:24:28 +00:00
clatter-nicklist.el feat(nicklist): follow the selected channel 2026-08-25 17:52:15 +02:00
clatter-notify.el notify: Focus the frame containing the buffer after popping it 2026-07-14 06:38:11 +02:00
clatter-org.el refactor(org): remove dead parse block in export-log 2026-08-21 16:53:19 +00:00
clatter-pals.el faces: inherit font-lock-doc-face instead of shadow 2026-08-05 19:29:58 +00:00
clatter-protocol.el refactor(protocol): inline tagged-notice helper 2026-08-21 17:03:02 +00:00
clatter-rawlog.el refactor(rawlog): remove unused original-send var 2026-08-21 16:54:15 +00:00
clatter-read-marker.el feat(ui): configure typing indicator placement 2026-08-25 09:13:41 +00:00
clatter-sasl-scram.el Address MELPA review feedback; make loading side-effect free 2026-06-15 07:42:15 +03:00
clatter-search.el refactor(search): alias visit-result-other-window to visit-result 2026-08-21 17:01:27 +00:00
clatter-smart.el smart: Simplify code 2026-07-14 05:24:36 +02:00
clatter-socks.el Address MELPA review feedback; make loading side-effect free 2026-06-15 07:42:15 +03:00
clatter-soju.el fix(soju): resolve bouncer password for fan-out children 2026-08-22 23:45:52 +03:00
clatter-sts.el Address MELPA review feedback; make loading side-effect free 2026-06-15 07:42:15 +03:00
clatter-track.el fix(track): clarify clatter buffer mode-line option 2026-08-24 12:29:16 +00:00
clatter-ui.el Merge pull request #132 from bergheim/fix/inline-timestamp-wrap 2026-09-16 15:23:47 +03:00
clatter-url-preview.el fix(replies): render correct parent context 2026-09-02 12:11:15 +00:00
clatter.el fix(feed): rename and harden aggregate feed 2026-08-28 06:53:24 +00:00
GUIDE.org Merge pull request #133 from bergheim/docs/feed-timestamp-readme 2026-09-16 15:24:03 +03:00
LICENSE MELPA prep: package-lint clean, add LICENSE, fix headers 2026-05-06 10:33:33 +01:00
Makefile docs: document SOCKS5/Tor proxy support; add test-socks target 2026-06-14 08:36:42 +00:00
manifest.scm fix(history): restore seen message playback 2026-07-29 18:27:22 +00:00
README.org Merge pull request #133 from bergheim/docs/feed-timestamp-readme 2026-09-16 15:24:03 +03:00

clatter.el

clatter.el - An IRCv3 Client for Emacs

A dedicated, fully IRCv3-compliant IRC client for Emacs. Pure Elisp, no Emacs Lisp dependencies. Buffer per channel, newest message at the top with the input prompt above it, and multi-network support out of the box.

Spiritual successor to CLatter (the Common Lisp TUI client), redesigned from scratch for Emacs.

Full reference: GUIDE.org - slash commands, keybindings, every user option, and the details of SASL, bouncers, proxies and troubleshooting.

/glenn/clatter.el/media/branch/master/images/screenshot.png

Requirements

Requirement Notes
Emacs 30.1+ No Emacs Lisp dependencies
GnuTLS Needed for TLS connections; check (gnutls-available-p)
curl Runtime, for async URL title and image fetching

Most Emacs builds ship with GnuTLS support. If yours does not:

Platform Install
Debian / Ubuntu apt install gnutls-bin libgnutls28-dev
Fedora / RHEL dnf install gnutls
Arch pacman -S gnutls
macOS (Homebrew) brew install gnutls

Installation

From MELPA

clatter is available on MELPA. Add MELPA to your archives if you have not already, then M-x package-install RET clatter RET:

(require 'package)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)

Manual (from source)

(add-to-list 'load-path "~/path/to/clatter.el")
(require 'clatter)
(require 'gnutls)
(clatter-setup)

clatter-setup

Loading clatter has no side effects: it installs no global hooks and enables no features. Call clatter-setup once from your configuration to install the disconnect and exit cleanup handlers and to turn on the bundled extras. Each extra is gated by its own option, so set anything you want to change before calling it:

Extra Option Default
Activity tracking clatter-track-enabled on
Desktop notifications clatter-notify-enabled on
Chat history clatter-chathistory-enabled on
Read markers clatter-read-marker-enabled on
soju bouncer fan-out clatter-soju-enabled on
Channel logging clatter-log-enable off
URL title preview clatter-url-preview-enable off
All-channels feed clatter-feed-enabled off

Quick Start

(setopt clatter-networks
        '(("libera"
           :server "irc.libera.chat"
           :port 6697
           :tls t
           :nick "yournick"
           :autojoin ("#emacs" "#commonlisp"))))
(clatter-setup)

Then M-x clatter and pick libera. To try clatter without configuring anything, M-x clatter-quick-connect prompts for a server and nick.

Everything else is a defcustom in the clatter group, so M-x customize-group RET clatter RET is always the complete option list.

Configuration

Libera.Chat with SASL

Register your nick with NickServ first, then put the account password in ~/.authinfo.gpg and leave :password out of the config:

machine irc.libera.chat login yournick port 6697 password yourpassword
(use-package clatter
  :ensure t
  :bind (:map clatter-mode-map
              ("C-c ."   . clatter-track-switch)
              ("C-c :"   . clatter-track-list)
              ("C-c n"   . clatter-nicklist-toggle))
  :custom
  (clatter-networks
   '(("Libera.Chat"
      :server "irc.libera.chat"
      :port 6697
      :tls t
      :nick "yournick"
      :realname "Your Name"
      ;; 'plain, 'scram-sha-256 or 'external (see GUIDE.org for CertFP)
      :sasl plain
      :autojoin ("#emacs" "#commonlisp" "#systemcrafters"))
     ("OFTC"
      :server "irc.oftc.net"
      :nick "yournick"
      :realname "Your Name"
      :autojoin ("#debian"))))
  :config
  (require 'gnutls)
  (clatter-setup))

soju bouncer

One entry connects to the bouncer and fans out into a separate connection per upstream network. :bouncer t with a bare :username makes this a control connection: clatter negotiates soju.im/bouncer-networks, runs BOUNCER LISTNETWORKS, and spawns one child connection per network the bouncer knows about, each named after that network.

(use-package clatter
  :ensure t
  :custom
  (clatter-networks
   '(("soju"
      :server "soju.example.com"
      :port 6697
      :tls t
      :nick "yournick"
      ;; Bare bouncer username: fans out to every upstream network.
      :username "sojuuser"
      :sasl plain
      :bouncer t)))
  :config
  (require 'gnutls)
  (clatter-setup))

To bind a single upstream network instead, use the user/network username form and no fan-out happens:

'(("soju-libera"
   :server "soju.example.com" :port 6697 :tls t
   :nick "yournick" :username "sojuuser/libera"
   :sasl plain :bouncer t))

Notes:

  • :autojoin is deliberately not propagated to child connections - soju replays your saved JOINs upstream-side.
  • :bouncer t also suppresses NickServ auto-identify and nick reclaim, since the bouncer owns that identity.
  • The bouncer password is looked up under either the network name (soju) or the server hostname; see GUIDE.org for the exact auth-source matching rules, which differ from a direct connection.

Everything on

Every optional extra enabled at once, as a starting point to trim down:

(use-package clatter
  :ensure t
  :custom
  (clatter-networks
   '(("Libera.Chat"
      :server "irc.libera.chat" :port 6697 :tls t
      :nick "yournick" :sasl plain
      :autojoin ("#emacs"))))
  ;; Off by default - turn them on.
  (clatter-log-enable t)                  ; log to ~/.emacs.d/clatter/logs/
  (clatter-url-preview-enable t)          ; fetch and show URL titles
  (clatter-feed-enabled t)                ; *clatter-feed* live inbox of all channels
  (clatter-feed-hide-visible t)           ; hide sources you already have open
  (clatter-feed-hide-channels '("#bots")) ; denylist, all networks
  (clatter-image-enable t)                ; inline images (GUI frames only)
  (clatter-rawlog-enabled t)              ; raw protocol inspector buffers
  ;; Tweaks to the on-by-default features.
  (clatter-track-show-in-clatter-buffers t) ; activity crumbs in every buffer
  (clatter-notify-keywords '("emacs" "lisp"))
  (clatter-notify-rules '((:target "#emacs" :level mentions :schedule (9 . 22))
                          (:target "#bots"  :level none)))
  (clatter-compact-system-messages 'compact) ; terse joins/parts/quits
  (clatter-group-messages-by-nick t)       ; show a nick once per burst
  (clatter-group-messages-gap 0.2)          ; slight space between bursts (GUI)
  ;; Fixed typing row keeps activity crumbs from shifting.
  (clatter-typing-indicator-location 'input-separator)
  (clatter-track-shorten 4)                ; e.g. #systemcrafters -> #syst
  (clatter-timestamp-format "%H:%M:%S")
  (clatter-timestamp-side 'inline)         ; end of line; also left/right/divider
  (clatter-timestamp-interval 5)           ; minute marks every 5 minutes
  (clatter-sender-format "[%nick]")        ; nick prefix, e.g. [alice] hey
  :config
  (require 'gnutls)
  (clatter-setup)
  ;; Not wired into clatter-setup - enable explicitly.
  (clatter-dcc-setup)
  (with-eval-after-load 'org
    (require 'clatter-org)
    (clatter-org-setup)))

Features

Feature Module Enabled by
IRC protocol (RFC 1459/2812), multi-network clatter-protocol always
IRCv3 CAP LS 302, message tags, batch, labels clatter-cap always
SASL PLAIN, SCRAM-SHA-256, EXTERNAL (CertFP) clatter-cap :sasl per network
TLS, client certificates, reconnect with backoff clatter-connection :tls per network (default on)
STS - auto-upgrade plaintext to TLS clatter-sts clatter-sts-enable (on)
SOCKS5 / Tor proxy, remote DNS, .onion clatter-socks :proxy / :tor t per network
soju bouncer fan-out, one buffer set per network clatter-soju :bouncer t + clatter-soju-enabled (on)
CHATHISTORY backlog; window-wide playback dividers clatter-chathistory clatter-chathistory-enabled (on)
Read markers (MARKREAD) synced across clients clatter-read-marker clatter-read-marker-enabled (on)
Mode-line activity tracking, unread counts, mentions clatter-track clatter-track-enabled (on)
Desktop notifications with per-channel rules clatter-notify clatter-notify-enabled (on)
Nick colorization (theme faces) + clickable URLs clatter-hl-nicks clatter-hl-nicks-enabled (on)
Incoming and editable mIRC formatting clatter-format on (C-c C-f while editing)
Completion for nicks, /commands, #channels clatter-completion always (TAB, standard CAPF)
Message action menu at point clatter-actions always (C-c C-a)
Smart noise filtering by signal-to-noise ratio clatter-smart clatter-smart-enabled (on)
Non-destructive message suppression clatter-ui clatter-suppress-messages, /suppress
Pals, fools and ignore lists (glob patterns) clatter-pals clatter-pals, clatter-fools, /ignore
Reply threads and emoji reactions (draft/react) clatter-ui always (/reply, /react)
Channel list browser clatter-list /list
Nick list sidebar clatter-nicklist clatter-nicklist-toggle
All-channels feed; hide visible or listed clatter-feed clatter-feed-enabled (off)
Inline / divider timestamp sides, mark interval clatter-ui clatter-timestamp-side, clatter-timestamp-interval
Channel logging to file, daily rotation clatter-log clatter-log-enable (off)
Full-text search across logs clatter-search /search (requires logging)
URL title preview clatter-url-preview clatter-url-preview-enable (off)
Inline image preview (GUI frames) clatter-image clatter-image-enable (off)
Raw protocol inspector clatter-rawlog clatter-rawlog-enabled (off)
DCC file transfer (XDCC receive, resume) clatter-dcc (clatter-dcc-setup)
Org links, capture templates, log export clatter-org (clatter-org-setup)

Keybindings

clatter binds no global keys. Inside a chat buffer RET sends, TAB completes, M-p / M-n walk the input history, C-c C-f applies IRC formatting and C-c C-a opens the action menu. The full default keymaps, plus Evil and vanilla binding examples, are in GUIDE.org.

Companion Packages

  • emojify - emoji rendering in messages (recommended)
  • corfu / vertico - completion UI for nick, command and channel completion
  • orderless - flexible completion matching
  • consult - consult-buffer integration via clatter-track (narrow with i)

Contributors

Thanks to the people who have contributed to clatter.el:

  • fmqa (F. Magsarian) - non-destructive message suppression, smart noise filtering, input history, WHOIS numerics, buffer cleanup hooks, CTCP ACTION/NOTICE consolidation with server-time, stricter mention matching, error numeric display, AWAY status broadcast, channel list robustness, keymap consolidation
  • trevarj (Trevor Arjeski) - SOCKS5 / Tor proxy support, auth-source server password lookup, left-side timestamps, message filling, fool visibility toggling, theme-aware faces

License

MIT