78 lines
4.4 KiB
Markdown
78 lines
4.4 KiB
Markdown
---
|
||
name: remind
|
||
description: >
|
||
Create, list, edit, enable, disable, and remove recurring or one-time reminders.
|
||
Triggers on: "/remind", "remind me", "set a reminder".
|
||
---
|
||
|
||
# /remind
|
||
|
||
Reminders are stored in SQLite (`db/reminders.sqlite`) and delivered by `remind_send.py`,
|
||
which runs every minute from the nanobot user crontab, directly to Telegram, outside the agent.
|
||
Reply to the user in their own language.
|
||
|
||
## Natural language → command mapping
|
||
|
||
| User says | Command |
|
||
|-----------|---------|
|
||
| "every day at 9" / "every weekday at 9:30" | `add --cron "0 9 * * *"` |
|
||
| "on 2026-06-15 at 18:00" / "once at …" | `add --at "2026-06-15T18:00:00"` |
|
||
| "randomly 2× between 08:00 and 20:00" | `add --random-times-per-day 2 --random-window 08:00-20:00` |
|
||
| "randomly 2× a week between 08:00 and 20:00" | `add --random-times-per-week 2 --random-window 08:00-20:00` |
|
||
| "what reminders arrived today / since when" | `delivered [--since YYYY-MM-DD]` |
|
||
| "what goes out today / tomorrow / this week" | `upcoming [--date YYYY-MM-DD \| --days N]` |
|
||
| list all reminders | `list` |
|
||
|
||
For the full flag reference of any command, run:
|
||
|
||
```sh
|
||
uv run skills/remind/scripts/remind_cli.py --help
|
||
uv run skills/remind/scripts/remind_cli.py <command> --help
|
||
```
|
||
|
||
## Behavioral contract
|
||
|
||
**Showing read results.** `list`, `upcoming`, and `delivered` return text for the user — present it, never collapse to a count. For `list`, rewrite the raw output into a compact, readable form of your own: **one reminder per line**, schedules paraphrased to natural language (`30 9 * * 1-5` → "9:30 on weekdays"). Show **only enabled** reminders — skip disabled ones; keep each shown reminder's `#display-id` exactly as the CLI printed it (so `--id` still matches — gaps from skipped disabled ones are fine). Don't print the `[enabled]` marker.
|
||
|
||
**`list`** returns readable text. Each reminder:
|
||
|
||
```
|
||
#<display-id> text [enabled|disabled]
|
||
cron: 0 9 * * *
|
||
at: 2026-06-15T18:00:00
|
||
random: 2× daily 09:00–21:00 (1-5) from 2026-06-01
|
||
random: 2× weekly 08:00–20:00
|
||
```
|
||
|
||
An empty store prints `(no active reminders)`.
|
||
|
||
**Display IDs** (`#1`, `#2`, …) are sequential positions among active reminders, computed on the fly — never the internal DB id. They renumber after every `remove`, so always run `list` first when unsure. The internal DB id is never shown to the user; do not surface the `id` field from mutation JSON as `#…`.
|
||
|
||
A weekly random schedule fires `N` times across the week (Mon–Sun) on `N` distinct
|
||
random days, one random time each inside the window. `--random-days`/`--random-from`/
|
||
`--random-until` narrow the eligible days; a partial week at a from/until edge squeezes
|
||
the full weekly count into the days that remain (no proration).
|
||
|
||
**Mutations** (`add`, `edit`, `remove`, `enable`, `disable`) return JSON: `{"added": …}`, `{"edited": …}`, etc. Errors go to stderr with a non-zero exit code.
|
||
|
||
**Selecting a reminder:** `edit`, `remove`, `enable`, `disable` accept `--keyword` (case-insensitive substring) or `--id` (the **display ID** from `list`). An ambiguous keyword match returns `{"error": "ambiguous", "matches": [{"display_id": n, "text": …}]}` — retry with `--id <display-id>`. Run `list` to see current display IDs.
|
||
|
||
**`delivered`** reads the `reminder_fires` table (delivered rows only, Prague local time). Defaults to today; `--since YYYY-MM-DD` widens the window. The agent never sees deliveries happen — this is the only window into them.
|
||
|
||
**`upcoming`** returns readable text: each scheduled fire as `YYYY-MM-DD HH:MM #display-id text (type)`, sorted by time. The `#display-id` matches the one in `list`. It shows the *plan* (computed from the schedules), not actual deliveries — use `delivered` for those. Defaults to the rest of today; `--date` shows one whole day, `--days N` the next N calendar days. An empty window prints `(nothing scheduled in this window)`.
|
||
|
||
**`remove`** is a soft delete.
|
||
|
||
## Editing reminders
|
||
|
||
**To fix or change wording:** use `edit --id <display-id> --text "…"` (get the display ID from `list`),
|
||
or `edit --keyword <kw> --text "…"`.
|
||
**NEVER remove + re-add a reminder just to change its text** — that loses the delivery history and changes the id.
|
||
|
||
Use `--replace-schedules` (with at least one new `--cron`/`--at`/`--random-*`) only when you need to change the *schedule*, not the text.
|
||
|
||
## Environment
|
||
|
||
- `REMIND_DB` — override SQLite path (used in tests).
|
||
- Scripts run via `uv run` (PEP 723 headers declare their dependencies).
|