Skip to content

feat(vocabulary): the verb remind - #443

Merged
leemour merged 1 commit into
mainfrom
feat/vocabulary-remind
Nov 2, 2026
Merged

leemour merged 1 commit into
mainfrom
feat/vocabulary-remind

Conversation

@leemour

@leemour leemour commented Nov 2, 2026

Copy link
Copy Markdown
Collaborator

Task

gcal gets events remind, the last gap against gcalcli's remind: a command a scheduler (cron, a systemd timer) runs every few minutes. It tells the owner once about each event that starts soon.

Why

The unknown-verb lint refuses any verb that is not in the vocabulary, and no verb means "tell me once":

  • watch keeps a process running.
  • send writes to a chat.
  • The noun reminders already names the task reminders that have delivery receipts.

What

  • Adds the verb remind to src/standards/vocabulary.ts: "tell the owner once about what starts soon: print it, or run the owner's own program for it".
  • Adds a CHANGELOG entry under Unreleased.

No new flag. The window reuses --due-within <duration>, because WC-CMD-11 allows no new bare-minutes option.

Testing

pnpm lint, pnpm typecheck, pnpm test (971 tests) and pnpm docs:check pass.

🤖 Generated with Claude Code

`remind` tells the owner once about what starts soon: it prints it, or runs
the owner's own program for it. gcal's `events remind` is the first user,
run by cron or a systemd timer every few minutes, as gcalcli's `remind` is.
No existing verb fit: `watch` keeps a process running, `send` writes to a
chat, and `reminders` already names the task reminders with receipts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@leemour
leemour merged commit 91eae15 into main Nov 2, 2026
10 checks passed
@leemour
leemour deleted the feat/vocabulary-remind branch November 2, 2026 00:19
@leemour leemour mentioned this pull request Nov 2, 2026
leemour added a commit that referenced this pull request Nov 2, 2026
Dates the Unreleased section (the verb `remind`, #443) as 0.73.0. Only
package.json and the CHANGELOG heading change.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
leemour added a commit to WireCatLabs/cli-core that referenced this pull request Nov 2, 2026
…imer to run (#2367)

## Task
Close the last gcal gap against gcalcli `remind`. Research IDEA-15 asks
for a message to the owner before a meeting, with the meeting brief.

## Why
cron or a systemd timer can run one short command every few minutes.
Running that command needs no long-lived process and no new background
framework. The command is `events remind`. It is in cli-core so that
every calendar CLI gets it.

## What
- `events remind [--due-within 10m] [--dry-run] [-- <program> [args…]]`.
  - It syncs first, unless `--offline`.
- It takes the timed events that start within the window and are not
cancelled, not declined, and not focus, out-of-office or
working-location blocks.
  - It prints each event, or runs the owner's program once per event.
- **Security**
  - The program is spawned with `shell: false`.
- The event goes as JSON on stdin. Only `<PREFIX>_EVENT=event:<id>` and
`<PREFIX>_PROFILE` are added to its environment.
  - A program still running after 60 s gets SIGTERM, then SIGKILL.
- `events.remind.hook` is in `CALENDAR_WRITE_KEYS` and
`CALENDAR_WRITE_DEFAULTS` as `deny`, because `--yes` answers `ask`.
  - The read-only lock refuses the program form.
  - The command is `mcp: false`.
- **State**
- A 0600 checkpoint file per profile at
`checkpoints/<profile>/events-remind.json`, keyed by event id and start,
so a moved meeting is reminded again. It keeps one day of history.
- A file instead of a store table: a table would need store version 44,
which reaches every CLI.
  - A lock (`takeLock`) keeps overlapping runs from reminding twice.
- An event whose program fails is not kept. The next run retries it
(`remind.hook-failed`).
- A failed sync goes into `meta.issues` (`sync.failed` /
`sync.partial`), and the run reminds from the store.
- `ownsTime()` is taken out of the next-meeting rule in `prepare.ts` and
shared with `isMeeting`.
- Bumps cli-base to 0.73.0 for the verb `remind`
(WireCatLabs/cli-base#443). The peer range is now `>=0.73.0 <0.74.0`.

## Testing
- New tests in `src/calendar/cli/remind.test.ts` use the fake source,
the memory store and a fake clock. They cover:
  - each event is told once, and a moved event is told again;
  - `--offline` and `--dry-run`;
  - a failed sync;
  - the window bounds;
  - the hook is denied by default and refused under the read-only lock;
- stdin JSON and env, with a hostile `$(touch pwned)` title that does
not run;
  - a failed hook is retried;
  - a missing program answers exit 127;
  - the command is off MCP.
- `pnpm lint`, `typecheck`, the full `test` and `docs:check` pass
locally.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant