Agendactl
Read & write the local macOS Calendar app and Reminders app on this Mac (Apple EventKit, iCloud-synced) via the bundled `agendactl` CLI. Use this skill for any request to add, list, view, change, reschedule, complete, or delete a calendar event or a reminder/to-do on this machine — e.g. "remind me to send the report", "what meetings do I have this week", "move the standup to Wednesday", "mark it done", "cancel that event", "what's on tomorrow" — even when the words "calendar" or "reminder" aren't used. This is macOS-native Apple Calendar/Reminders, not Google, Outlook, or Feishu/Lark, and not a generic task app. Always drive it through `agendactl` with arguments; never write osascript/AppleScript/JXA or shell out to these apps another way. Calendar = timed events with a start/end interval (no "complete"); reminders = to-dos with a due date that can be completed — route by intent.From its SKILL.md
npx -y skills add henrywen98/agendactl --skill agendactlAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
9.0 KB, ~2.4k tokens by cl100k_base, as published. Nobody here has run it
macOS Calendar & Reminders automation (agendactl)
Drive macOS Calendar and Reminders by calling the agendactl CLI. Only call commands and pass
arguments — authorization, time zones, stable ids, and validation (end > start, etc.) are all
handled inside the CLI. Whatever the CLI does not expose is simply not available; do not route
around it by writing scripts.
Running agendactl
The binary ships inside this skill at scripts/agendactl. Resolve it in this order:
- If
agendactlis onPATH, just callagendactl. - Otherwise, run the bundled binary using this skill's own directory — the absolute path of the
folder this
SKILL.mdwas loaded from — e.g.~/.claude/skills/agendactl/scripts/agendactlor~/.pi/agent/skills/agendactl/scripts/agendactl. Resolvescripts/agendactlagainst the skill directory, NOT against the current working directory (the cwd is usually the user's project, not this skill). No install step beyond having the skill folder is required.
Subcommands and flags are identical either way. Do not find the whole disk for it, and do not
substitute another tool (Google Calendar, Outlook, Feishu/Lark, or a separate task app): this drives
the Apple Calendar.app / Reminders.app on this Mac (iCloud-synced), and only agendactl reads that
data.
Design notes (read first)
- Responses carry meta. Every
agendactlresponse has_at/_tz/_iso/_noteat the top level._atis the moment the CLI ran (meta), NOT the item'sstart/end/duetime. The underscore prefix marks meta; bare names are data._notespells this out. - Get "today" from the response, not from context. When the user says "today / tonight /
tomorrow", read the date from any
agendactlresponse's._isofield (e.g.2026-06-29). Do not calldatefor it and do not guess — the host's reported "today" can be stale or wrong, and writing an event to yesterday drops it out of the calendar view. - CLI-only. Only call
agendactl <app> …with arguments. Never write code; never use osascript/AppleScript/JXA or touch EventKit directly — for macOS Calendar/Reminders,agendactlis the tool, even for a one-liner. If something is not reachable, say "not supported yet" rather than inventing it. - List the containers before writing. Run
calendars/listsfirst to get the real container names (the response also returns_iso, handy for building "today").
Calendar vs Reminders — route correctly
-
Concept. CALENDAR = a schedule entry (meeting/event, has a
start/endinterval, has location/notes, has no "complete" concept — it exists or it is deleted). REMINDERS = a to-do (has aduetime, can be completed). -
Go to calendar when the user says "add a meeting" / "what's on this week" / "3–4pm" (an interval) / "cancel that event" / anything with a start–end span.
-
Go to reminders when the user says "remind me" / "to-do" / "mark complete" / "what do I have to do today" / any to-do concept.
-
Easy to confuse:
- "What's on this week" / "what meetings this week" → calendar (a schedule).
- "What do I have to do today" / "today's to-dos" → reminders (things to do).
- "Meeting at 3 tomorrow" → calendar (a meeting, an interval).
- "Remind me to be at the 3pm meeting" → reminders (the user said "remind" = a to-do not to forget; do not also create a calendar event).
-
Command map (same verbs, different prefix — don't cross them):
action calendar reminders list containers agendactl calendar calendarsagendactl reminders listslist items agendactl calendar list-eventsagendactl reminders listcreate agendactl calendar create-eventagendactl reminders createupdate agendactl calendar update-event <id>agendactl reminders update <id>complete (none — events have no "complete"; use delete-event)agendactl reminders complete <id>delete agendactl calendar delete-event <id>agendactl reminders delete <id>
Calendar commands
| command | purpose |
|---|---|
agendactl calendar calendars | list all calendars: name + id + writable. Run before any write. |
agendactl calendar list-events [--calendar <name>] [--from <iso>] [--to <iso>] [--limit <n>] | list events (default next 30 days), returns {…meta, items:[...]} |
agendactl calendar create-event --calendar <name> --summary <title> --start <iso> --end <iso> [--location <text>] [--notes <text>] [--all-day] | create an event, returns one with id |
agendactl calendar update-event <id> [--summary] [--start] [--end] [--location] [--notes] | update (fields not given stay unchanged) |
agendactl calendar delete-event <id> | delete an event |
<id> comes from list-events / create-event. --end must be later than --start (else
exit 1); when changing only one end, keep the order valid.
Reminders commands
| command | purpose |
|---|---|
agendactl reminders lists | list all lists: name + id + writable. Run before any write. |
agendactl reminders list [--list <name>] [--status incomplete|completed|all] [--due today|<iso>] [--limit <n>] | list reminders (default incomplete), returns {…meta, items:[...]} |
agendactl reminders create --list <name> --name <text> [--notes <text>] [--due <iso>] [--priority 0-9] | create a reminder, returns one with id |
agendactl reminders update <id> [--name] [--notes] [--due] [--priority] [--complete] | update (fields not given stay unchanged) |
agendactl reminders complete <id> | mark complete |
agendactl reminders delete <id> | delete |
Priority: 0=none, 1–4=high, 5=medium, 6–9=low (Apple's convention). --status defaults to
incomplete.
Dates
- Input ISO 8601:
2026-06-29T09:00:00(no tz suffix = local time);2026-06-29is also accepted. Output is UTC ISO (withZ). - For relative dates ("today / tomorrow / the day after"), first read
._isofrom any response for "today", then do calendar arithmetic with macOS BSDdate—date -j -f "%Y-%m-%d" -v+1d "$ISO" +%Y-%m-%dfor "tomorrow" (note: BSD-j -f -v, not GNUdate -d).agendactlitself accepts only full ISO 8601, never expressions like "tomorrow".
Example — "review tomorrow 3–4pm":
RESP=$(agendactl calendar calendars) # real calendar name (+ _iso)
ISO=$(echo "$RESP" | jq -r ._iso)
CAL=$(echo "$RESP" | jq -r '.items[] | select(.writable) | .name' | head -1)
TOMORROW=$(date -j -f "%Y-%m-%d" -v+1d "$ISO" +%Y-%m-%d)
agendactl calendar create-event --calendar "$CAL" --summary "Review" \
--start "${TOMORROW}T15:00:00" --end "${TOMORROW}T16:00:00"
Standard workflow (required for writes)
- List containers first (
calendars/lists) to get real names — don't guess ("Personal" vs "个人", duplicate "Holidays" calendars write to the wrong place). - Call
create/update/complete/delete. - Compound filtering (e.g. "events over 1 hour this week", "today's high-priority to-dos"):
coarse-filter with
--from/--to/--list/--status/--due, then refine in context yourself — the CLI does not do complex queries. - After writing, re-read with
list/list-eventsto confirm. - Confirm with the user before bulk deletes, then delete one by one.
Exit codes (judge by these, don't guess)
| code | meaning | what to do |
|---|---|---|
| 0 | success | read the JSON on stdout |
| 1 | usage/arg error | read stderr, fix the arguments |
| 2 | name/id not found | pick from stderr's available:; or run calendars/lists first |
| 3 | not authorized | have the user grant Full Access in System Settings → Privacy & Security → Calendars / Reminders |
| 4 | runtime error | read the reason on stderr |
On failure, stderr's first line is agendactl: <reason>.
Not covered (say "not supported yet", don't invent)
- Calendar: attendees/invites, room booking, shared-calendar permissions, recurrence-rule editing.
- Reminders: subtasks, attachments, structured URL/flag read-write.
What ships with it: 3 files
305.8 KB alongside SKILL.md, 2 of them executable
scripts/
- agendactlruns286.9 KB
- agendactl.swift17.8 KB
- build.shruns1.1 KB