Skip to main content

AutoMUD

A persistent telnet/MUD session you drive with small, discrete commands. There is no language model and no API key inside it: the intelligence is whoever runs it, a person, a script, or an autonomous agent. It exists because a raw telnet session is interactive and blocking, so it cannot be held open across separate shell commands. AutoMUD keeps the connection alive in a small background daemon and exposes simple verbs against it.

Install

pipx install git+https://github.com/CharlesCNorton/automud

Or from a clone:

pip install .

Standard library only, Python 3.8+.

Use

automud sites                        # list verified public targets
automud connect achaea               # by name, or: automud connect <host> <port>
automud send 2                       # send a line, print the reply
automud send Maelvorn
automud recv                          # drain any new output
automud wait --for "You are hungry"   # block until output matches a regex
automud state                         # structured game state (GMCP) as JSON
automud status
automud close
verb what it does
connect HOST PORT / --demo NAME open a session and start the daemon (--tls, --encoding ENC, --idle-exit SEC, --debug)
send [TEXT] send one line, print what comes back (omit TEXT for a blank line; --stdin reads the text from stdin)
recv print any new output (--nowait returns whatever is buffered immediately)
wait --for REGEX / --gmcp PKG block until output matches, or a GMCP package updates
gmcp PACKAGE [JSON] send a GMCP message (e.g. Char.Skills.Get)
state [--key PKG] [--times] captured GMCP state as JSON (--times: seconds since each package updated)
status connection, options, vitals summary
log [--tail N] session transcript (last N lines with --tail)
close end the session and stop the daemon
kill force-stop a wedged daemon and clear the session
sites directory of ~45 verified public targets (MUDs, MOOs, BBSes, services)

Every entry in sites was verified reachable by a live probe. Connect to any of them by name: automud connect aardwolf, automud connect telehack, automud connect fics.

Every reading verb takes --json and prints one structured object (data, prompt, connected, elapsed, ...) instead of raw text, which is the natural mode for driving it from a program. A minimal agent loop is just:

automud connect example.com 4000 --json
automud send look --json                 # {"ok": true, "data": "...", "prompt": true, ...}
automud wait --for "^You (win|die)" --max 120 --json

Exit codes: 0 ok, 1 failure, 2 usage error, 3 the operation succeeded but the connection is closed.

Driving it with an agent

There is no agent mode and nothing to configure: an agent drives the same verbs a person does, and everything past that is behavior. One pattern is worth writing down because it falls out of the design. Since the agent holding the session sits between the user and the wire, it can be the user's entire interface to the game and re-voice everything that crosses it: a total conversion of the setting, applied live. The user names the world they want in conversation ("Achaea, but it is Paris on the 14th of July 1789 and I am a hated noble"), and from then on the agent translates both directions, the user's stated intent into real commands and the raw replies into the agreed fiction, mechanics included if the user wants them (vitals re-skinned as a HUD). What keeps it honest:

  • The theme is the user's to pick. If they have not said what they want, ask; do not invent on their behalf.
  • Translate, do not decide. The user's intent picks the command, and the server's actual reply decides what happened. Failures and deaths render in-fiction, but they render.
  • Keep the mapping stable: the same room, denizen, or stat appears under the same converted name every time.
  • out.log keeps the untranslated transcript, so the fiction is always auditable against what the server really said.

Local single-player (Cataclysm)

automud connect cdda launches a local game of Cataclysm: Dark Days Ahead and drives it through the same verbs, so there is a world to play even with no MUD to connect to, an obligate single-player mode for when every public server is finally gone. It is a second backend: a persistent tmux session holds the game open the way the telnet daemon holds a socket, and send / recv / wait / state / status / close all work against it.

Requirements: tmux and a terminal cataclysm binary. On Windows the game runs in WSL and automud bridges to it automatically (AUTOMUD_CDDA_DISTRO selects the distro; AUTOMUD_CDDA_DIR / AUTOMUD_CDDA_BIN / AUTOMUD_CDDA_LAUNCH point at the binary).

automud connect cdda
automud send north              # move; the reply is the message log + a status line
automud send examine east       # a named action, not the seven keystrokes e-x-a-m-i-n-e
automud send nearby             # list items/creatures around you (no map needed)
automud state                   # the character as JSON: stats, hp, needs, place, threats
automud send help               # the action vocabulary for the current screen

The map is obscured on purpose. A blurry ASCII minimap is neither reliable for a language model to parse nor necessary to one that reads a room description, so game-mode output is the message log plus a structured status line (vitals, place, time, nearby threats), never the tilemap. Ask for spatial detail when you want it: send look, send examine <dir>, send nearby.

Actions, not raw keys. send understands word directions (north, se), named keys (enter, escape), and named game actions (examine, pickup, eat, wait, wield, ...) that map to the right key. An unrecognized word is reported, not typed out letter by letter. Single characters are still sent literally, so raw CDDA keys work too.

Character creation is one line per choice. send newgame drives the whole pre-chargen main menu (a maze with no readable cursor where New Game and World look identical) to the character-creation screen, and each choice is its own verb:

automud send newgame                             # main menu -> character creation
automud send scenario Sheltered
automud send profession "Sheltered Survivor"    # or: send class ...
automud send stats 8 10 10 10                    # STR DEX INT PER; reports the real values
automud send trait Fleet-Footed
automud send name Dougal
automud send finalize

Each reports what it actually committed (and refuses a locked or mismatched entry rather than silently selecting the wrong one), and in chargen state returns the build so far (scenario, profession, stats, name). The missing-mod prompts a fresh world throws are cleared automatically.

Behaviour

  • Smart waiting. send and recv return as soon as the server stops talking, either a telnet GA/EOR prompt marker or output going quiet, so you never guess a sleep duration. --max caps the wait and --quiet sets the idle threshold. wait extends this to regex/GMCP conditions.
  • GMCP. It negotiates GMCP and parses the structured state modern MUDs push (health, room, exits, skills) into JSON for state. Standard list deltas (Room.AddPlayer, Char.Afflictions.Add, ...) are applied to their lists, and Comm.Channel.Text is kept as a bounded Comm.Channel.History. TTYPE, NAWS and CHARSET negotiation are answered; options it does not implement (compression, MSDP, MXP) are refused rather than mishandled.
  • Encodings and TLS. --encoding sets the wire charset (default utf-8; use latin-1 or cp437 for older servers), and telnet CHARSET negotiation can switch it when the server asks. --tls wraps the connection (--tls-insecure for self-signed certificates).
  • One session per name, held by a background daemon; a new connect replaces it, and -s NAME gives you independent parallel sessions. Session state and transcripts live under a per-user state directory (override with AUTOMUD_DIR); the previous session's transcript is kept as out.prev.log.
  • Robust lifecycle. TCP keepalive is enabled, a dead daemon is detected by pid and its stale session cleared, concurrent connects are serialized by a lock, a wedged daemon is force-killed on reconnect (or by kill), and --idle-exit stops a forgotten daemon.

Security

The control channel is a localhost-only socket authenticated by a per-session random token. State lives in a per-user directory ($XDG_RUNTIME_DIR/automud, else <tempdir>/automud-<uid> on POSIX, %TEMP%\automud on Windows) that is created 0700 and refused if another user owns it. Prefer automud send --stdin for passwords: argv is visible to other local processes, and shell history persists. Plain telnet is cleartext; use --tls where the server offers it.

Tests

python -m unittest discover -s tests -t .

License

MIT. See LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

automud-0.3.2.tar.gz (52.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

automud-0.3.2-py3-none-any.whl (45.7 kB view details)

Uploaded Python 3

File details

Details for the file automud-0.3.2.tar.gz.

File metadata

  • Download URL: automud-0.3.2.tar.gz
  • Upload date:
  • Size: 52.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for automud-0.3.2.tar.gz
Algorithm Hash digest
SHA256 60877b7e0f135b383ee0d735a6e40330391d248e97281d0498b8c692613b72a8
MD5 a499239b98ed600567fe8551e28ad865
BLAKE2b-256 f1ce86661258a9b78f17dc7417d910a80c62831440f5cc2b5b6ed6a0e9da1b70

See more details on using hashes here.

Provenance

The following attestation bundles were made for automud-0.3.2.tar.gz:

Publisher: publish.yml on CharlesCNorton/automud

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file automud-0.3.2-py3-none-any.whl.

File metadata

  • Download URL: automud-0.3.2-py3-none-any.whl
  • Upload date:
  • Size: 45.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for automud-0.3.2-py3-none-any.whl
Algorithm Hash digest
SHA256 7650b0c199efc6c5750a7e997bac6645fc45db42a27f0c7eabcb636308aa6b34
MD5 c7f85eface02c713ea3e4119f7615a93
BLAKE2b-256 db8a9e6b7a519985c5617fcde58ce5319fd5509ed86527d9f5fa8863e8a3e82a

See more details on using hashes here.

Provenance

The following attestation bundles were made for automud-0.3.2-py3-none-any.whl:

Publisher: publish.yml on CharlesCNorton/automud

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.3.7

2 files

0.3.6

2 files

0.3.5

2 files

0.3.4

2 files

0.3.3

2 files

This release

0.3.2 This release

2 files

0.3.1

2 files

0.3.0

2 files

0.2.1

2 files

0.2.0

2 files

0.1.3

2 files

0.1.2

2 files

0.1.1

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page