GMCP triggers

Posted by Kyle Hankinson June 16th, 2026


GMCP triggers

GMCP (Generic MUD Communication Protocol) lets a MUD send your client structured data out of band: your health, the current room, your inventory, and more. Instead of scraping that information out of the text on screen with fragile regular expressions, you can react to the data directly and reliably.

This post covers how to fire a trigger when a GMCP value changes, and how to read the data with getGMCP.

Enabling GMCP

GMCP is enabled per connection and is on by default. You can toggle it in the connection editor. Two console commands help while you work:

#gmcp

Prints every GMCP value the MUD has sent so far, as formatted JSON. This is the quickest way to discover what your MUD exposes and the exact key names to match against.

#enableGMCP

Re-negotiates GMCP with the server if it was turned off.

How GMCP data is keyed

The client flattens each GMCP package into dotted paths. If the MUD sends:

Char.Vitals { "hp": 100, "maxhp": 120, "mana": 50 }

the client stores:

Char.Vitals.hp    = 100
Char.Vitals.maxhp = 120
Char.Vitals.mana  = 50

Nested objects keep extending the path, so Room.Info { "name": "Town Square", "exits": { "north": "101" } } becomes Room.Info.name and Room.Info.exits.north.

Creating a GMCP trigger

In the trigger editor, set the match type to "variable updated (including GMCP)". The trigger's pattern is then a GMCP path, not a regular expression, and the trigger fires whenever the value at that path changes.

For example, a trigger with the pattern:

Char.Vitals.hp

fires every time your health changes. To watch several paths with a single trigger, separate them with a pipe:

Char.Vitals.hp | Char.Vitals.mana

Matching is case-insensitive by default.

Reading the value with getGMCP

When a GMCP trigger fires, the path that changed is available as \0, and you read values with getGMCP:

  • getGMCP('Char.Vitals.hp') returns the single value (for example 100).
  • getGMCP('Char.Vitals') returns an object with everything under that branch: { hp: 100, maxhp: 120, mana: 50 }.

Example: low-health warning

Match type variable updated (including GMCP), pattern Char.Vitals.hp:

var hp  = getGMCP('Char.Vitals.hp');
var max = getGMCP('Char.Vitals.maxhp');

// Show current health in the app icon badge.
badge(hp + '/' + max);

if (max && hp / max < 0.25) {
    log('Warning: health is low (' + hp + '/' + max + ')');
    beep();
}

Example: show the current room in the status bar

Match type variable updated (including GMCP), pattern Room.Info.name:

status('Room: ' + getGMCP('Room.Info.name'));

Tips

  • Run #gmcp first to see exactly which packages and key names your MUD sends. Field names (for example hp versus maxhp) vary between MUDs.
  • A GMCP trigger matches on the path, not the value, so the action runs on every change. Use getGMCP inside the action to read the current value and decide what to do.
  • Because the data is structured, a GMCP trigger is almost always more reliable than a text trigger for anything the MUD reports over GMCP (health, room, inventory).
  • See the Functions post for getGMCP and setGMCP, and the Scripts post for sharing helper functions across triggers.

Tags: Scripting

Scripts

Posted by Kyle Hankinson June 16th, 2026


Scripts

The Scripts section is where you keep reusable JavaScript. Instead of copying the same code into every trigger and alias, you write a function once in a script and pull it in wherever you need it.

Every trigger and alias runs in its own JavaScript context, so the functions you define in a script are not available everywhere automatically. You make them available by including the script.

include() and require()

include(scriptName)

The include function loads another script by name and makes everything it defines available to the current trigger, alias, or script. scriptName is the title of the script as it appears in the Scripts list, and is not case sensitive.

require(scriptName)

require is identical to include. Use whichever reads better to you.

A script is only ever included once per run, so it is safe to include the same script from several places, and scripts may include other scripts.

Using a script from a trigger or alias

Create a script named Combat with a couple of helpers:

// Script: Combat
function herb(name) {
    command('get ' + name + ' from pack');
    command('eat ' + name);
}

function quaff(potion) {
    command('quaff ' + potion);
}

To use it from a trigger, include the script at the top of the action, then call the function. (Capture groups from the trigger's pattern are available as \1, \2, and so on. See the Regular expression tips post.)

// Trigger action. Pattern: ^You feel hungry
include('Combat');
herb('bloodroot');

An alias works exactly the same way. Here the first capture group of the alias pattern is passed straight through:

// Alias action. Pattern: ^h (\w+)
include('Combat');
herb('\1');

Because the include runs first, herb is ready to call on the lines that follow.

Reloading after edits

When you change a script, reload so your triggers and aliases pick up the new code:

#reload

Reloads every trigger, alias, and script from disk and reports how many of each were loaded.

Tips

  • Group related helpers into one script (for example a Combat script and a Travel script) and include only what each trigger needs.
  • Includes are resolved when the action is prepared, so there is no measurable cost to including a script you use often.
  • See the Functions post for the full list of built-in functions you can call from your scripts, and Console commands for the # commands.

Tags: Scripting

Regular expression tips

Posted by Kyle Hankinson August 17th, 2022


General

If you need a trigger or alias to match on a regular expression, here are some hints and tips to use.

Regex vailidation

As you type your regex, the main mud display will update to highlight matches.

  • The background will be highlighted with the full match range. The full match can be accessed in script via \0.
  • Each capture group will be underlined and can be used as a paramter in the script starting with \1, \2, \3, etc.

Whitespace

For whitespace (space, tab, linebreak) use the \s+ syntax option. While most muds will use spaces, some muds will use tabs is certain instances which may case a basic space match to fail.


Tags: Scripting

Console commands

Posted by Kyle Hankinson August 5th, 2022


Commands

#clearMessages

Clears anything currently in the messages window.

#clearOutput

Removes the main output buffer.

#autocomplete list

Displays a list of current autocomplete entries.

#autocomplete clear

Clears the autocomplete entries.

#vars

Displays a list of current script variables.

#disconnect

Disconnects from the current session. If auto-reconnect is enabled, a countdown will be started and the connection re-attempted.

#close

Disconnects the current connection and closes the window.

#set VARIABLE=VALUE

Sets the specified varaible to the specified value.

#stop

Stops any activly waiting scripts. Scripts may be in a waiting state from either a wait or a commandAndReadFromServer function.

#enable name

Enables a trigger or alias by name (not case sensitive) and saves the change.

#disable name

Disables a trigger or alias by name (not case sensitive) and saves the change.

#status name

Shows whether the named trigger or alias is currently enabled or disabled.

#reload

Reloads all triggers, aliases, and scripts from disk and reports how many of each were loaded. Run this after editing a script so your triggers and aliases pick up the new code.

#setAlias name=command

Creates or updates an alias, mapping name to command, and saves it.

#continue

Resumes any scripts that are paused in a wait.

#gmcp

Prints all current GMCP values as formatted JSON, handy when writing GMCP-aware scripts.


Tags: Scripting

Functions

Posted by Kyle Hankinson August 4th, 2022


General functions

command(commandToRun)

The command function will process a command as if the user had typed it into the console. Any aliases in the command will be processed as well.

wait(timeout)

The wait function will cause the current script to delay for timeout seconds before continuing the script. The wait timeout can contain miliseconds by specifying decials.

log(logMessage)

The log function will append the specific message to the console. This can be useful when debugging scripts.

processForAutocomplete(entries)

The processForAutocomplete method adds entries to the interal autocomplete list. entries can either be an array of strings, or a string which will be delimited by whitespace.

commandAndReadFromServer(command)

The commandAndReadFromServer will process a command as if the user had typed it into the console, then will read from the server until the next data stream has finished.

beep

The beep function will cause your device to output a beep sound effect.

addComm(message)

The addComm function adds message to the Communications (Messages) window, the side panel used to collect tells, says, and other channel chatter.

Variables

Variable functions are unrelated to javascript functions. Rather they are a way to store variables over multiple scripts. Regular javascript variables are removed from memory once the funcion has completed. All varaible methods below should have variable names passed as a string.

isEmpty(variableName)

The isEmpty method returns true if a variable is unset or empty. A string variable is considered empty if it has zero length or is completely whitespace. A numeric variable is never empty (zero is not considered empty). Use the unset function to completely unset a variable.

unset(variableName)

The unset function is used to completely clear a variable.

setVar(variableName, value)

Stores value under variableName for the rest of the session, so other scripts can read it back with getVar.

getVar(variableName)

Returns the current value of the specific variable.

(getValue is an alias for getVar, and setValue for setVar.)

macOS specific functions

status(display)

The status function updates the status bar to show the value for display.

notify(message)

The notify function will add a macOS notification with the specific message.

badge(display)

The badge method updates the app icon badge to show the specific display. This should be limited to a short string (less than 10 characters), or it will be truncated. Current/max HP is an example of what one might display in the badge.

GMCP

getGMCP(path)

Returns the GMCP value stored at the dotted path, for example getGMCP('Char.Vitals.hp'). If path points at a branch rather than a single value (for example getGMCP('Char.Vitals')), an object containing everything under that branch is returned.

setGMCP(path, value)

Sets the GMCP value at the dotted path. Useful for feeding your own data into GMCP-aware overlays and scripts.

Persistent variables

The setVar/getVar variables above live only for the current session. To keep a value across launches, use the saved variants.

saveVar(name, value)

Stores value on disk under name so it survives quitting and relaunching the app.

loadVar(name)

Returns the value previously stored with saveVar, or nothing if it was never set.

Flow control

waitUntil(condition, timeout)

Waits until the condition function returns true, checking repeatedly, and gives up after timeout seconds (default 5). Returns true if the condition was met, or false if it timed out.

stopOthers()

Stops any other actions that were already running when this one started. Handy when several triggers could fire at once and you only want the first to proceed.

continueAction(name)

Releases scripts that are paused in a wait. Pass an action name to release a specific one, or call it with no argument to release all.

debounce(name, delay)

Collapses rapid repeats. Returns true the first time it is called for name, then false for any call within delay seconds. Use it to act on only the first of a burst of matching lines.

throttle(key, interval)

Rate-limits by key. Returns 0 when the action is allowed to run, or the number of seconds remaining until it is allowed again.

throttleFn(fn, interval)

Rate-limits a function: calls fn at most once per interval seconds (the first call always runs, calls in between are skipped). Unlike throttle, you hand it the function and it does the gating for you.

lastUserInput()

Returns the number of seconds since you last pressed Enter in the input field. Useful for telling whether you are actively playing or idle.

Aliases and scripts

setAlias(name, command)

Creates or updates an alias at runtime, mapping name to command.

include(scriptName) / require(scriptName)

Loads a script from the Scripts section so its functions are available in the current trigger, alias, or script. See the Scripts post for a full walkthrough.


Tags: General

More articles: