Commands

Lua command modules return a commands array. Each entry has a native Lua pattern, a handler function, and an optional access level:

return {
  commands = {
    {
      pattern = "^say%s+(.+)$",
      access = "wizard",
      handler = function(ctx, message)
        mux.notify(ctx.enactor, "You said: " .. message)
        return true
      end,
    },
  },
}

Omit access, or set it to "public", to allow everyone. Set it to "wizard" to allow Wizards and God, or "god" to allow only God. Values are case-sensitive. Invalid values cause module validation and reload to fail.

An entry the invoker cannot access is skipped silently before its pattern or handler runs. Matching continues with later entries and command scopes.

Programmable commands must be defined in Lua. Persistent object state is data only and is never matched as a command.

Pattern matching

Patterns use Lua’s string.match syntax, not MUX wildcards or regular expressions. Matching is case-sensitive. Anchor a pattern with ^ and $ when it must match the complete command.

Common Lua pattern elements include:

PatternMeaning
.Any character
%sWhitespace
%dDigit
+One or more repetitions
*Zero or more repetitions
(...)Captures a value for the handler

The pattern is matched against the otherwise-unmatched command text. Each capture becomes an argument after ctx, in capture order. When a pattern has no explicit captures, Lua passes the complete match as the argument after ctx.

{
  pattern = "^roll%s*(%d*)$",
  handler = function(ctx, sides)
    sides = tonumber(sides) or 6
    -- ...
    return true
  end,
}

Handling results and order

A handler returns true to handle the command. Returning false or nil leaves it unhandled.

For object modules, all matching entries run in declaration order. If no object handler handles the command, matching continues through the remaining local and zone Lua scopes. A Lua pattern or handler error is logged and counts as handled.

Global command modules run only after local and zone Lua matching declines the command. Their modules are checked in lexical path order and stop at the first handler that returns true.

Command context

Every command handler receives a context table as its first argument.

FieldLocal object commandGlobal commandDescription
ctx.objectdbrefnilThe command-scope object whose active module handled the command.
ctx.enactordbrefdbrefThe player or object that issued the command.
ctx.causedbrefdbrefThe original MUX command cause.
ctx.commandstringstringThe command text tested by the Lua pattern.
ctx.scopenil"global"Present only for global commands.
ctx.descriptornumber or nilnumber or nilThe fd of the descriptor that typed the command, when the command came from a live connection rather than a queued or scheduled execution.
ctx.argsempty tableempty tableReserved for event arguments; command captures are passed as handler arguments instead.

Use ctx.enactor for player-facing notifications. An object module may use ctx.object with the mux package to store persistent state. Global handlers must not assume an object is present. Use ctx.descriptor with mux.flow_start to start an interactive flow on the connection that issued the command.

Discovering commands

Wizards can use @list commands to see three separate command groups: built-in commands, global Lua commands, and object Lua commands. Each Lua entry shows its pattern and source. Global entries use the module path as their source; object entries use the object’s name and dbref.

The list applies the invoking player’s Lua command access level. Object entries are further limited to command sources reachable from the player’s current location, including the player, inventory, room, room contents, and applicable zones. Halted objects and objects blocked from the relevant command scope are omitted. Listing does not evaluate patterns or run handlers.