Skip to content

The Scripting Model

Everything you register with rune — aliases, triggers, timers, hooks, key bindings, bars, GMCP handlers, slash commands — lives in the same kind of registry and behaves the same way. Learn the model once and every other page gets shorter.

Every creation function returns a handle:

local h = rune.trigger.contains("spam", nil, {gag = true, name = "spam-gag"})
h:disable() -- stop firing, stay registered
h:enable() -- resume
h:remove() -- unregister
h:name() -- "spam-gag"
h:group() -- nil (no group set)

Methods chain:

rune.trigger.contains("Weather:", nil, {gag = true}):disable()

You rarely need to keep the handle. Name the item instead and manage it by name from anywhere: rune.trigger.disable("spam-gag").

Every creation function takes an optional opts table with the same core fields:

Option Type Default Description
name string none Unique ID for management. Registering the same name again replaces the old entry (upsert) — reloading a script never stacks duplicates.
group string none Group membership for batch enable/disable/remove.
priority number 50 Execution order where multiple items can match (aliases, triggers, hooks). Lower runs first.
once bool false Auto-remove after the first match (aliases, triggers).

Individual registries add their own options — triggers take gag and raw, for example. Each API reference page lists its extras; the four above work everywhere.

Items have two independent enable switches: their own state (h:disable()) and their group’s master switch (rune.group.disable("combat")). An item fires only when both are enabled, and re-enabling a group preserves each item’s individual state. See Groups for patterns.

Wherever an action is expected, a string is sent as a command and a function runs your logic:

rune.alias.exact("n", "north") -- string: sent as-is
rune.trigger.contains("hungry", "eat bread") -- string: sent on match
rune.alias.exact("heal", function(args, ctx) -- function: full control
rune.send("cast heal " .. (args ~= "" and args or "self"))
end)

Regex string actions substitute captures with %1, %2, …:

rune.alias.regex("^cmd\\s+(\\w+)\\s+(.+)", "command private %1 to %2")

Function actions receive a context table as their last argument:

Field Description
ctx.name The item’s name, if set
ctx.group The item’s group, if set
ctx.type "alias", "trigger", "timer", or "hook"
ctx.line The original line (a line object for triggers)
ctx.args Argument string (exact aliases)
ctx.matches Capture array (regex matches)
ctx:remove() Remove this item from inside its own callback

ctx:remove() is how a timer stops itself:

rune.timer.every(10, function(ctx)
if done then ctx:remove() end
end)

To recover, fix the error and re-enable the item — h:enable(), rune.trigger.enable("name"), or just /reload (re-registering resets the failure count). One successful run also clears the count.

Every registration records the registering script’s file:line. It shows up in error messages and in the listing commands — /aliases, /triggers, /timers, /hooks, /binds, /bars — so you can always tell which script owns an item.

Every registry exposes the same management functions, taking the item name: enable, disable, remove, plus list(), count(), clear(), and remove_group(group). The full contract is in the API reference.

Related: API reference overview · Triggers · Aliases · Groups