durthang 0.2.0

A modern, terminal-based MUD client with TLS, GMCP, automap, aliases, triggers, and a sidebar panel system
durthang-0.2.0 is not a library.

๐Ÿฐ Durthang

"A few miles north, high up in the angle where the western spur branched away from the main range, stood the old castle of Durthang, now one of the many orc-holds that clustered about the dale of Udรปn." โ€” J.R.R. Tolkien, The Return of the King

Durthang is a modern, terminal-based MUD client written in Rust ๐Ÿฆ€. It runs entirely in your terminal, requires no graphical environment, and ships as a single statically-linked binary with no extra runtime dependencies.


โœจ Features

Category Details
๐Ÿ”Œ Connection Plain TCP and TLS (system root certs); clean disconnect and reconnect
๐Ÿ“ก Telnet IAC negotiation โ€” ECHO, NAWS, GMCP; all unknown options refused
๐Ÿ—บ๏ธ GMCP Room.Info parsing for automap; extensible for other modules
๐ŸŽจ ANSI / VT100 Full 16- and 256-colour rendering via ratatui
๐Ÿ“œ Scrollback buffer 5 000 lines; scroll with PgUp/PgDn or mouse wheel
โŒจ๏ธ Input Shell-style history (โ†‘/โ†“), Home/End/Left/Right cursor movement
โšก Aliases Per-character short-command expansions, stored in config
๐Ÿ” Triggers Regex โ†’ highlight colour and/or auto-send, stored per character
๐Ÿ“‹ Copy mode Scroll and copy output text to clipboard via OSC 52
๐Ÿ—บ๏ธ Automap Real-time ASCII map built from GMCP Room.Info or heuristic Exits: parsing; persisted to disk per server
๐ŸชŸ Sidebar Right-side panel column with an Automap minimap and a Notes panel; toggleable, resizable, configurable per character
๐Ÿ“ Notes panel Create, edit, delete, and reorder personal free-text notes without leaving the game
๐Ÿ” Secure credentials Passwords stored in the OS keyring (Secret Service / macOS Keychain / Windows Credential Manager); never written to the config file
๐Ÿ’พ Config persistence TOML config at ~/.config/durthang/config.toml (XDG respected); sidebar layout and notes are saved automatically
๐Ÿ“ถ Latency display Rolling-average latency shown in the status bar
๐Ÿ–ฑ๏ธ Mouse support Scroll wheel for scrollback
๐Ÿชต Logging Structured logs to ~/.local/share/durthang/durthang.log via tracing

๐Ÿ“ฆ Installation

Method Platform Command / Link
crates.io Any (needs Rust โ‰ฅ 1.85) cargo install durthang
AUR (source) Arch Linux yay -S durthang
AUR (binary) Arch Linux yay -S durthang-bin
AppImage Linux x86-64 Download .AppImage, chmod +x, run
Windows Binary Windows x86-64 Download .zip from GitHub Releases
From source Any See below

From crates.io

cargo install durthang

AUR (Arch Linux)

# Build from source
yay -S durthang

# Or install the pre-built binary
yay -S durthang-bin

AppImage (Linux)

Download the latest .AppImage from GitHub Releases:

chmod +x durthang-*.AppImage
./durthang-*.AppImage

Windows Binary

Download the .zip archive from GitHub Releases, extract it and run durthang.exe.

From source

git clone https://github.com/Pommersche92/durthang.git
cd durthang
cargo build --release
# The binary is at target/release/durthang

Minimum Rust version: 1.85 (edition 2024)

๐Ÿง Linux: password storage dependency

Durthang uses the OS keyring to store passwords securely. On most Linux desktops this works out of the box via the Secret Service D-Bus API (GNOME Keyring, KWallet, etc.).

On a headless or minimal system you need a running Secret Service daemon:

# Debian/Ubuntu โ€” GNOME Keyring
sudo apt install gnome-keyring
eval $(gnome-keyring-daemon --start --components=secrets)

# or use the kwallet-based stack on KDE

Durthang will still start without a keyring, but password saving will fail with a runtime error. You can work around this by leaving the password field blank and using the server's own login prompt.


๐Ÿš€ Quick Start

Launch Durthang:

durthang

An optional --config flag points to a custom config file:

durthang --config ~/my-muds.toml

You will land on the server/character selection screen.

๐Ÿ—‚๏ธ Selection screen keys

Key Action
โ†‘ / โ†“ Move cursor
Space / โ† / โ†’ Expand or collapse a server
Enter Connect with the selected character
N Add a new server
n Add a new character to the selected server
e Edit the selected server or character
d Delete the selected server or character (with confirmation)
q / Ctrl+Q Quit

๐ŸŽฎ Game Screen

Once connected, the game screen shows:

โ”Œโ”€ MUME โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                                            โ”‚  Automap     โ”‚
โ”‚  [scrollable MUD output]                   โ”‚  . . .@. .   โ”‚
โ”‚                                            โ”‚  @ Rivendell โ”‚
โ”‚                                            โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                            โ”‚  Notes       โ”‚
โ”‚                                            โ”‚  - buy food  โ”‚
โ”‚                                            โ”‚  - repair eq โ”‚
โ”‚                                            โ”‚              โ”‚
โ”‚                                            โ”‚              โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚              โ”‚
โ”‚ โ–ถ input line                              โ”‚              โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ†‘42 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ MUME / Berejorn   lat 12ms   Ctrl+Q disconnect            โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

โŒจ๏ธ Game screen keys

Key Action
Enter Send the current input line
โ†‘ / โ†“ Input history
PgUp / PgDn Scroll the output buffer
Ctrl+End Jump back to the live view
F3 Toggle the right sidebar
F4 Cycle focus to the next sidebar panel
F1 / Esc (in sidebar) Return focus to the game input
Ctrl+C Enter copy mode (scroll + copy a line)
Ctrl+Q Disconnect and return to the selection screen

๐Ÿ’ฌ Meta-commands (type in the input line)

Command Effect
/connect Reconnect to the current server
/disconnect Disconnect and return to the selection screen
/quit Exit Durthang
/alias <name> <expansion> Add or update an alias
/unalias <name> Remove an alias
/trigger <regex> [color=<c>] [send=<cmd>] Add a trigger
/untrigger <id-prefix> Remove a trigger
/sidebar right Toggle the right sidebar

๐ŸชŸ Sidebar panels

The sidebar is toggled with F3. Focus cycles through panels with F4. Press o while a panel is focused to open the Sidebar Options overlay, where you can toggle panel visibility, reorder panels, and adjust the sidebar width.

๐Ÿ—บ๏ธ Automap panel

The automap builds a live ASCII grid as you move through the world:

  • @ marks your current room.
  • . marks known adjacent rooms.
  • The legend line shows the current room name and Z-level.

Map data is loaded from GMCP Room.Info when available, with a fallback heuristic that reads Exits: lines from the server output. Maps are saved automatically to ~/.local/share/durthang/<server-id>.map.json.

๐Ÿ“ Notes panel

A personal scratchpad attached to each character.

Key Action
n / a Add a new note
e / Enter Edit the selected note inline
d / Delete Delete the selected note
K Move the selected note up
J Move the selected note down
Esc Cancel editing

Notes are persisted in the character's sidebar config automatically on every change.


โšก Aliases & Triggers

Aliases and triggers are stored per character in the config file.

Alias example โ€” type k orc in game and it expands to kill orc:

/alias k kill

Trigger example โ€” highlight lines containing "You are hungry" in yellow:

/trigger You are hungry color=yellow

Trigger with auto-response โ€” auto-buy food when a shopkeeper says it's available:

/trigger "You see food on sale" send="buy bread"

โš™๏ธ Configuration

Config file: ~/.config/durthang/config.toml

[[servers]]
id = "โ€ฆ"            # auto-generated UUID
name = "MUME"
host = "mume.org"
port = 4242
tls  = true

[[characters]]
id        = "โ€ฆ"
name      = "Eomer"
server_id = "โ€ฆ"    # references servers[].id
login     = "xX_H0R538055_Xx"
password_hint = "mother's maiden name"   # reminder only, not the actual password
notes     = "Rohirrim, warrior"

[characters.sidebar]
right_visible = true
right_width   = 26

[[characters.sidebar.panels]]
kind     = "automap"
side     = "right"
height_pct = 35

[[characters.sidebar.panels]]
kind     = "notes"
side     = "right"
height_pct = 65

[[characters.aliases]]
name      = "k"
expansion = "kill"

[[characters.triggers]]
id      = "โ€ฆ"
pattern = "You are hungry"
color   = "yellow"

Passwords are never stored here ๐Ÿ”’; they live in the OS keyring under the key durthang/<server-id>/<character-name>.


๐Ÿ—‚๏ธ Project Structure

src/
  main.rs        Entry point, CLI parsing, terminal setup, main event loop
  app.rs         Top-level state machine (ServerSelect โ†” Game)
  config/        Serde data model, TOML persistence, keyring helpers
  net/           Async TCP/TLS/Telnet connection task (tokio)
  ui/
    selection.rs Server/character selection tree-view
    game.rs      Game screen, key handling, alias/trigger evaluation
    sidebar.rs   Sidebar panel system (automap + notes)
  map/           Room data model, GMCP/heuristic parsing, JSON persistence

๐Ÿค Contributing

Issues and pull requests are welcome!

cargo fmt --check
cargo clippy -- -D warnings
cargo test

๐Ÿšข Releasing

All release automation lives in scripts/.

Scripts Overview

Script Purpose
scripts/release.sh Full pipeline: tests โ†’ crates.io โ†’ GitHub โ†’ AUR
scripts/release-github.sh Build assets and create/update a GitHub release
scripts/build-appimage.sh Build a Linux AppImage (auto-downloads linuxdeploy)
scripts/deploy-aur.sh Update and push durthang + durthang-bin PKGBUILDs to AUR

Prerequisites

Tool Purpose Install
gh GitHub CLI โ€” creates releases and uploads assets cli.github.com โ†’ gh auth login
gcc-mingw-w64-x86-64 Windows cross-compile linker sudo apt install gcc-mingw-w64-x86-64 / sudo pacman -S mingw-w64-gcc
zip Windows zip packaging sudo apt install zip / sudo pacman -S zip
makepkg Generates .SRCINFO for AUR (optional) Arch Linux or an Arch-based container
AUR SSH key Authenticates pushes to AUR Add public key at aur.archlinux.org/account

linuxdeploy (AppImage builder) is downloaded automatically into target/appimage-build/ on first use โ€” no manual install needed.

Recommended SSH config for AUR (~/.ssh/config):

Host aur.archlinux.org
    IdentityFile ~/.ssh/id_ed25519_aur
    User aur

Optional โ€” AppImage icon: Place a docs/durthang.png (256 ร— 256 px or larger) in the repo. If absent, a placeholder is generated via ImageMagick (convert), or a 1ร—1 fallback is used so the build does not abort.

AUR one-time setup

Before the first --push to AUR, clone both package repos:

mkdir -p aur/durthang
git clone ssh://aur@aur.archlinux.org/durthang.git aur/durthang/aur-repo

mkdir -p aur/durthang-bin
git clone ssh://aur@aur.archlinux.org/durthang-bin.git aur/durthang-bin/aur-repo

Running a release

# Full release: crates.io + GitHub + AppImage + Windows zip + AUR
./scripts/release.sh

# Draft GitHub release (safe to iterate on)
./scripts/release.sh --draft

# Skip individual steps
./scripts/release.sh --skip-crates        # already published to crates.io
./scripts/release.sh --skip-github        # skip GitHub release
./scripts/release.sh --skip-aur           # skip AUR push

All build artefacts land in target/dist/ (git-ignored):

target/dist/
  durthang-<ver>-x86_64.tar.gz           โ† Linux tarball (GitHub + AUR source)
  durthang-<ver>-x86_64.AppImage         โ† Linux AppImage
  durthang-<ver>-x86_64-windows.zip      โ† Windows binary zip

AUR-only update

To push only a version bump to AUR without a full release:

# Dry-run (no push) โ€” inspect the changes first
./scripts/deploy-aur.sh

# Push both packages
./scripts/deploy-aur.sh --push

# Push only one package
./scripts/deploy-aur.sh --push --package durthang-bin

The script reads the version from Cargo.toml, downloads the relevant source or binary to compute sha256sums, updates both PKGBUILDs, regenerates .SRCINFO (via makepkg --printsrcinfo), and pushes to the AUR.


๏ฟฝ๐Ÿ“œ License

GNU General Public License v3.0 โ€” see LICENSE for the full text.


"Even in Mordor, there were those who endured." ๐Ÿ”ฅ