Lua
Your first script
Lua · Updated 09 November 2026
Set up, write a script table with a manifest, and run it.
Lua scripts run in bwu_host, the BotWithUs native host, which embeds Lua 5.4. LuaJIT and Lua 5.1 to 5.3 are not supported.
Setup
- Nothing to install.
bwu_hostbrings its own Lua 5.4 and thebotwithuslibrary. - Put your scripts in
~/.botwithus/scripts/lua(%USERPROFILE%\.botwithus\scripts\lua). That is the folder thebwu_hostGUI lists.
The script table
A Lua script is a file that builds a script table and returns it:
local bot = require("botwithus")
local TREE_IDS = { [38782] = true, [38783] = true, [38785] = true, [38787] = true }
local OBJECT_OPTION_1 = 3
local CHOP_TICKS = 5
local script = {
manifest = { name = "Woodcutter", author = "example", version = "1.0.0" },
}
function script.on_start(ctx)
local me = ctx.game:self()
io.write(("woodcutter: starting at %s (cb %d)\n"):format(tostring(me.tile), me.combat_level))
end
function script.on_loop(ctx)
local me = ctx.game:self()
local tree = bot.objects(ctx.game):where(function(o) return TREE_IDS[o.id] end):nearest(me.tile)
if not tree then
io.write("woodcutter: no tree nearby; stopping\n")
return -1
end
ctx.game:do_action({ id = OBJECT_OPTION_1, p1 = tree.id, p2 = tree.tile.x, p3 = tree.tile.y })
io.write(("woodcutter: chopping tree %d at %s\n"):format(tree.id, tostring(tree.tile)))
return CHOP_TICKS
end
function script.on_stop(ctx)
io.write("woodcutter: stopped\n")
end
if select("#", ...) == 0 then
bot.run(script)
end
return script
The action { id = 3, p1 = loc id, p2 = x, p3 = y } is "object option 1" ("Chop down" on a tree). Like a click, it makes the client walk the player to the tree first.
The manifest
manifest = { name, version, author, description, category }. Every field is optional, but each one that is set must be a string (version = 1.0 is refused; write "1.0"). The limits, in bytes:
| Field | Default | Length |
|---|---|---|
name |
the file name | 1 to 128 |
version |
"1.0" |
1 to 64 |
author |
"" |
0 to 128 |
description |
"" |
0 to 4096 |
category |
none | 1 to 64 |
Use one of the Java host's category names, such as Skilling, Combat or Woodcutting, to group the script in the GUI.
The self-run guard
The last lines of the example matter:
if select("#", ...) == 0 then
bot.run(script)
end
return script
- When
bwu_hostruns the file directly, it calls it with no arguments, so the script runs itself. - When the GUI loads the file to list it, or another file
requires it, there is an argument. The file then only returns its table.
Without the guard, listing the script in the GUI would start it. Attaching to a client while the file is being listed fails with attach during load: guard the self-run.
Running it
In the GUI. Start bwu_host with no arguments. It lists the .lua files in ~/.botwithus/scripts/lua by their manifests and runs each one in a worker process of its own against the client you pick.
From a console.
bwu_host --lua $HOME\.botwithus\scripts\lua\woodcutter.lua
On the command line a script gets its default settings, and no stop request reaches it. It ends when on_loop returns a negative number, when it fails, or when its client exits.