Skip to content

Core

The top-level functions on the rune table. For a task-oriented introduction, see Scripting Basics.

rune.send(text) -- process command syntax and aliases, then send
rune.send_raw(text) -- game lines, bypassing command processing
rune.echo(text) -- print to the local display only
rune.connect(address) -- "host:port", optional tls:// scheme
rune.disconnect() -- close the connection
rune.load(path) -- run a Lua script; true, or nil + error
rune.reload() -- reload core + user scripts
rune.quit() -- exit the client
rune.config_dir -- path to the config directory (data, not a function)
rune.version -- client version string
rune.debug -- set true to enable rune.dbg output
rune.dbg(msg) -- print msg, but only while rune.debug is true
rune.config.get(key) -- read a typed configuration value
rune.config.set(key, value) -- validate and update a configuration value

rune.echo prints locally and never touches the server — pair it with rune.style for colored messages. rune.reload reloads the core plus your scripts; rune.session state survives it.

rune.send(text)
  • text (string) — command text to process and send.

Before sending the text, Rune processes the configured command separator (; by default) and #N repeats, then checks each resulting command against your aliases. Doubling the separator makes it literal: rune.send("say one;;two") sends say one;two as one command. Escapes are decoded before aliases run. An alias returning a string starts a new command-processing pass; use rune.send_raw inside an alias callback to send its arguments without further interpretation. #N command repeats one command or alias: #3 north;look sends north three times, then look once. say #3 cheers is ordinary chat text. For a sequence, repeat an alias or use a Lua loop. Alias expansions are processed recursively, with a depth limit to catch loops.

Unlike text you type into the input line, rune.send does not run input hooks, save the command in history, or perform history expansion. It still applies the command separator, #N repeats, and aliases as described above.

for _ = 1, 2 do
rune.send("get bread bag;eat bread")
end
rune.send_raw(text) -> true | nil, err
  • text (string) — sent as game lines without aliases, command-separator splitting, or #N repeats. Text containing newlines is split and sent one physical line at a time. LF, CRLF, and bare CR are line breaks; empty lines are preserved.

Despite its name, send_raw sends MUD text, not Telnet or GMCP protocol data. Returns true, or nil plus an error message (which is also echoed) when the send fails — typically because you’re disconnected. This is what alias and trigger string actions ultimately call.

Before processing any user submission, Rune finishes an active partial line: it commits the prompt overlay and closes open multiline spans before input hooks and any local echo, history, aliases, or slash commands. This is independent of local echo, connection state, whether a hook consumes the submission, and whether it eventually sends anything.

A game line sent programmatically by an alias, trigger, timer, or other Lua callback also finishes the partial line, once the connection accepts it for writing. A failed programmatic send leaves the line open. GMCP and other Telnet protocol traffic never finish it. If the partial line was really part of an ordinary line, Rune commits the visible prefix and treats later bytes as a new line.

rune.connect(address)
  • address (string) — host:port with an optional scheme prefix:
Form Connection
host:port Plain telnet (default)
tls://host:port TLS, certificate verified
tls+insecure://host:port TLS, no verification (self-signed certs)

The full address, scheme included, is what rune.state.address reports and what the core stores for /reconnect. Connecting is asynchronous — the "connecting" and "connected" hook events report progress.

rune.connect("tls://mud.example.com:4000")
rune.load(path) -> true | nil, err
  • path (string) — path to a Lua script; ~ expands to your home directory.

Runs the script immediately and returns true, or nil plus an error message. While the script runs, its directory temporarily joins package.path, so it can require() files relative to its own location:

~/.config/rune/
├── init.lua -- main script
├── combat.lua -- require("combat")
└── utils/
└── helpers.lua -- require("utils.helpers")
-- In init.lua:
local combat = require("combat") -- loads combat.lua
local helpers = require("utils.helpers") -- loads utils/helpers.lua

Standard Lua require() semantics apply: modules are cached after the first load, and should return a table of exports.

rune.config_dir and rune.version are plain strings set by the client. rune.config_dir reflects --config-dir, RUNE_CONFIG_DIR, or the platform default, in that order. Set rune.debug to true to make rune.dbg print messages with a [dbg] prefix. When it is false, rune.dbg does nothing:

rune.debug = true
rune.dbg("trigger fired for " .. name)

Rune checks every configuration value against the type and rules below. Read and change settings through get and set; direct property assignment is not supported.

rune.config.get(key) -- value
rune.config.set(key, value)
Key Type Default Meaning
command_separator non-empty string ";" Text that separates multiple commands entered on one line
history_character empty or one visible, non-space character "!" Character used for history expansion (!, !!, !prefix); empty disables it
keep_input boolean false After Enter, leave the text you typed selected; Enter repeats it and typing replaces it
numpad boolean false Enable terminal support for physical numpad bindings; see Numpad keys
mouse boolean false Capture the mouse so its wheel scrolls Rune; see Scrolling and the mouse

An unknown key, a value of the wrong type, an empty command_separator, or an invalid history character raises an error and leaves the configuration unchanged.

rune.config.set("keep_input", true)
rune.config.set("command_separator", "|")
rune.config.set("history_character", "^")
rune.config.set("numpad", true)
rune.config.set("mouse", true)
assert(rune.config.get("keep_input") == true)

Set history_character to "" to turn history expansion off. Rune recognizes command separators before history expansion. For example, if !! is your command separator and ! is your history character, the !! between two commands remains a separator.

Double the configured separator to include it literally in a command (see command separators). Verbatim input and rune.send_raw bypass command processing and leave doubled separators unchanged.

A successful set takes effect immediately. On /reload, settings start from their defaults and your init.lua applies your choices again. Put settings you want to keep in init.lua; any key it no longer sets returns to its default. Rune applies the finished settings together, so the interface does not briefly switch to defaults while reload is running.

Related: Scripting Basics · State & Lines · rune.alias · Storage