| name | apple-reminders |
| description | Read, brief on, capture, and safely change tasks in the native Apple Reminders app through the on-device `apple-reminders` command. Use this skill whenever the user asks about their reminders, to-dos, or tasks — daily or weekly briefings, what is overdue or due today, unscheduled inbox items, adding or capturing a new task, rescheduling a due date, changing priority, moving a task to another list, marking things done, cleaning up a list, or finding a specific reminder. Trigger it even when the user never says "reminder": "what's on my plate today", "add milk to my shopping list", "push that to Friday", "what did I miss this week", "clear out the done stuff", "브리핑", "할 일", "미리알림", "오늘 뭐 해야 해", "장바구니에 추가", "마감 지난 것", "提醒事项", "待办", "今天要做什么", "リマインダー", "タスク". Also trigger when the user asks for something Reminders cannot do through this command (tags, sections, attachments, flags, subtasks, recurring reminders) so the limitation is reported accurately instead of guessed.
|
| compatibility | iOS only. Requires the built-in `apple-reminders` native command and granted Reminders permission; the command is not registered on Android. No external dependencies, no scripts, no network.
|
Apple Reminders
Overview
apple-reminders is a built-in native command backed by EventKit. It exposes five
verbs — list, create, update, complete, delete — over reminder titles,
due dates, lists, priorities, notes, and completion state. Every call prints one
JSON envelope to stdout.
The command is small, but three of its behaviours fail silently and successfully:
a mistyped list name, an unparseable due date, and a truncated read all return
ok: true. Most of this skill exists to keep those three from turning into wrong
answers or misplaced tasks. Read references/cli.md for the full contract — flags,
JSON shapes, error codes, and the exact date grammar.
apple-reminders list [--incomplete|--completed] [--list <name>] [--limit <N>]
apple-reminders create --title <t> [--due <dt>] [--list <name>] [--priority <0-9>] [--notes <text>]
apple-reminders update --id <id> [--title <t>] [--due <dt>] [--list <name>] [--priority <0-9>] [--notes <text>]
apple-reminders complete --id <id> [--undo]
apple-reminders delete --id <id>
Add --compact to minimize JSON, -q to print only the data field. Prefer
--compact for large reads to save context.
Run apple-reminders --help when you are unsure whether an option still exists —
the help text is authoritative for the build you are running, and this reference may
lag it.
The command is iOS-only. If it is not on PATH, say that reminder access is not
available on this device. Do not reach for a workaround: there is no supported path
to Reminders data outside this command, so do not try to install an adapter, script
around it, or read Reminders storage directly.
Three checks before any write
These are not style preferences. Each one prevents a wrong result that the command
itself reports as success.
1. Resolve the exact list title from a read. Never pass a guessed name.
--list matches by case-insensitive substring, so --list Work also matches
Workout, and when several titles match, EventKit's calendar order decides which
one wins — not you. Worse, on create an unmatched --list is not an error: the
reminder is silently saved to the default list and the response still says
ok: true. So read first, pick the exact title, then write, then confirm the
list field in the response is the list you intended.
Empty lists never appear in list output, because list titles are only observable
through the reminders inside them. If the user names a list you cannot find, say it
is either empty or nonexistent — do not create the task somewhere else and hope.
2. Compute due dates as absolute local datetimes yourself.
Accepted forms are YYYY-MM-DD, YYYY-MM-DDTHH:MM, YYYY-MM-DDTHH:MM:SS
(interpreted in the device's local timezone), and full ISO 8601 with an offset or
Z. Relative offsets are accepted only into the past (-7d, -2h, -30m);
there is no +3d form.
Anything else — tomorrow, next Monday, +1d, 3d, 내일 — fails to parse, and
a failed parse is dropped without an error: the reminder is created or updated
with no due-date change and the command still exits 0. So resolve the user's
wording into a concrete date and time before you build the command, and state the
date you chose in your answer so a misreading is visible.
Two consequences worth knowing: YYYY-MM-DD alone becomes 00:00 local, since this
command has no all-day form; and create does not echo due back, so after any
create --due you must read the reminder back to confirm the date actually landed.
update does echo due, so its own response is the confirmation.
3. Treat a truncated read as "I have not seen the data yet".
--limit defaults to 100, and result order is not guaranteed — so a truncated read
is an arbitrary subset, not the first 100 by date. When data contains
_warning and total_available, you cannot say anything about the whole set:
"nothing is overdue" may simply mean the overdue items were outside the window.
Re-run with a narrower scope (--incomplete, --list <exact title>) or with
--limit above total_available, then answer. Say so if you deliberately answer
from a bounded scope.
Workflow
- Read the real state first. Ground every answer in actual titles, list names,
due dates, and completion state. For briefings use one
--incomplete read;
--incomplete includes reminders with no due date, which is what you want for
an inbox view.
- Normalize time language into explicit dates, times, and weekdays before
reasoning or writing. Use the device's local timezone.
- Keep reads bounded by list, completion state, and limit — the three filters
that exist. There is no date-range or text-search filter, so date grouping and
keyword matching happen on your side, after the read.
- Target writes by
id only. Get id from a list read. Never write against
a title you have not resolved to a single id. If several reminders share a
title, disambiguate by list, due date, or notes, and name which one you chose.
- Verify after writing.
update and complete return post-write state — read
it, don't assume. create returns only id, title, and list, so verify due
date, priority, and notes with a follow-up read when they matter. Never treat a
zero exit status or a bare ok: true as proof the change landed the way you
intended: all three silent failures above exit 0 and report success.
- Report the exact affected set — titles, lists, and dates — not a count.
- Do not retry a failed write blindly. Check
error.code first:
authorization_denied needs the user to grant Reminders access in Settings, and
retrying will not help; invalid_args means fix the command; no_data means the
id no longer resolves — re-read before concluding the reminder is gone.
Write safety
This skill supports standing delegation — a user who has told you to act on their
reminders without checking in each time has granted it, and asking again on every
write makes the skill useless for the exact people who want it. So when standing
delegation applies, execute high-impact writes without stopping for a separate
confirmation.
Delegation removes the prompt, not the evidence. Every delegated write must
still be bounded to a target set you enumerated from a read, verified by read-back,
and reported afterward with the exact items affected — that report is what makes the
change reviewable after the fact, which is the whole basis for skipping the prompt.
When standing delegation does not apply, restate the qualifying set and scope before
writing.
Preserve everything the user did not ask to change. update is a patch: flags you
omit are left untouched, so pass only the fields you intend to change. Never send a
field "to be safe".
Match the care to how recoverable each verb is:
complete is fully reversible with complete --id <id> --undo. Lowest risk.
Prefer completing over deleting when the user's intent is "this is done", and
when they say "clear" or "clean up", ask which they mean if it is not obvious
from context — the two are not equivalent and only one is undoable.
update overwrites the previous value with no undo. Capture the current
value from your read before patching, and report old → new so the user can
reverse it manually.
delete is the only irreversible verb here. This skill cannot guarantee
whether a deletion made through this command is recoverable from the Reminders
app's Recently Deleted, so do not tell the user it is. Before deleting, capture
title, list, due, priority, and notes, and include them in your report
so the reminder can be recreated by hand if the deletion was wrong.
- Bulk changes need an enumerated target set before the first write, never a
filter applied blindly. Keep batches small enough to report individually. If any
single write returns
ok: false, stop and report what has already been applied —
do not continue through the rest of the batch, because a partially applied bulk
change that is reported as complete is far harder to recover from than a stopped
one.
Priority is inverted and unvalidated: 1 is the highest, 5 is medium, 9 is the
lowest, 0 is none. Map the user's words to that scale (high → 1, medium → 5,
low → 9) and never pass a number the user gave you as if it were a 1–10 ranking.
Ids from update, complete, and delete are resolved by scanning the whole
reminder store with a 10-second cap. On a large store, a no_data "Reminder not
found" can be that timeout rather than a missing reminder — re-read before telling
the user their reminder is gone.
Output conventions
Name the list for every reminder when location matters, and use exact dates with
weekdays (Fri 2026-08-07) rather than "in 3 days". A missing or null due date
means unscheduled, not undated-and-fine.
A due time of exactly 00:00 is most likely an all-day reminder created in the
Reminders app, not a midnight deadline — all-day items surface as T00:00:00 here
and cannot be told apart from timed midnight ones. Present those as a date, and
never "fix" one by writing a time onto it.
Do not surface a reminder's notes unless the user asked for them or they are
needed to tell two otherwise identical candidates apart. Notes routinely hold
private detail — medical, financial, personal — that the user did not ask to have
read back, and a briefing is not a reason to print it. Keep raw JSON, ids, and
local file paths out of the user-facing answer too; use them, don't display them.
For briefings, build the groups yourself from one --incomplete read, using the
device's local timezone and skipping groups that are empty:
- Overdue — due before today's local midnight, oldest first
- Due today — due on today's local date, including times already past
- Upcoming — "this week" means after today through the coming Sunday; "the next
seven days" means a rolling seven-day window. State which basis you used
- Unscheduled — no due date. Show at most 20, grouped by list, and report how
many more were omitted, because an unscheduled inbox can be enormous
- Cleanup candidates — long-overdue or clearly stale items, only when asked
Keep it short and actionable. If your read was truncated or deliberately scoped, say
so in one line rather than implying the briefing is complete.
What this command cannot do
Report these plainly when asked. Do not simulate them, do not write them into
--notes as a silent substitute, and do not report success for something you did
not do — the honest limitation is more useful than a fake feature.
| Requested | Status |
|---|
| Sections within a list | Not exposed |
| Tags / hashtags | Not exposed |
| Flag a reminder | Not exposed |
| Image or URL attachments | Not exposed |
| Subtasks | Rejected with not_available — iOS has no public API for it |
| Creating or deleting a list | Not exposed; ask the user to create it in the Reminders app first |
| List emoji or color | Not exposed |
| All-day due dates | Not exposed; a date-only value becomes 00:00 local |
| Recurring reminders | Not exposed |
| Alarms, location or messaging triggers | Not exposed; this command sets a due date, and whether a notification fires is up to the Reminders app |
| Listing empty lists | Not observable — list titles only appear via reminders inside them |
| Filtering by date range or search text | Not exposed; read bounded, then filter your side |
When a request needs one of these, offer the closest honest alternative — a note in
--notes, a priority instead of a flag, a separate list the user creates — and let
the user decide. Do not invent a subcommand or flag to cover the gap. If the user
wants the capability itself, point them at filing a feature request on the Minis
repository rather than leaving them thinking it exists.
Examples
Daily briefing. "What's on my plate today?"
apple-reminders list --incomplete --limit 200 --compact
Check _warning; if present, raise --limit above total_available and re-read.
Then group into Overdue / Due today / Upcoming / Unscheduled, naming each list.
Capture into a named list. "Add pick up prescription to my errands list, Friday 6pm"
Read first to resolve the exact list title, compute the absolute datetime, create,
then confirm the list field came back as the list you intended and read the due
date back:
apple-reminders list --incomplete --limit 200 --compact
apple-reminders create --title "Pick up prescription" --list "Errands" --due 2026-08-07T18:00
apple-reminders list --list "Errands" --incomplete --compact
Reschedule. "Push the tax filing task to next Monday."
Resolve the id from a read, patch only --due, and use the returned due as
confirmation. Report Wed 2026-08-05 → Mon 2026-08-10.
Ambiguous list name. The user says "work list" and the read shows both Work
and Workout. Do not pass --list work; it would match by substring and the
winner is unpredictable. Pass the exact title you determined, or name both and ask
which one when the reminder's content does not settle it.
Unsupported request. "Attach this screenshot to the visa reminder."
Say the on-device command has no attachment support, so you cannot do it from here;
offer to reference the file path in the reminder's notes instead, and mention that
attaching it by hand in the Reminders app is the only way to get a real attachment.