Skill: Remind Me
When to use
- User says "remind me to...", "set a reminder", "set an alarm"
- User says "every Monday at 9 AM...", "every 30 minutes check..."
- User says "in 20 minutes tell me...", "at 3 PM send me..."
- User wants to schedule a recurring cron job via chat
- User says "cancel my reminder", "delete that cron", "stop the alert"
- User says "list my reminders", "what reminders do I have?"
- User wants to know what cron jobs are active in this chat
When NOT to use
- User wants to check a stock price right now (not scheduled) → use
stock-price-checker-pro - User wants to run a one-time task immediately (no scheduling involved)
⚠️ CRITICAL: Always resolve these FOUR things before creating a reminder
Before calling the script, you MUST have all four resolved:
| Field | Question to answer | Example | |---|---|---| | WHAT | What should happen / be said? | "Check NVDA stock price" | | WHEN / HOW OFTEN | One-time or recurring? At what time/interval? | "Every Monday at 9 AM" | | WHERE | Which channel + chat ID to deliver to? | Auto-detected from session | | TIMEZONE | What timezone should times be interpreted in? | Auto-detected from USER.md |
Missing field rules
- WHAT is missing → Ask: "What would you like me to remind you about?"
- WHEN is missing AND cannot be reasonably assumed → Ask: "How often, or at what time?"
- WHEN is missing BUT can be reasonably assumed as once → Assume one-shot, but confirm: "Just once, right?"
- WHERE is always auto-detected → Never ask the user for this. Read it from session context (see below).
- TIMEZONE is always auto-detected → Never ask unless unresolvable (see Step 2 below).
Do NOT create the job until all four are confirmed.
Step 1 — Auto-detect channel, chat ID, and timezone from context
Channel and chat ID
The source channel and chat ID are available in your session context. Extract them before doing anything else.
- channel: the platform the message arrived on (e.g.
telegram,discord) - chatId / to: the specific chat or user ID within that platform (e.g.
<chatId>)
These two values are passed as --channel and --to to the script.
Never ask the user for these. Never hardcode them. Always read from session context.
Timezone — 3-tier resolution (in priority order)
Resolve the user's timezone using this exact priority chain:
| Priority | Source | How to read it |
|---|---|---|
| 1 | Message itself | User says "at 9 AM London time" or "remind me at 3 PM EST" → extract from their words |
| 2 | USER.md | Read the Timezone: field from /root/.openclaw/workspace/USER.md |
| 3 | Ask the user | Only if tiers 1 and 2 both fail — ask once, then offer to save it |
Rules:
- If tier 1 applies → use it directly, no need to check USER.md
- If tier 2 applies → use it silently, do not mention it to the user
- If tier 3 triggers → ask: "What timezone are you in? (e.g. London, New York, Lagos)" — then offer: "Want me to remember your timezone for future reminders?" If they say yes, update
USER.md - The resolved timezone is passed as
tz:<IANA>to the script - If no timezone can be resolved at all, pass
tz:UTCand mention it in the confirmation summary
Step 2 — Parse the user's intent
From the user's natural language request, extract:
Schedule type
Map what the user said to one of three prefixed schedule strings.
⚠️ When the user states a clock time (e.g. "9 AM", "3 PM", "noon"), always interpret it in their resolved timezone (from Step 1), not UTC. The
--tzflag passed to the script ensures cron expressions fire at the correct local time.
| What user said | Schedule string to pass |
|---|---|
| "every 30 minutes" | every:30m |
| "every hour" | every:1h |
| "every day at 9 AM" | cron:0 9 * * * |
| "every Monday at 9 AM" | cron:0 9 * * 1 |
| "weekdays at 8 AM" | cron:0 8 * * 1-5 |
| "every Friday at 5 PM" | cron:0 17 * * 5 |
| "in 20 minutes" | at:20m |
| "in 2 hours" | at:2h |
| "at 3 PM today" | at:<computed duration from now> |
| "once at 9:30 AM tomorrow" | at:<computed duration from now> |
One-shot vs recurring
at:→ always one-shot (--onceis auto-set by the script)every:orcron:→ recurring by default- If user says "just once" or "one time" with a
cron:orevery:→ pass--once
Job name
Generate a short, descriptive name from the user's request.
- "Remind me to check NVDA every Monday" →
"NVDA Check - Monday 9AM" - "Alert me in 20 minutes" →
"Alert - 20min" - "Grocery reminder at noon" →
"Groceries - Noon"
Message
The message is what the agent will say or do when the job fires. Craft it clearly so the agent knows exactly what to do:
- "Remind me to do groceries" →
"Reminder: Time to do groceries! 🛒" - "Check NVDA every Monday at 9 AM" →
"Check the current NVDA stock price and send me a summary." - "Send me a motivational quote every morning" →
"Send me an inspiring motivational quote to start the day."
Step 3 — Clarification rules (ask before acting)
Ask when:
-
No schedule at all: "Remind me to call John" → no time/frequency given
Ask: "Sure! When would you like me to remind you — just once at a specific time, or on a recurring schedule?"
-
Ambiguous frequency: "Remind me often" or "check regularly"
Ask: "How often? Every hour, every day, or something else?"
-
Conflicting signals: "Remind me every Monday but just once"
Ask: "Just to confirm — should this be a one-time reminder or repeat every Monday?"
Do NOT ask when:
- Everything is clear: "Remind me every Monday at 9 AM to check NVDA" → create immediately
- One-shot is obvious from context: "Remind me in 20 minutes" → at:20m, once
- User confirms after your clarification question → proceed immediately
Confirmation before creating (always):
Before calling the script, summarise what you're about to set up and get a quick confirmation:
"Got it! Here's what I'll set up: ⏰ Reminder: Check NVDA stock price 🔁 Schedule: Every Monday at 9 AM 🌍 Timezone: Africa/Lagos (UTC+1) 📱 Delivered to: This chat
Shall I go ahead?"
Always include the Timezone line in the confirmation summary. If falling back to UTC because none was found, say so clearly:
🌍 Timezone: UTC (no timezone found — times will be in UTC)
Only proceed after user confirms.
Commands
Create a reminder
uv run /root/.openclaw/workspace/skills/remind-me/src/main.py create \
"<job name>" \
"<what to say or do>" \
"<every:duration | cron:expr | at:duration>" \
"<channel>" \
"<chatId>" \
[once] \
[tz:<IANA timezone>]
tz:is optional but always include it when a timezone was resolved (tiers 1–2)- Pass
tz:UTCexplicitly when falling back — makes the stored description accurate - Examples:
tz:Africa/Lagos,tz:America/New_York,tz:Europe/London,tz:Asia/Kolkata - Common short names are accepted:
tz:EST,tz:IST,tz:CET,tz:Lagos,tz:London
List reminders for this chat
uv run /root/.openclaw/workspace/skills/remind-me/src/main.py list \
"<channel>" \
"<chatId>"
Cancel a reminder by name
uv run /root/.openclaw/workspace/skills/remind-me/src/main.py cancel name "<job name>"
Cancel a reminder by ID
uv run /root/.openclaw/workspace/skills/remind-me/src/main.py cancel id "<job id>"
Examples
Example 1 — Clear request, no clarification needed
User: "Remind me every Monday at 9 AM to check NVDA"
- Detect: channel=telegram, to=<chatId>
- Read USER.md → Timezone: Africa/Lagos → resolves to
Africa/Lagos - Parse: WHAT="Check NVDA stock price", WHEN=cron:0 9 * * 1, one-shot=false
- Confirm with user (include timezone line)
- Run:
uv run /root/.openclaw/workspace/skills/remind-me/src/main.py create \
"NVDA Check - Monday 9AM" \
"Check the current NVDA stock price and send me a summary." \
"cron:0 9 * * 1" \
"telegram" \
"<chatId>" \
"tz:Africa/Lagos"
Example 2 — Missing frequency, ask first
User: "Remind me to go do groceries by 12 PM"
- Detect: channel=telegram, to=<chatId>
- Read USER.md → Timezone: Africa/Lagos → resolves to
Africa/Lagos - Parse: WHAT="Do groceries", WHEN=12 PM but frequency unclear
- Ask: "Just to confirm — is this a one-time reminder for today at noon, or should I remind you every day at 12 PM?"
- User says: "Just today"
- Compute duration from now to today's noon in Africa/Lagos time → e.g.
at:3h30m - Confirm (include timezone line), then run:
uv run /root/.openclaw/workspace/skills/remind-me/src/main.py create \
"Groceries - Noon" \
"Reminder: Time to go do groceries! 🛒" \
"at:3h30m" \
"telegram" \
"<chatId>" \
once \
"tz:Africa/Lagos"
Example 3 — List reminders
User: "What reminders do I have?"
uv run /root/.openclaw/workspace/skills/remind-me/src/main.py list \
"telegram" \
"<chatId>"
Format the output as a readable list, not raw JSON. Example response:
You have 2 active reminders in this chat:
NVDA Check - Monday 9AM 🔁 Every Monday at 9 AM "Check the current NVDA stock price..." 🌍 Timezone: Africa/Lagos (UTC+1) Next run: Mon 10 Mar 2026, 09:00
Groceries - Noon (one-time) "Time to go do groceries!" 🌍 Timezone: Africa/Lagos (UTC+1) Runs in: 3h 30m
Example 4 — Cancel a reminder
User: "Cancel my NVDA reminder"
- List jobs for this channel/chat first (internally)
- Find the matching job by name
- Confirm: "Cancel NVDA Check - Monday 9AM? This will stop all future runs."
- User confirms
- Run:
uv run /root/.openclaw/workspace/skills/remind-me/src/main.py cancel name "NVDA Check - Monday 9AM"
Example 5 — One-shot in-chat reminder
User: "In 30 seconds send me a love letter"
at:schedules are duration-based (relative to now), so timezone does not affect when they fire. Still passtz:so it is stored in the job description for consistency.
uv run /root/.openclaw/workspace/skills/remind-me/src/main.py create \
"Love Letter - 30s" \
"Write a beautiful, heartfelt love letter. Make it romantic and touching." \
"at:30s" \
"telegram" \
"<chatId>" \
"tz:Africa/Lagos"
Example 6 — Timezone in message, no USER.md entry
User: "Remind me every day at 8 AM New York time to drink water"
- Detect: channel=telegram, to=<chatId>
- Tier 1 hit: "New York time" → resolves to
America/New_York— no need to check USER.md - Parse: WHAT="Drink water", WHEN=cron:0 8 * * *, one-shot=false
- Confirm with user
- Run:
uv run /root/.openclaw/workspace/skills/remind-me/src/main.py create \
"Drink Water - 8AM NY" \
"Reminder: Time to drink water! 💧" \
"cron:0 8 * * *" \
"telegram" \
"<chatId>" \
"tz:America/New_York"
Example 7 — No timezone anywhere, ask user
User: "Remind me every day at 7 AM to exercise"
- Detect: channel=telegram, to=<chatId>
- Tier 1: no timezone in message
- Tier 2: USER.md Timezone field is empty
- Tier 3: Ask — "What timezone are you in? (e.g. London, Lagos, New York)"
- User says: "Lagos"
- Resolve:
Africa/Lagos - Offer: "Want me to remember Lagos time for future reminders?"
- If yes → update USER.md:
Timezone: Africa/Lagos - Confirm, then run:
uv run /root/.openclaw/workspace/skills/remind-me/src/main.py create \
"Exercise - 7AM" \
"Reminder: Time to exercise! 💪" \
"cron:0 7 * * *" \
"telegram" \
"<chatId>" \
"tz:Africa/Lagos"
Channel scoping rules
- Jobs created from Group A are only visible when listing from Group A
- Jobs created from Group B are only visible when listing from Group B
- Jobs created from the main/private chat are visible only in that main chat
- The script handles this automatically via the
[remind-me:channel:chatId]tag embedded in each job's description - Never show a user jobs that belong to a different chat
Output formatting
After running any command, always format the result in plain conversational language — never dump raw JSON to the user.
On create success:
✅ Done! I've set up your reminder: ⏰ NVDA Check — Every Monday at 9 AM 📱 Delivered to this chat
On list (empty):
You have no active reminders in this chat.
On cancel success:
✅ Reminder "NVDA Check - Monday 9AM" has been cancelled.
On error:
❌ Something went wrong:
<error message>Want me to try again?
Notes
uv runauto-installs dependencies from the inline script header — no pip or venv needed.- The script calls
openclaw cronCLI internally — the gateway must be running. - Always use
--channel "last"behaviour naturally: since--tois set to the originating chat ID, delivery is always back to the right place. - Do NOT use sessions_spawn, web search, or any other tool to create cron jobs — always go through this script.
- Do NOT hardcode channel IDs. Always read from session context.
- The
at:schedule prefix does not support standard cron expressions — usecron:for those.
微信扫一扫