What it does
- Scheduled posts: daily brief, weekly review, monthly review, in the household timezone.
- Commands:
/brief,/actions,/health,/fire,/cash,/spend,/calendar,/done,/todo. - Free-text questions go to a model with eight read-only tools over the same views. The assistant never writes; it tells you the slash command instead.
- Only the bound group and allow-listed senders get answers. Everything heard and said is logged to a table readable from Metabase.
How it is built
Signal has no bot API, so the bot runs its own Signal account through signal-cli wrapped in a REST sidecar. The account has its own phone number. After registration no phone is involved. Messages stay end to end encrypted.
The bot connects as a least-privilege bot_app role with a 15-second statement timeout. It writes to its own bot schema and to one completions table, nothing else. A transport layer keeps WhatsApp as a fallback behind one environment variable.
What it taught me
WhatsApp was the first transport. An adversarial review of the design made Signal the obvious choice: no account-ban risk for automation, end to end encryption by default, and a sidecar that is boring to operate. The review is in the repo.
Adding the bot's number to a group before it has ever messaged you leaves a pending invite the sidecar cannot accept. Have the bot message you once first, then add it.