A hyper-modern, cross-platform TUI client for MU* (MUSH / MUCK / MUD) worlds, built for GPU-accelerated terminals (Kitty, WezTerm, Ghostty) on Windows and Linux.
Part of the SharpMUSH family: SharpMUSH is the server, SharpClient is the graphical client, and SharpMUTerm is the terminal one. It speaks plain telnet, so it connects to any MU* world — not just SharpMUSH ones.
The goal is BeipMU-class feature parity in a terminal-native client: rich truecolor text, inline graphics, powerful automation, and full MU* protocol support.
Status: milestone M1 delivered (usable text client foundation) with substantial work from M2–M4 in place — automation engines, inline-graphics subsystem, Lua scripting, and theming.
SharpMUTerm.Coreis fully unit-tested (514 tests across the solution). Seedocs/PLAN.mdfor the full architecture and roadmap.
"GPU acceleration" is a property of the terminal emulator, not the app. Any TUI running inside Kitty / WezTerm / Ghostty gets GPU-accelerated glyph rendering for free. SharpMUTerm focuses on emitting rich truecolor/styled text and using the Kitty graphics protocol (with Sixel and half-block fallbacks) for inline images and maps.
- .NET 10 / C#
- SharpConsoleUI — compositor-based TUI framework: split layouts, tabs, resizable/mouse windows, Spectre-style markup, and a native Kitty graphics protocol (+ Sixel/half-block)
- TelnetNegotiationCore — telnet option negotiation (NAWS, MTTS, CHARSET, EOR/GA, MSSP, GMCP)
- MoonSharp — embedded, sandboxed Lua scripting
- Custom app-layer parsers for ANSI (256 + 24-bit), MXP, and Pueblo
Multi-world tabs · regex triggers · aliases · macros/keybinds · spawns · maps · stat panes · inline image viewer · puppets · multiple input windows · scripting (Lua) · TLS + IPv6 · HTML logging · GMCP / MSDP / MSSP / MCCP · MXP + Pueblo · Unicode/emoji.
MSSP is in and readable. Every server's own description of itself — name, players, uptime,
codebase, contact, website, and the rest of what it chose to publish, official variables and invented
ones alike — is captured on connect, kept between launches, and read from F5 ▸ i on the selected
world. (Capture is bounded and stripped of control characters, because the report comes off the wire
from a stranger; the limits are far above anything a real server sends.) It says when it was captured,
because a player count from last week is not a player count; and it distinguishes a world you have
never dialled from a server that answered and publishes no MSSP, which is the ordinary case on a MUSH
and not a fault.
| Project | Responsibility |
|---|---|
SharpMUTerm.Core |
Transport, telnet, ANSI/MXP/Pueblo parsers, GMCP/MSDP routing, scrollback, trigger/alias/macro engines, logging (UI-agnostic) |
SharpMUTerm.Graphics |
Kitty graphics protocol, capability probe, Sixel + half-block fallbacks, GraphicsView |
SharpMUTerm.Scripting |
MoonSharp host + scripting API |
SharpMUTerm.Tui |
SharpConsoleUI application (windows, panes, settings, wiring) |
*.Tests |
TUnit test projects |
- Transport & telnet — TCP with optional TLS (
SslStream) and IPv6, wrapping TelnetNegotiationCore for NAWS/MTTS/CHARSET/EOR/GA/GMCP/MSSP/MSDP/MCCP negotiation. Prompt (GA/EOR) detection surfaces prompts separately from scrollback. - ANSI parser — incremental SGR parsing: 16-colour, 256-colour, and 24-bit truecolour (semicolon and colon forms), with the usual rendition attributes; non-SGR CSI/OSC sequences are recognised and discarded.
- Scrollback — bounded, thread-safe styled-line model with change events.
- Automation — regex triggers (gag / highlight / rewrite / respond / spawn-route / script), aliases (capture-group expansion, multi-command), macros/keybinds (F-keys and Ctrl/Alt chords — the numpad is not deliverable through the terminal, and F4 says so per binding), and a recurring/one-shot timer scheduler. User regexes run with a ReDoS match-timeout guard.
- MXP & Pueblo — first-class parsers for both markup protocols: tags → styled spans, with
clickable
<SEND>/<A>links and commands (SpanInteraction), colours, entities, and line breaks. Selectable per world. - Emoji — optional emoticon (
:)→ 🙂) and:shortcode:(:fire:→ 🔥) substitution. - Logging — plain-text and styled HTML session logs.
- Config — a fresh JSON schema: worlds (servers) hold characters, and automation lives in
shared, named trigger sets that characters opt into; versioned with automatic migration. Character
passwords are saved in a separate
secrets.json(owner-only,0600) and the config carries only a meaningless GUID pointing at them — so yourconfig.jsonstays safe to paste into a bug report. - Inline graphics — Kitty graphics-protocol encoder (incl. Unicode placeholders), Sixel and half-block fallbacks, and a capability probe that degrades cleanly when no protocol is present.
- Scripting — sandboxed Lua (MoonSharp) exposing
world/output/trigger/alias/timer/gmcp/log, with hot-reload. - Theming — yazi-style named themes (Dark / Light / Solarized Dark) with a 16-colour palette override and semantic UI colours, serialised to the config as hex.
- TUI — a SharpConsoleUI app rendering the multi-pane
workspace design over the
Core.Workspacesmodel: a connection rail (worlds → characters → windows with connected/active/unread markers, any of which you can click to switch to — collapsed to a strip of initials, those are clickable too), split panes with tabbed windows (tmux-style split/close/zoom), a command surface (Ctrl+P) with ranked GO TO / WORLD / TERMINAL / LAYOUT actions, per-world accent colours, a GMCP-driven status bar with HP/EN meters, and a character-bound input prompt + destination/draft gutter. Output is truecolor markup with clickable MXP/Pueblo/web spans; every connected world is told its own pane's size over NAWS, on every resize and every layout change (rate-limited, with the settled size always delivered).Ctrl+Nnext window ·Ctrl+Onext pane ·Ctrl+Wclose ·Ctrl+Rcommand history (per command line, newest first, typing filters it; ⏎ puts an entry on the input line rather than sending it) ·Ctrl+Qquit (asks first, naming the connections and unsent drafts it would end). Hand-typed login lines (connect <name> <password>) are kept out of history, and history is never written to disk. - Web view — an in-TUI text-mode browser (
SharpMUTerm.Web, AngleSharp): fetch a URL or follow an MXP/Pueblo/HTML link and read the page as styled, word-wrapped text with clickable links you can navigate in-pane.<img>shows as a labelled link (graphics-terminal image rendering reuses the Kitty/Sixel/half-block pipeline). - Packaging — self-contained single-file publishing for Linux/Windows (see
docs/PACKAGING.md); a tagged release workflow builds the binaries.
Requires the .NET 10 SDK.
dotnet build SharpMUTerm.slnx -c Releasedotnet run --project src/SharpMUTerm.Tui -- <host> <port> [--tls] [--insecure] [--name NAME]
sharpmuterm --help # once publishedIn-app: Up/Down input history · Ctrl+N next window · Ctrl+W close window · Alt+R reconnect (drops the connection and redials it) · Ctrl+D disconnect · Ctrl+Q quit (y/n confirmation). Alt+R and Ctrl+D act at once, on the character whose pane is focused, and say so when there is nothing connected. (Windows/panes are mouse-resizable; each window keeps its own input draft.)
The test projects use TUnit, which runs on the Microsoft.Testing.Platform. Run each directly
(the classic dotnet test/VSTest path is not used by MTP on .NET 10):
dotnet run --project tests/SharpMUTerm.Core.Tests
dotnet run --project tests/SharpMUTerm.Graphics.Tests
dotnet run --project tests/SharpMUTerm.Scripting.Tests
dotnet run --project tests/SharpMUTerm.Web.Tests
dotnet run --project tests/SharpMUTerm.Tui.TestsMIT © 2026 Harry Cordewener