Builder Commands

Audience: Builder Status: ✅ Ready

The in-game command surface, with emphasis on how commands are resolved and on the staff/builder verbs an elevated session gains over an ordinary player. This page explains the dispatch model (so you understand why n means north and why a verb you lack simply “doesn’t exist”), then itemizes the everyday command surface and the staff verbs. For who gets staff rank and how it’s applied, see Trust Tier Model; for the deeper parser/targeting internals see Command Parser & Targeting.

How commands are resolved

Every line a player types enters one dispatcher running on the zone’s single goroutine, so a command handler mutates zone state without locking. The pipeline is: trim the line (a blank line just re-prompts), split into a verb and the rest, lowercase the verb, clear AFK as a side effect, resolve the verb, gate it, and run it.

Player aliases expand at the split step

A character can define Unix-style aliasesalias bc burn corpse makes bc expand to burn corpse, and bc altar to burn corpse altar (trailing input is appended). Expansion runs at the split step, before verb resolution — the phase the parser reserves for it — which has two consequences worth understanding: an alias can target any verb the resolver handles (built-in, ability, custom, channel, or a named exit), and it grants no privilege, because the MinRank gate always runs on the resolved verb, not the typed alias. Expansion is cycle- and depth-bounded (a visited-set plus a cap), and the reconstructed line is re-clamped to the ingress byte cap so a chained alias can’t amplify one keystroke past it. alias lists, alias <name> queries, unalias removes. (This is distinct from a built-in command alias like nnorth, which is engine-defined; see the abbreviation rule below.)

Four namespaces, in strict precedence

A verb is looked up across four namespaces in a fixed order; a later namespace can never shadow an earlier one:

  1. Built-in verbs — the engine’s core commands (movement, look, inventory, combat, …). Abbreviation-aware (below).
  2. Ability invocations — abilities whose invocation is a command verb (e.g. a spell word). Exact match only, so an ability can never shadow or abbreviate a core verb.
  3. Custom Lua commands (command_defs) — verbs a pack defines in Lua. Exact match only; a custom verb that collides with a built-in is rejected at load with a warning, so content can never override a core verb.
  4. Content channel verbs (channel_defs, e.g. gossip) — exact match only.

If none of those match, a final named-exit fall-through tries the current room’s exit keys: an unknown verb that exactly matches an exit key traverses it, so a content exit like grove or warded is typeable as a movement verb. It is consulted last, so it can never shadow or abbreviate a core verb, and it checks the exits map only — never entrances, which is the instance-entry security path. Only then, if nothing at all matched, is the reply Huh? and a fresh prompt.

Exact-match, then abbreviation — and the alias rule

Within the built-in table, resolution is: (1) an exact match on a canonical name or an alias always wins; (2) otherwise the first command, in registration/priority order, whose canonical name has the typed verb as a prefix. Aliases do not participate in prefix matching — only canonical names abbreviate. Movement is registered first (highest priority), which is why n abbreviates to north and cl abbreviates to close (the low-priority clear never wins the abbreviation). A verb longer than any candidate name is a Huh?.

Insufficient rank reads as “unknown”

Staff verbs carry a minimum rank. If your session’s rank is below a verb’s minimum, the resolver forces the verb to not found before the fall-through — so an insufficient-rank staff verb is indistinguishable from a nonexistent one. This is the classic wizard posture: the existence of staff tooling never leaks to a mortal. (Rank is your session tier’s rank vs. the command’s minimum — see Trust Tier Model.)

Shape-only surface (honest caveats). The command struct also declares MinPos, Level, and Flags (CmdHidden, CmdNoWhileFighting), but dispatch enforces only MinRank. Position/combat gating is done ad hoc inside individual handlers (movement refuses while fighting; rest checks position) rather than by the dispatcher. CmdHidden marks staff verbs and is now consumed by the help command’s index (a hidden or over-MinRank verb is filtered from a mortal’s help, exactly as dispatch hides it); CmdNoWhileFighting is enforced nowhere. Player alias expansion is not implemented (it’s deferred to a later phase). Treat those fields as declared-but-inert.

The everyday command surface

All of these are ungated (rank 0). Aliases are shown in parentheses.

Movement (highest priority): north (n), south (s), east (e), west (w), up (u), down (d) — walk an exit, whether that’s a local move, an intra-shard transfer, or a cross-shard handoff. Refused while fighting (“flee first”). The named-exit verbs enter / exit / out walk a content-authored non-cardinal exit (a city gate, a portal) through the same move() chokepoint; they’re registered low-priority so o still abbreviates to open. The built-in Exits: line lists these too, in the order exit, enter, out, n, e, s, w, u, d (so a gate room reads e.g. Exits: exit, south). A pack may also register its own toggle verbs (toggle_defs) the same low-priority way — the demo’s overworld verb flips the minimap.

Look & common:

  • look (l) — bare shows the room; look <target> examines an item, occupant, or container’s contents.
  • help / help <topic> — the content-defined help index and topics (help_defs), with the registered command set auto-included; the listing honors CmdHidden + MinRank, so it doubles as the tier-appropriate command reference.
  • say (') — room speech (fires Lua speech triggers on scripted mobs present).
  • score (sc) — your character sheet; renders the content score display template if the pack defines one, else a built-in.
  • who — the cross-shard online roster, filtered by visibility/holylight, with a per-session cooldown (falls back to a zone-local list if presence is disabled).
  • tell / reply — directed, durable player-to-player messages.
  • tells (replay) — your recent private-message history, sent + received interleaved chronologically. A transient, session-scoped ring: pair-privacy is structural (an A↔B exchange lives only in A’s and B’s own session rings — no shared store to leak from, no access check needed), it skips an ignored author so it matches what actually reached your screen, and it resets on relog/handoff. A sent tell is recorded at the confirmed-echo point (past both the resolve-miss and publish-failure returns), never optimistically at enqueue — so a tell to a nonexistent name leaves no phantom entry, keeping “history == what you actually saw.”
  • audit — your own permanent-record trail (creation, deaths, tier/attribute/track grants), scoped by your stable character id; audit <name> is a staff-only lookup of another character. See Persistence & Durability → the audit trail.
  • quit — clean disconnect.

Carrying capacity (encumbrance) is pure content: carry_capacity is a derived attribute (5e’s Str×15 authored as a base formula), and the engine only enforces aggregate carried weight ≤ carry_capacity at acquisition — get/get from refuse an over-weight pickup, and get all takes what fits and leaves the rest. Worn gear stays in contents, so one weight pass covers carried + worn with no double-count; a pack that sets carry_capacity ≤ 0 models no encumbrance (a clean no-op).

Inventory, equipment & containers: inventory (i, inv), equipment (eq), get (take), drop, put, wear, wield, hold, remove, open, close, split (split a material stack), keep / unkeep (protect an item from drop/sacrifice). inventory and equipment render content display templates if defined.

Combat: kill (k) — engage melee and arm the zone’s round driver; flee — a sanctioned mid-fight exit; assist (as) — join an ally’s fight; consider (con) — size up a target.

Rest & position: rest (sit) — enter a faster-regen resting position; stand. rest/rest short/sit is a short rest and rest long/rest full a long rest — the engine fires OnRest plus the specific OnShortRest/OnLongRest, and what each restores is content (5e: short spends Hit Dice, long restores all).

Credits: credits (aliases license, copyright) — show the loaded packs’ declared license/attribution notices (a pack’s required CC-BY-style credit, surfaced in-game). A world whose packs declare none reports a clean “no content credits.”

Vitals: vitals — toggle live resource pools in your prompt (vitals on|off).

Comms toggles: channels — list/toggle channels (channels on|off <ref>); ignore — manage a per-player ignore list; afk — set/clear AFK. history <channel> replays that channel’s recent scrollback — but only to a viewer the channel’s live hear predicate still admits at fetch time (a since-demoted or flag-dropped player replays nothing), while a member who merely toggled the channel off can still read it. Shard-local, so on a multi-shard fleet the backlog is a partial view — and it says so, appending an in-band “shard-local view; may be incomplete” footer whenever the shard has peers (a single-shard run, the common case, shows no footer).

Mail: mailmail (list) / mail read <n> / mail delete <n> / mail send <name> <subj> | <body>; degrades to “Mail is unavailable” on a shard with no store.

Screen: clear (cls) — wipe the terminal. This is universal, not rank-gated: it emits an engine-constant ANSI clear (never player-controlled bytes), so there is nothing untrusted to gate. It’s registered at low priority so cl still abbreviates to close.

Aliases: alias — list your aliases; alias <name> — show one; alias <name> <expansion> — define one (alias bc burn corpse); unalias <name> — remove one. Per-character, durable across logout and a cross-shard walk. See how aliases expand.

Staff / builder verbs

All staff verbs are world verbs, registered last (lowest priority, so they never win an abbreviation), hidden (CmdHidden), and gated at MinRank = 1 — “any tier above baseline.” Below that rank they are treated as unknown (see above). The account-tier side of granting staff rank is in First Admin Setup and Trust Tier Model.

Verb Side MinRank Effect
stat [<target>] world 1 Inspect an entity’s internals: runtime id, prototype (“vnum”), flyweight bit, component set, live flags (reserved trust flags marked *), serialized state. Bare = current room; me/self = you; else keyword-resolve over room/inventory/equipment. Read-only. Cannot inspect a target of higher tier than you.
reload [<pack>] world 1 Trigger a director-coordinated content hot-reload across the fleet.
pull <version> [force] world 1 (force: admin) Request a director-coordinated install of a published content version from the external store. force downgrades the live-zone prune veto to a report — it still runs and still reports what it blocked — and needs admin on top of the builder flag, since it strips content the fleet may be hosting. See Content Pack Operations.
holylight on\|off world 1 See-all toggle (reserved holylight flag). Turning it on is capped: only a tier that grants holylight may enable it (no self-elevation); off is always allowed. Session-scoped (relog re-derives from tier).
wizinvis on\|off world 1 Staff invisibility (reserved wizinvis flag): hides you from anyone of strictly lower trust rank. No grant cap — reach is bounded by your own rank. Republishes presence. Session-scoped (cleared at login).
rolls on\|off world 1 Surface your own hidden check-roll math.
debug on\|off world 1 Subscribe your session to live zone diagnostics (first consumer: Lua script errors). Session-scoped, and rank is re-checked per line, so a mid-session demote stops delivery before relog.

Notes:

  • reload and pull are content operations, coordinated by the director across all shards. The operational side (external store, versions, CI) is in Content Pack Operations.
  • The screen.* Lua capability is not a per-tier unlock. The sandboxed full-screen ANSI builder (screen.frame()clear/home/at/color/write/show) is available to content regardless of the player’s tier; its trust boundary is content-authorship (a builder wrote the Lua), not a per-call rank check, and it’s bounded by per-frame caps. A builder does not “unlock” it by tier. See Pack Lua Scripting.
  • There is no world-side promote/demote verb. Tier changes are account/edge-side (promote/demote on the gate → SetAccountTier), and the world applies the new tier on the target’s next login. The gate verbs also carry the wiz-command posture: a non-staff actor who types promote/demote gets a plain Huh? — no usage hint, no authorization refusal, and no account-service round-trip — so the verbs’ existence never leaks (and can’t be used to probe the account service). The gate resolves a manage_tiers visibility bit once at login and only uses it to decide whether to intercept; the account service stays authoritative. See First Admin Setup, Trust Tier Model, and Accounts & Auth Internals.