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 aliases — alias 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 n→north, 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: mail — mail (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.