# Efinger for Emacs A client for the [Finger protocol](https://www.rfc-editor.org/rfc/rfc1288.html) (RFC 1288) with an [Elfeed](https://github.com/skeeto/elfeed)-inspired reader for Emacs. ## How it works ``` Emacs Finger servers (TCP 79) +---------------------+ | *efinger* | n / p +----------------------+ | ------------------ |------ move -->| happynetbox.com | | >random@happynetbox | | thebackupbox.net | | Carmack diary | RET / l | your own fingerd | | ring@thebackupbox |<-- enter/back | | +----------+----------+ +----------+-----------+ | | v preview | async, :nowait +---------------------+ | | *efinger .plan* |<-------------------------+ | the fingered text | +---------------------+ ``` 1. You keep a list of finger accounts in `efinger-accounts`. 2. `M-x efinger` opens the account list next to a content pane. 3. Moving with `n` / `p` fingers the account under point and previews its `.plan` in the other pane, asynchronously so Emacs never blocks. 4. `RET` jumps into the content, `l` goes back to the list, `q` closes both panes. ## Buffers ### Account list + content (`M-x efinger`) ``` Efinger — n/p move · RET open · g refresh · q quit ┌────────────────────────┬───────────────────────────────────────┐ │ random@happynetbox.com │ johnc@idsoftware.com │ │ Carmack diary │ ───────────────────────────────────── │ │ ring@thebackupbox.net │ │ │ me@happynetbox.com │ -------------------------------------- │ │ │ John Carmack's .plan for Aug 18, 1997 │ │ │ -------------------------------------- │ │ │ │ │ │ I get asked about the DOOM source code │ │ │ every once in a while, so here is a │ │ │ full status update: │ │ │ ... │ └────────────────────────┴───────────────────────────────────────┘ ``` ### Single account (`M-x efinger-finger`) ``` .plan — l back · n/p next/prev · g refresh · q quit Emily Carter Marine biologist. Coffee, kayaks and old maps. --- 2026-08-14 --- Back from sampling on the coast. Three jars of plankton to review. ``` ## Features - **Account list**: keep your finger accounts in `efinger-accounts` and browse them in a dedicated buffer, the way Elfeed lists feeds. - **Live preview**: move with `n` / `p` and the `.plan` under point is fingered and shown in the content pane automatically. - **Two-pane reader**: `RET` enters the content pane to read and scroll, `l` returns to the list, `q` closes both. - **Asynchronous connections**: connections use `:nowait`, so Emacs never freezes even when a host resolves but never answers on port 79 (the common case today). - **Connection timeout**: a stalled connection is abandoned after `efinger-connection-timeout` seconds with a clear message, instead of hanging. - **Graceful errors**: refused or timed-out connections are reported in the content pane, never as a backtrace. - **One-off finger**: `M-x efinger-finger` fingers a single `user@host` in its own buffer, showing the server reply raw, with no title header. - **Configurable layout**: list on the left and content on the right (`horizontal`), or list on top and content below (`vertical`). - **Ports and listing**: targets accept an optional `:port`; omitting the user (`host` or `@host`) asks the server to list every user. - **UTF-8**: replies are decoded as UTF-8, so accents and box drawing render correctly. ## Keymap ### Account list (`efinger-list-mode`) | Key | Description | |-------|------------------------------------------| | `n` | Move to next account and preview it | | `p` | Move to previous account and preview it | | `RET` | Enter the content pane for this account | | `g` | Re-finger the account at point | | `G` | Rebuild the list from `efinger-accounts`| | `q` | Close both panes | ### Content pane (`efinger-plan-mode`) | Key | Description | |-------|------------------------------------------| | `l` | Back to the account list | | `n` | Preview next account (stay in content) | | `p` | Preview previous account (stay in content)| | `g` | Re-finger the current account | | `q` | Close both panes | | `SPC` / `DEL` | Scroll the content up / down | ## Installation ### MELPA ``` M-x package-install RET efinger RET ``` ### use-package with :vc (Emacs 29+) ```elisp (use-package efinger :vc (:url "https://git.andros.dev/andros/efinger.el" :rev :newest) :config (setq efinger-accounts '(("random" "random@happynetbox.com") ("Andros" "me@andros.dev")))) ``` ### use-package with :load-path For manual installation or Emacs < 29: ```elisp (use-package efinger :load-path "/path/to/efinger.el" :config (setq efinger-accounts '(("random" "random@happynetbox.com") ("Andros" "me@andros.dev")))) ``` ### Manual Clone the repository and place the file in a directory on your `load-path`: ```sh git clone https://git.andros.dev/andros/efinger.el.git ``` Then add to your init file: ```elisp (add-to-list 'load-path "/path/to/efinger.el") (require 'efinger) (setq efinger-accounts '(("random" "random@happynetbox.com") ("Andros" "me@andros.dev"))) ``` ## Usage 1. Set `efinger-accounts` in your init file. Each entry is either a `"[user@]host[:port]"` string or a `(LABEL "[user@]host[:port]")` list. 2. Run `M-x efinger` to open the reader. 3. Move with `n` / `p` to preview each account, `RET` to read one in full, `l` to return to the list and `q` to quit. 4. Or run `M-x efinger-finger` to finger a single account on demand. Public servers you can try today: `random@happynetbox.com`, `benbrown@happynetbox.com` and `ring@thebackupbox.net`. ## Customization Run `M-x customize-group RET efinger RET` to list all available options. Key options: - `efinger-accounts`: the accounts shown in the reader. - `efinger-port` (default `79`): default finger TCP port. - `efinger-connection-timeout` (default `10`): seconds before a stalled connection is abandoned; `nil` waits indefinitely. - `efinger-forward-host` (default `nil`): send `user@host` instead of just `user` (finger forwarding, for old daemons). - `efinger-layout` (default `horizontal`): `horizontal` (list left, content right) or `vertical` (list top, content bottom). - `efinger-list-width` (default `40`): list width in columns (horizontal). - `efinger-list-height` (default `12`): list height in lines (vertical). ## The Finger protocol Finger is minimal: the client opens a TCP connection to port 79 of the server, sends a single line (the user name, or an empty line to list everyone) terminated by CRLF, and the server replies with plain text and closes the connection. No encryption, no headers, no sessions. You can speak it by hand: ```sh echo "random" | nc happynetbox.com 79 ``` ## Contributing Contributions are welcome! Please see the [contribution guidelines](https://git.andros.dev/andros/contribute) for instructions on how to submit issues or pull requests. ## License This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see [https://www.gnu.org/licenses/](https://www.gnu.org/licenses/).