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
connectanddisconnectevents.
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.
| Shortcut | What it does |
|---|---|
| Cmd+K | Open the command palette |
| Cmd+Shift+F | Search scrollback |
| Cmd+Shift+C | Connect to the current world |
| Cmd+Shift+D | Disconnect |
| Cmd+Tab / Cmd+Shift+Tab | Next / previous world |
| Cmd+1…9 | Jump to world N |
| Cmd+W | Close the current world tab |
| Cmd+/ | Show all shortcuts |
| Cmd+Shift+Enter | Toggle light / dark theme |
| Esc | Return focus to the input bar |
| Tab / Shift+Tab | Cycle 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.