aboutsummaryrefslogtreecommitdiff
path: root/README.md
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-05-21 18:56:19 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-05-21 18:56:19 +0200
commit688779fbc61d48046199d1f45549720e289ce417 (patch)
tree4ea8c13d96428176f97c0c27f665391c09a93098 /README.md
parentfb0fd67d6e7e55548c7a0a1ec67f608efffe3a94 (diff)
downloadxmppcb-688779fbc61d48046199d1f45549720e289ce417.tar.gz
xmppcb-688779fbc61d48046199d1f45549720e289ce417.zip
Added support for user generated shell scripts:
- create a director with shell scripts - call them within the chat with @<script-name> - four sample scripts
Diffstat (limited to 'README.md')
-rw-r--r--README.md52
1 files changed, 48 insertions, 4 deletions
diff --git a/README.md b/README.md
index cbe2f8d..b5fc3fe 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,8 @@
# xmppcb
-A lean XMPP AI chatbot in C. It joins MUC rooms, logs messages, and
-answers `@bot` commands via an OpenAI-compatible LLM HTTP API.
+A lean XMPP AI chatbot in C. It joins MUC rooms, logs messages,
+answers `@bot` commands via an OpenAI-compatible LLM HTTP API, and runs
+`@scriptname` commands backed by local scripts.
A C reimplementation of the Python `bot.py` in the parent directory,
written in the suckless spirit: one source file, one library
@@ -94,10 +95,52 @@ In a joined room:
| `@bot summarize [period]` | Summarise the conversation |
| `@bot tasks [period]` | Extract action items |
| `@bot <question>` | Ask anything, using recent chat as context |
+| `@<name> [args]` | Run the script command `cmd/<name>` (see below) |
Period tokens: `1h 1d 2d 1w 2w 1m`. Without one, the last 50 messages
are used.
+## Script commands
+
+Besides the `@bot` builtins, any executable you drop into the `cmd/`
+directory becomes an `@<name>` command — no recompile, no restart.
+
+Example, `cmd/weather`:
+
+```sh
+#!/bin/sh
+# @weather [location] - current weather via wttr.in
+loc=$(printf '%s' "${1:-Krakow}" | tr ' ' '+')
+curl -fsS --max-time 8 "https://wttr.in/${loc}?format=3"
+```
+
+```sh
+chmod +x cmd/weather
+```
+
+Then in any joined room `@weather Wroclaw` makes the bot run the script,
+capture its output (stdout and stderr) and post it back. `@bot help`
+lists the script commands it finds.
+
+How it works and the safety boundaries:
+
+- The text after the command name is passed as **one argv element** —
+ `@weather New York` runs `cmd/weather "New York"`. The bot never hands
+ it to a shell, so there is no command injection; quote `"$1"` inside
+ your script and you are safe.
+- Command names allow only letters, digits, `-` and `_`, so they cannot
+ escape the `cmd/` directory.
+- A script is SIGKILLed after `CMD_TIMEOUT_SEC` seconds (default 10);
+ the bot is single-threaded, so it is paused meanwhile.
+- Output is capped at ~4 KB; longer output is truncated with `...[cut]`.
+- Unknown `@names` are ignored silently, so the bot does not react to
+ `@mentions` of people.
+
+Security: anyone in a joined room can run anything in `cmd/`. The
+command set is whatever lives in that directory — keep it curated, and
+do not let scripts print secrets. `CMD_DIR` and `CMD_TIMEOUT_SEC` are in
+`config.h`. Two example scripts ship in `cmd/`: `weather` and `uptime`.
+
## Run under a supervisor
The bot does not daemonise. Use a process supervisor so it restarts
@@ -127,8 +170,8 @@ Prefer an `EnvironmentFile=` with mode 600 over inline secrets.
## Notes and limitations
- The bot only sees messages sent while it is in the room.
-- LLM calls are blocking: the bot pauses for the few seconds a reply
- takes. Adequate for a low-traffic bot.
+- LLM calls and script commands are blocking: the bot pauses while a
+ reply or a `cmd/` script runs. Adequate for a low-traffic bot.
- The XML parser is intentionally narrow — it understands only the
XMPP stanzas this bot needs, not arbitrary XML.
- Resource use is small: ~37 KB binary, a few MB RSS.
@@ -144,6 +187,7 @@ xmppcb/
├── instruction.md system prompt in use (gitignored)
├── start.sample run-script template (committed)
├── start run script exporting the secrets (gitignored)
+├── cmd/ @scriptname command scripts (weather, uptime, fx)
├── makefile
└── history/ per-room chat logs (generated, gitignored)
```