This page is CONTRIBUTING.md in the repository. The format in full: docs/02.
Contributing
The spec is docs/ and it wins over code; PLAN.md is the build order. Read CLAUDE.md for the rules every change follows — the short version: security boundaries live in code, the Worker never executes, nothing runs without a valid chore header, secrets never reach a model, a log or Telegram, every action is one journal line, and the bot speaks in docs/10-voice.md.
Running the tests
make test # gofmt, the dependency-surface checks, vet, every package
make test-linux # the same suite in a Linux container (SO_PEERCRED, ionice)
make test-relay # the relay against a Postgres container
make test-install # the install script in an Ubuntu 24.04 container
make weight # binary sizes and the idle footprint of both daemons
Report what the tests cover, not only that they pass. Never say a thing works if it was not run.
Writing a chore
Chores are bash files with a header, and a contributed one lands in chores/core/ beside the fourteen that ship. The full format is docs/02-chores.md. Ten lines of header, then the script:
# ---
# name: Journal vacuum
# verb: sweep
# os: linux
# safety: green
# touches: /var/log/journal
# needs: journalctl
# trigger: night
# params: days=14
# default: on
# author: core
# ---
set -euo pipefail
if [ "${AROMBA_DRY_RUN:-0}" = "1" ]; then journalctl --disk-usage; exit 0; fi
journalctl --vacuum-time="${P_days}d" >/dev/null
echo "kept_days=$P_days" >> "$AROMBA_RESULT"
echo "Journal: kept the last $P_days days" >> "$AROMBA_RECEIPT"
Rules the engine enforces, so write for them:
AROMBA_DRY_RUN=1reports what would happen and changes nothing. Every chore.- Running twice in a row changes nothing the second time.
- One
key=valueline inAROMBA_RESULT(freed=in bytes,moved=,updated=,alert=,event=) and one human line inAROMBA_RECEIPT. - Non-zero exit on unexpected state. The engine retries once the next night, then disables the chore and tells the user.
- Green means regenerable: before marking a chore green, say in one line why every file it touches can be regenerated with no user effort. Otherwise it is yellow — and yellow never deletes, it moves to quarantine.
touchesis a cage, not a comment: the chore runs with only those paths writable.
Every chore gets a <name>_test.sh beside it that runs in the CI container for each supported OS and asserts the receipt line and that nothing outside touches changed. Issues labeled good first chore list the ones we want first.
Pull requests
Small, one concern each; the title says what changed for the user, not the file. A new tool or command adds a row to the policy table and a redaction test. A new background loop states its cost in MB and CPU. Docs are the spec: when code and docs disagree, say so in the PR; do not pick silently.