Repository navigation
Creating custom commands
This page documents how to write and use BotWave's custom commands.
A custom command is a handler with a few key differences.
Like regular handlers, custom command files live in the handlers directory (/opt/BotWave/handlers by default). But instead of a .hdl or .shdl extension, they use .cmd, this keeps them visually distinct from event-driven handlers.
The first line of every custom command file must be a shebang in this format:
#!/<server|local|*>/<command_name>
-
servermakes the command available inbw-server,localinbw-local. Use*to make it available in both. -
<command_name>is the command's name as typed in the prompt. It must match the filename (without the extension).
BotWave loads every custom command on startup. They can also be loaded during runtime using the reload command.
In this part, we'll assume you have a Linux machine with BotWave server installed.
Let's start with a simple example. Create /opt/BotWave/handlers/hello.cmd:
sudo nano /opt/BotWave/handlers/hello.cmd#!/*/hello
# hello <word>
# Prints "Hello, <word>" with word as the first arg passed
< echo Hello, {BW_ARGV1}
In this example:
- The shebang on line 1 registers this as a command named
hello, available on both the local client and the server (*). - The
#block right after it is the help text. BotWave reads the first consecutive#block and uses it in thehelpcommand output. This block is optional but strongly recommended. -
<runs its arguments in a shell and prints the output. -
{BW_ARGV1}is replaced at runtime with the first argument passed to the command.BW_ARGV{n}variables are 0-indexed, soBW_ARGV1is the first user-supplied argument, not the command name itself (BW_ARGV0).
After saving, the command is immediately available:
botwave › help
[...]
hello <word> The hello custom command
[...]
botwave › hello world
Hello, world
botwave › hello "kitty kitty kitty"
Hello, kitty kitty kittyOne-liners work fine for simple cases, but the moment you need conditionals, loops, or proper error handling, it's cleaner to delegate to a shell script and use the .cmd file purely as a bridge:
/opt/BotWave/handlers/hello.cmd:
#!/*/hello
# hello <word>
# Prints "Hello, <word>" with word as the first arg passed
< bash /opt/BotWave/scripts/hello.sh/opt/BotWave/scripts/hello.sh:
#!/bin/bash
if [[ -z "$BW_ARGV1" ]]; then
echo "Syntax: hello <word>"
exit
fi
echo "Hello, $BW_ARGV1"Since BotWave exposes BW_ARGV{n} as real environment variables, your shell script can access them directly, no special syntax needed there.
botwave › hello
Syntax: hello <word>
botwave › hello :3
Hello, :3An alternative to < is the pipe command (|). Like <, it runs its argument in a shell, but instead of printing the output, it re-runs each output line as a BotWave command.
This is useful when you want a script to generate commands dynamically rather than just producing text. For example, a whitelist check that kicks unauthorized clients:
/opt/BotWave/scripts/whitelist.sh:
#!/bin/sh
WHITELIST="pi pi1 radpi"
FOUND=0
for h in $WHITELIST; do
if [ "$h" = "$BW_CLIENT_HOSTNAME" ]; then
FOUND=1
break
fi
done
if [ "$FOUND" -ne 1 ]; then
echo "kick ${BW_CLIENT_HOSTNAME} \"Not on whitelist\""
fi/opt/BotWave/handlers/wl.cmd:
#!/server/wl
# wl
# Runs the whitelist script
| sh /opt/BotWave/scripts/whitelist.shEach line the script prints gets executed as a BotWave command. In this case, if the client isn't on the whitelist, the script outputs a kick command, which BotWave then runs.
You can also use it for something as simple as feeding a command list from a file:
| cat commands.txt
Running exit inside a custom command stops that command right there: the remaining lines are skipped, and BotWave keeps running. It does not shut down the server or local client.
This is handy for guard checks. For example, BW_REMOTE_CLIENT_IP is empty when a command is typed in the BotWave prompt, and set to the sender's IP when it comes from the remote shell. A script can use that to refuse to run remotely:
/opt/BotWave/scripts/localonly.sh:
#!/bin/sh
if [ -n "$BW_REMOTE_CLIENT_IP" ]; then
echo "< echo \"This command can only be used locally\""
echo "exit"
fi/opt/BotWave/handlers/kickall.cmd:
#!/server/kickall
# kickall
# Kicks every client, local use only
| sh /opt/BotWave/scripts/localonly.sh
kick all "Kicked by the host"# typed in the BotWave prompt
botwave › kickall
(every client gets kicked)
# sent through the remote shell
botwave › kickall
This command can only be used locallyWhen kickall is run remotely, the script prints the echo and exit lines. The echo line runs, then exit stops the command, so kick all never runs. When it's run locally, the script prints nothing and the command carries on.
Two formats are supported for the # block that follows the shebang.
The v0 format (shown above) is a loose #-prefixed block: the first line becomes the syntax, the rest becomes the long help. It's quick to write and fine for personal, one-off commands.
For anything you're releasing as a plugin (see For Developers/Creating a plugin) or want to show up cleanly in help <command>, use the v2 format instead: it enforces a stricter structure so syntax, short help, and long help are parsed unambiguously rather than guessed from line position.
A file is auto-detected as v2 if it contains any #> or #? line, so don't mix formats in the same file.
v2 syntax:
-
#> keyword "value": metadata lines. Supported keywords:-
short_help(required): one-line summary, shown in thehelpcommand list -
syntax(optional): argument syntax, without the command name. Wrap required args in<>, and optional ones in[]
-
-
#? ...: help lines, arbitrary content. These become the long help shown byhelp <command>. At least one#?line is required. A v2 file with only metadata and no#?lines will fail to parse.
Let's take the hello.cmd built above and update it to match the v2 format:
#!/*/hello
#> syntax "<word>"
#> short_help "Displays 'Hello, <word>' in the output"
# lines with a regular # are now treated as regular comments
# the following lines are shown in 'help hello':
#? Displays 'Hello, <word>' when executed.
#?
#? Examples:
#? - hello marc
#? - hello "world!"
< bash /opt/BotWave/scripts/hello.shWith this new format, the help command shows more information:
botwave › help
[...]
hello <word> Displays 'Hello, <word>' in the output
[...]
botwave › help hello
› hello <word>
Displays 'Hello, <word>' when executed.
Examples:
- hello marc
- hello "world!"BotWave by DPIP Studio | Website