Event Subscriptions
Use the cremind skill-events CLI to list and delete subscriptions, simulate events, and manage a skill's listener daemon.
A skill's listener drops events into events/<event_type>/, but those events only become useful once they're routed somewhere. A subscription binds an event type (from a skill) to a conversation, so that when the event fires the agent runs in that conversation. The cremind skill-events CLI (alias cremind events) is how you inspect subscriptions, tail live events, test events without their real trigger, and control the listener daemons.
Every operation here has a control on the Skill Events page of the Cremind web UI (Sidebar → Skill Events). The CLI is the terminal-side counterpart. CREMIND_TOKEN is required for every subcommand.
Inspecting what a skill can emit
Before subscribing, see which events a skill declares (read from its SKILL.md events map):
cremind skill-events events <skill>This prints the array of {type, description} objects — exactly what the Subscribe dialog in the UI populates from.
Subscriptions are created in the UI
The CLI does not have a subscribe subcommand. Subscriptions are created when a skill is bound to a conversation in the web UI; the CLI then lists, simulates, and deletes them.
Listing and deleting subscriptions
List the subscriptions for the active profile:
cremind skill-events listIt renders a table — subscription ID, the owning SKILL, the EVENT_TYPE it matches, and the CONVERSATION it routes into (with its title). The ID is what delete and simulate take.
Remove a subscription so its events stop being routed:
cremind skill-events delete <id>Simulating an event
simulate drops a markdown file into a subscription's watched events folder, firing an event as if the real trigger had occurred. This is the fastest way to develop and dry-run an event handler without waiting on a real email, calendar change, or webhook.
The body is read from stdin:
# From a file
cremind skill-events simulate <id> --filename morning-brief.md < morning.md
# From a heredoc
cremind skill-events simulate <id> <<'EOF'
# PR opened
- Author: li
- Repo: cremind
EOF--filename is optional; omit it and a unique simulate-*.md name is chosen. The skill's listener daemon then picks up the dropped file and routes it through the normal event pipeline.
The listener must be running
If simulate is silent and nothing happens, the listener for that skill probably isn't running — the dropped file is only picked up by a live listener. Check listener-status and start it if needed.
Tailing live events
Two long-lived Server-Sent Events streams let you watch events arrive. Both print one line per event and exit cleanly on Ctrl-C.
Server-wide admin snapshot — every change to any subscription, listener status, or routed event:
cremind skill-events streamPer-profile notifications — the same badges shown on the web UI sidebar:
cremind skill-events notificationsBoth default to a table line of [<event_type>] <raw JSON payload>. Pass the root --json flag to emit just the raw JSON payload per line, which is ideal for piping into jq:
cremind skill-events notifications --json | jq '.summary'Resuming after a disconnect
notifications accepts a --since resume cursor in Unix milliseconds. The server backfills any notifications recorded at or after that timestamp before going live, so you can reconnect without losing events:
cremind skill-events notifications --since 1746201600000Notifications are not retained forever — if --since reaches past the server's retention window, no backfill is produced, but the live tail still works.
Managing the listener daemon
The listener daemon is what actually watches the source and posts events back. Start (or resume) it as an autostart process so it relaunches at server boot:
cremind skill-events listener-start <skill>This is idempotent — calling it against an already-running listener returns the existing process and autostart ids without duplicating. It prints the process_id (use with cremind proc attach) and the autostart_id (delete with cremind proc autostart delete to undo).
Check whether the daemon is alive, via its most recent heartbeat:
cremind skill-events listener-status <skill>The output reports running (yes/no), the last_heartbeat, the backing autostart_id, and the exact command the listener runs as.
A worked loop
Inspect, subscribe in the UI, confirm, then dry-run:
# What does the skill emit?
cremind skill-events events daily-brief
# (create the subscription in the UI, binding it to a conversation)
# Confirm it appears, then fire a test event
cremind skill-events list
cremind skill-events simulate sub_19a8 <<'EOF'
# Morning brief
- Top issue: cremind#42
EOFBring a stale listener back to life:
cremind skill-events listener-status daily-brief # running no
cremind skill-events listener-start daily-brief
cremind skill-events listener-status daily-brief # running yesTroubleshooting
| Symptom | Likely cause |
|---|---|
stream / notifications exit immediately | Auth issue — confirm cremind me works first. |
simulate is silent, nothing fires | The skill's listener isn't running — check listener-status. |
| No notifications though the skill should have fired | Listener down; or the subscription's conversation was deleted; or the skill's event_type changed and the subscription no longer matches (re-create it). |
--since returns nothing | The cursor reaches past the retention window — the live tail still works. |
| Listener won't start | A stale autostart row may block it — cremind proc autostart list, then delete the stale id. |
Event Listeners
How a skill's long-running listener subscribes to the Cremind Connect relay and drops external changes as markdown events.
Local Tokens & Secrets
How skill credentials and OAuth tokens stay on your machine, where they live on disk, and how skill configuration flows through scripts/.env.