Skip to content

commands

Declare client commands from a script: arguments, replies, completion, lifetime.

Client commands typed in chat behind the client prefix (. by default). A scripted command behaves like a built-in one: it appears in .help, completes in the chat box and shows its usage hint while you type.

commands.register({
    name = "ping",
    description = "Prints your latency",
    execute = function(ctx)
        ctx:info(server.ping() .. " ms")
    end,
})
Function Does
commands.register(desc) Registers a command and returns a handle
commands.prefix() The prefix in effect, e.g. "."
commands.run(line) Runs a client command as if typed, with or without the prefix

Commands aimed at the server go through chat.command instead.

The descriptor

Field Meaning
name Command name, no prefix and no spaces. Required
execute function(ctx, args). Required
aliases Extra names it answers to
description The line .help lists it with. Defaults to the script file name
usage Detail lines shown by .help <name>
params Argument hints shown in the chat box while typing
hidden Keeps it out of .help and completion
complete function(ctx, args) -> string[]

Registering a name or alias another command already owns raises an error, so a script cannot shadow .help or another script’s command.

Arguments

args holds the words after the command name, with quoted sections kept together (.warp "spawn area" is one argument). Everything arrives as a string; use tonumber when you need a number.

commands.register({
    name = "warp",
    params = {
        { name = "name" },
        { name = "distance", type = "number", optional = true },
    },
    execute = function(ctx, args)
        if #args == 0 then
            ctx:error("usage: " .. ctx.prefix .. "warp <name>")
            return
        end
        ctx:success(("warping to %s"):format(args[1]))
    end,
})

params only shapes the hint the chat box shows (<name: string> [distance: number]). type is a label, not a parser, so validate values yourself.

Replying

ctx carries the prefix in effect, the alias the player typed (ctx.label) and the raw line after the prefix (ctx.raw), plus four output channels:

Call Prints
ctx:respond(msg) A text component or string, as an indented line
ctx:info(text) Grey aesthetic » line
ctx:success(text) Green aesthetic » line
ctx:error(text) Red aesthetic » line

Completion

complete runs on every keystroke with the arguments typed so far. The last one is the word being completed, empty right after a space, so #args is its position. Return every candidate and the client filters by what is already typed.

commands.register({
    name = "tp",
    params = { { name = "player" } },
    execute = function(ctx, args)
        chat.command("tp " .. (args[1] or ""))
    end,
    complete = function(ctx, args)
        if #args ~= 1 then return {} end
        local names = {}
        for _, entry in ipairs(server.tablist.entries() or {}) do
            names[#names + 1] = entry.name
        end
        return names
    end,
})

Lifetime

A command belongs to the script that registered it: saving the file re-registers it, deleting the file removes it. To drop one earlier, keep the handle:

local cmd = commands.register({
    name = "debug",
    hidden = true,
    execute = function(ctx) ctx:info("still here") end,
})

cmd:unregister()

cmd:usage() returns the usage line with the current prefix, useful in a bad-argument reply.

Errors from execute land in chat with the lua » prefix like any script error. An error inside complete is reported once, then that completer goes quiet.

Navigation

Type to search…

↑↓ navigate↵ selectEsc close