diff options
| author | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-05-21 18:56:19 +0200 |
|---|---|---|
| committer | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-05-21 18:56:19 +0200 |
| commit | 688779fbc61d48046199d1f45549720e289ce417 (patch) | |
| tree | 4ea8c13d96428176f97c0c27f665391c09a93098 /README.md | |
| parent | fb0fd67d6e7e55548c7a0a1ec67f608efffe3a94 (diff) | |
| download | xmppcb-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.md | 52 |
1 files changed, 48 insertions, 4 deletions
@@ -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) ``` |
