maubot-plugins/journal/README.md
Padreug b21ad2890f docs: add umbrella + journal READMEs
Root README orients new contributors on the build/upload/iterate
loop and points at ~/dev/CLAUDE.md for maubot patterns. journal/
README covers the three commands, the SQLite schema, known
quirks (edits don't re-trigger, subcommand detection scope), and
documents why this plugin uses @command.passive instead of the
more obvious @command.new.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 09:55:24 +02:00

2.6 KiB

journal

Daily-journal Matrix bot. Each room member can record what they did, and anyone in the room can query the log.

Commands

!journal <what you did>          record an entry (multi-line OK)
!journal show [@user:domain]     last 10 entries, optionally filtered by user
!journal today                   all entries from today (UTC)

Multi-line works either inline or after a newline:

!journal Did three things today:
- planted garlic
- mucked out the goat pen
- finished the irrigation patch
!journal
- planted garlic
- mucked out the goat pen

Both record the full body verbatim.

Storage

One SQLite database per maubot instance, at /var/lib/maubot/plugin-dbs/journal.db on the host. Schema (managed by mautrix.util.async_db.UpgradeTable):

CREATE TABLE entries (
    id   INTEGER PRIMARY KEY AUTOINCREMENT,
    user TEXT   NOT NULL,   -- @sender:domain
    room TEXT   NOT NULL,   -- !roomid:domain
    ts   BIGINT NOT NULL,   -- ms since epoch (from evt.timestamp)
    text TEXT   NOT NULL    -- raw entry body
);
CREATE INDEX entries_user_ts ON entries (user, ts DESC);
CREATE INDEX entries_ts      ON entries (ts DESC);

Wipe data via the maubot UI's per-instance Database tab:

DELETE FROM entries;
DELETE FROM sqlite_sequence WHERE name = 'entries';

(The second line resets the auto-increment counter; skip it if you'd rather keep IDs monotonic across resets.)

Known quirks

  • Edited messages don't re-trigger the bot. Matrix sends edits as a separate m.replace event that bots don't react to. If you typed !journal then edited the message to add content, the bot saw only the empty !journal and won't record. Send a fresh message instead of editing.
  • !journal show <random text> runs the show query with that text as the user filter. If it doesn't match any MXID, you get "No entries." Use a fully-qualified MXID like @pat:ariege.io.
  • Subcommand detection only looks at the first line. Anything starting with show or today on the first line dispatches to the query handlers; anything else (including prose that happens to contain "show" mid-text) records as an entry.

Architecture note

This plugin uses @command.passive with a regex matcher rather than @command.new. The reason — and why other plugins should consider the same pattern for prose-input commands — is documented in ~/dev/CLAUDE.md under "Multi-line freeform parent commands". Short version: @command.new silently drops !journal\n<content> because maubot's parser only treats space as the command/args delimiter, leading to invisible data loss when users naturally hit Enter after the command.