Getting Started
1. Create a file and declare a module
Create my-module.lua in <config>/aesthetic/scripts/ — the game can be running:
local module = ui.category("scripts"):module("code", "My Module")
ui.category(name)— GUI category:"combat","movement","visuals","player","misc"or"scripts".:module(icon, title[, description])— icon name (e.g."code","bolt","eye"— the editor autocompletes the full set) and the module title. The title must be unique across all modules.
2. Add settings
local delay = module:number("Delay", 20, 1, 100, 1, "t")
local text = module:string("Text", "hello")
local on = module:boolean("Enabled part", true)
Settings are read with :get() and show up in the module's GUI automatically.
All types are listed in Modules & Settings.
3. Subscribe to events
local ticks = 0
module:callback("enable", function()
ticks = 0
end)
module:event("tick", function()
ticks = ticks + 1
if on:get() and ticks % delay:get() == 0 then
client.print_chat(text:get())
end
end)
callback handles the lifecycle ("enable", "disable"), event handles game events
(see Events). Event names ignore case and underscores: render_2d and
render2d are the same.
4. Save and enable
Save the file — chat shows [lua] Loaded my-module.lua and the module appears in the
GUI. Enable it and keep editing: every save reloads the script while keeping your
setting values and the enabled state.
Editor support (autocomplete)
The mod generates language-server annotations for the whole API on every launch:
<config>/aesthetic/scripts/library/*.lua— LuaCATS stubs for all globals, events, settings and render canvases;<config>/aesthetic/scripts/.luarc.json— configuration pointing lua-language-server at them.
Open the scripts folder in an editor with lua-language-server — the
Lua extension in
VS Code, the SumnekoLua plugin in IntelliJ, or lua_ls in Neovim — and you get
completion, hovers, signature help and type checking out of the box, including event
names with typed callback arguments (module:event("render_2d", function(render) ...),
packet names and the full icon-name set.
The library/ folder is regenerated on every launch to match the installed mod version —
don't edit it. .luarc.json is only written when missing, so your own tweaks survive.
Debugging
print("a", value)andclient.print_chat(text)— output to chat ([lua]prefix);aesthetic.log(msg)— output to the game log;- callback errors print to chat and disable the module — fix and re-enable.
Shared libraries
require resolves files relative to the scripts folder. Only top-level .lua files
auto-load as scripts, so keep shared code in a subfolder:
local util = require "lib/util" -- <scripts>/lib/util.lua