Documentation · v0.1

How Mallard works.

A tour of the moving parts, in roughly the order you'll meet them. Skim what looks useful; the table of contents on the left will jump you anywhere.

Getting started

Download Mallard from the downloads page, install it, and open it. The first time it launches you'll get an empty workspace and a vertical world rail down the left side. Click the + at the top of that rail to add your first world.

A world needs only a name, a host, and a port. TLS and login credentials are optional. Once you've saved it, click the world's tile in the rail and hit Cmd+Shift+C (or Ctrl+Shift+C on Windows / Linux) to connect.

The workspace

Mallard's window is built around a docking system. Panels can be split, stacked, and rearranged. The arrangement is saved per world, so each world remembers its own layout across restarts.

Panel types

The built-in panels are:

  • Output — the main scrollback and MUD text.
  • Inspector — a live tree of GMCP / MSDP frame state and MSSP server info.
  • Triggers — manage triggers, aliases, and timers.
  • Variables — a read-only table of user-defined variables.
  • Logs — the most recent 500 protocol events (GMCP, MSDP, MSSP, ATCP, MXP, MCCP2, auto-login).
  • Plugin panels — anything a plugin contributes (vitals, mapper, chat capture, etc.).

Moving panels

Right-click any tab for a menu: Move to left / right / above / below, Stack with…, or Move to new column.

The world rail

The 48-pixel vertical strip on the left is the world rail. Each world gets a tile with a status dot (connected, disconnected, or connecting) and its first letter. Hover for the full name. The + button at the top adds a new world; a gear icon at the bottom opens settings and theme.

Connecting to a world

Profiles

Each world is a profile. The fields you'll see when adding or editing one are:

  • Name, host, port — the basics.
  • TLS — toggle on for encrypted connections. Combine with cert pinning (below) if you want trust-on-first-use.
  • Auto-connect — connect the moment Mallard starts.
  • Auto-login — username and password. Passwords are stored in the OS keychain, not on disk. Login is driven by regex prompts you can edit.
  • Charset — UTF-8 by default; ASCII variants are available for older worlds.
  • Logging — toggle per-world session logs to disk.

Certificate pinning

With TLS on, you can also enable a per-world certificate pin in trust-on-first-use mode. The first connection records the server's certificate fingerprint; subsequent connections refuse to proceed if the fingerprint changes. Helpful against a quiet certificate swap on a long-lived world.

Typing commands

The input bar lives at the bottom of the Output panel. It's a multi-line textarea — Enter sends, and Shift+Enter inserts a newline. A bare Enter on an empty input sends an empty line, matching the behaviour of mud.send("").

Command history

and walk through previously sent commands. Arrow navigation only triggers when the cursor is on the first or last logical line of the input — so multi-line edits still work as expected.

Command separator

Per world, you can choose a character (commonly ;) that splits one typed line into multiple sends. Typing n;n;e with ; as separator becomes three consecutive sends.

Autocomplete

Press Tab while typing to cycle through ghost-text suggestions drawn from a per-world vocabulary of words the server has recently sent (minimum length 3). Shift+Tab cycles in reverse.

The output pane

Output is virtual-scrolled, so thousands of lines render without visible lag. Full ANSI SGR colour is supported, including 16-color and 256-color indexed palettes plus 24-bit RGB.

MXP

Common MXP tags are rendered — bold, italic, underline, colour, <send> (clickable command), and <a> for autolinks. Plugin authors can hook into custom MXP tags and entity declarations via mxp.on and mxp.on_entity.

Themes

Mallard ships with a dark and a light theme. Custom themes are authored as TOML files; reload them from disk via the command palette. Each world can override the global theme, and a 16-slot ANSI palette editor is available per world.

Searching scrollback

Cmd+Shift+F opens the search modal. Tokens AND together; toggles for regex and case sensitivity sit alongside the input. Lines older than seven days, or already evicted from memory, are searched via a streaming backfill with a progress indicator. If a line lives only in the on-disk log, an Open log file affordance jumps you there.

Aliases, triggers, timers, variables

The Triggers panel is the central place to manage automation. Each entry is one of:

Aliases

A regex matched against what you type. When it matches, actions run instead of (or in addition to) sending the original line. Actions can send text back to the world (including multiple \n-separated lines), note a system line into the output, or chain multiple actions.

Triggers

A regex matched against lines from the world. Capture groups are available in actions. Same action vocabulary as aliases.

Timers

Named one-shot or repeating timers. From Lua: timer.every(ms, fn) and timer.after(ms, fn). You can also create and disable them from the Triggers panel without writing code.

Variables

User-defined string variables. Edit them in the Variables panel, reference them from Lua, or interpolate them into action text.

Tags

Every alias, trigger, and timer can carry free-form tags. The panel has a pill filter at the top with AND semantics — useful once you've built up dozens of entries and want to view, say, everything tagged combat and discworld.

Plugins

Mallard's plugins are written in Lua and ship as .mallardx bundles — a folder zipped up with a manifest. The runtime sandboxes each plugin and gives it a scoped host API.

Manifest

Every plugin has a manifest.toml at its root. The required fields are id, author, and version. Optional fields cover declared permissions, allowed outbound URLs under network, and any GMCP advertise strings under [gmcp].

# manifest.toml
id      = "com.example.combat-helper"
author  = "Player Two"
version = "0.3.1"

permissions = ["storage", "ui"]

[network]
allow = ["https://wiki.example.com/"]

[gmcp]
advertise = ["Char.Vitals", "Room.Info"]

What a plugin can do

  • Register aliases, triggers, and timers programmatically.
  • Subscribe to GMCP and MSDP frames.
  • Read and rewrite output lines (including span-aware re-styling).
  • Add highlight rules to incoming lines.
  • Contribute panels — grid templates, log templates, or fully custom HTML in a sandboxed iframe.
  • Persist state per (plugin, world), up to 50 MB.
  • Bind keyboard shortcuts, world-scoped.
  • Listen for connect and disconnect events.

Custom panels

Plugin panels come in three flavours: a structured grid template (rows of labels, values, bars), a log template (timestamped scrolling entries), or a fully custom HTML page rendered in a sandboxed iframe with a JSON-RPC bridge to the plugin's Lua context.

Protocol support

Mallard speaks the protocols you'd expect from a serious MUD client and a few you'd hope for. Most of this is invisible — it just means the worlds you connect to behave themselves.

  • Telnet with full option negotiation (RFC 1143).
  • TLS, optionally pinned per world.
  • MCCP2 compression.
  • ANSI SGR — 16-color, 256-color, and truecolor.
  • MXP — bold, italic, underline, colour, <send>, <a>, custom tags, and entity declarations.
  • GMCP with manifest-driven Core.Supports.Set.
  • MSDP table parsing.
  • MSSP server info (visible in the Inspector panel).
  • ATCP as a legacy fallback.
  • CHARSET and TTYPE negotiation.
  • NAWS (window size).

Keyboard shortcuts

Cmd on macOS, Ctrl on Windows and Linux.

ShortcutWhat it does
Cmd+KOpen the command palette
Cmd+Shift+FSearch scrollback
Cmd+Shift+CConnect to the current world
Cmd+Shift+DDisconnect
Cmd+Tab / Cmd+Shift+TabNext / previous world
Cmd+19Jump to world N
Cmd+WClose the current world tab
Cmd+/Show all shortcuts
Cmd+Shift+EnterToggle light / dark theme
EscReturn focus to the input bar
Tab / Shift+TabCycle ghost-text autocomplete
/ Walk through command history

Plugins can register additional world-scoped shortcuts. F-keys and modifier combos fire regardless of focus; bare keys require focus outside the input bar.

Settings

Global

  • Theme — dark, light, or any custom TOML theme on disk.
  • Show / hide system lines.
  • Show / hide local echo lines.
  • Reload themes from disk.

Per-world overrides

  • Theme.
  • Local echo (on / off / default).
  • Line height (1.2 – 1.8).
  • Wrap (wrap / no-wrap).
  • Font family and size (10 – 20 px).
  • Charset.
  • Command separator character.
  • TLS pin mode.
  • Per-world logging.
  • Full 16-slot ANSI palette.

Logs & debugging

Logs panel

A live tail of the last 500 protocol events. GMCP and MSDP payloads can be expanded inline as JSON; MXP tags and entities, MCCP2 frame boundaries, and auto-login state changes all show up here too. There's a Clear button for when you want a fresh canvas before reproducing something.

Inspector panel

A live tree of the current GMCP frame state, MSDP table state, and MSSP server info. Handy when you're writing a plugin and need to know what shape a frame actually arrives in, as opposed to what the docs say it should be.

Variables panel

A read-only listing of all user variables currently in scope. Useful for confirming a trigger really did set the variable you expected.

On-disk logs

When per-world logging is enabled, every session is written to disk. The search modal will offer to open the underlying log file when a match is older than what's still resident in memory.

← Back to the front page