Control macOS Calendar.app and Reminders.app from the CLI. Calendars/events (list, read, create, update, search, delete) and reminder lists/reminders (list, add, complete, delete, cleanup) with due dates, alarms, recurrence, priority, and JSON output. Zero install — built-in osascript; uses icalBuddy for fast calendar reads when present.
Scanned 9/5/2026
Install to Claude Code
npx -y skills add lidge-jun/cli-jaw-skills --skill jaw-calendar-reminders --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Jaw Calendar Reminders?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/lidge-jun-jaw-calendar-reminders)More formats (shields.io, HTML) on the badges page.
---
name: jaw-calendar-reminders
description: Control macOS Calendar.app and Reminders.app from the CLI. Calendars/events (list, read, create, update, search, delete) and reminder lists/reminders (list, add, complete, delete, cleanup) with due dates, alarms, recurrence, priority, and JSON output. Zero install — built-in osascript; uses icalBuddy for fast calendar reads when present.
metadata:
{
"openclaw":
{
"emoji": "📆",
"os": ["darwin"],
"requires": { "bins": ["osascript"] },
"optional_bins": ["icalBuddy"],
"install":
[
{
"id": "brew-icalbuddy",
"kind": "brew",
"formula": "ical-buddy",
"bins": ["icalBuddy"],
"label": "Optional: install icalBuddy for fast read-only calendar event queries",
},
],
},
"triggers": ["calendar", "캘린더", "apple calendar", "애플캘린더", "ical", "event", "일정", "schedule", "meeting", "약속", "reminder", "리마인더", "미리알림", "remind me", "to-do", "todo", "할일", "할 일", "due"],
}
---
# Apple Calendar + Reminders (macOS) Control
One skill to drive both **Calendar.app** and **Reminders.app** from the terminal.
Works on every calendar/list synced into macOS (iCloud, Google, Exchange,
CalDAV) — no API keys, no OAuth.
Verified pattern: **icalBuddy for fast calendar reads (when installed) +
osascript (AppleScript) for all writes.** Everything falls back to built-in
`osascript`, so the skill works with zero installs. Reminders are osascript-only.
## When to Use
- Calendar: user mentions "calendar"/"캘린더", an event/meeting/appointment.
- Reminders: user mentions a "reminder"/"미리알림", a personal to-do, or a task
with a due date synced to iPhone/iCloud.
## When to Use a Heavier Tool Instead
These scripts cover the common 90%. For the following, a native EventKit tool
such as [che-ical-mcp](https://github.com/PsychQuant/che-ical-mcp) (Swift MCP,
29 tools) is a better fit — note it requires a signed binary install:
- Writing attendees/organizer (AppleScript/EventKit exposes these read-only).
- Undo/redo of calendar operations.
- Geofence (location-triggered) reminders, structured lat/long locations.
- Per-event IANA timezone, conflict detection, duplicate detection, large batch
create/move with idempotency.
Recurring-occurrence-level edits (change one instance of a series) are also
limited here — treat the series as a whole or use the heavier tool.
## Operating Rules (follow for every write)
1. **Read → write → verify.** Before create/update/delete, do a bounded read of
the target window/list. After the write, read back and report the final state
(title, time, calendar/list).
2. **Confirm destructive or broad changes.** Deletes, cross-calendar moves, and
multi-item edits need explicit user confirmation. Title/name-based bulk
deletes require `--force`.
3. **Disambiguate duplicates.** If multiple items share a title, do not act on
"the one" — list candidates (use UID for events) and ask which.
4. **Make recurrence & timezone explicit.** Confirm RRULE and all-day/timezone
intent before writing recurring events; avoid silent defaults that drift
after DST.
5. **Minimal exposure.** Query only the window/fields needed; never dump entire
calendars for a narrow lookup. Data stays local — never send it to third
parties.
## Setup & Permissions
- macOS only. `osascript` is built in.
- **First run triggers a TCC permission prompt** for Calendar and/or Reminders.
Grant access under System Settings → Privacy & Security → Calendars /
Reminders for the controlling terminal/app.
- Optional calendar read speed-up: `brew install ical-buddy` (binary `icalBuddy`).
- Calendar names are matched **case-insensitively**; an unknown name errors with
the list of available calendars.
## Calendar Scripts
| Script | Purpose |
|--------|---------|
| `cal-list.sh` | List all calendar names |
| `cal-events.sh` | Read events (quick ranges, date range, `--json`) |
| `cal-add.sh` | Create an event (alarm, recurrence) |
| `cal-update.sh` | Edit an event by UID (selective fields) |
| `cal-search.sh` | Find events by summary substring (`--json`) |
| `cal-delete.sh` | Delete event(s) by UID or exact title (destructive) |
```bash
scripts/cal-list.sh
# Quick ranges + JSON
scripts/cal-events.sh today
scripts/cal-events.sh week --json
scripts/cal-events.sh --from 2026-06-29 --to 2026-07-06 --calendar "Home"
# Create with alarm (15 min before) and weekly recurrence
scripts/cal-add.sh --calendar "Home" --title "Standup" \
--start "2026-06-29 09:00" --end "2026-06-29 09:15" \
--alarm 15 --repeat "FREQ=WEEKLY;BYDAY=MO,WE,FR"
scripts/cal-add.sh --calendar "Home" --title "Holiday" --start "2026-07-04" --allday
# Edit by UID (only passed fields change)
scripts/cal-update.sh --calendar "Home" --uid "ABCD-1234" \
--start "2026-06-29 14:00" --end "2026-06-29 15:00" --location "Room 2"
scripts/cal-search.sh "standup" --calendar "Work" --json
scripts/cal-delete.sh --calendar "Home" --uid "ABCD-1234"
scripts/cal-delete.sh --calendar "Home" --title "Lunch" --force
```
Event dates accept `YYYY-MM-DD` or `YYYY-MM-DD HH:MM`. Omitting `--end` defaults
to start + 1 hour. `cal-add.sh` prints the new event UID; use it with
`cal-update.sh`/`cal-delete.sh`. JSON/osascript output uses sortable ISO dates.
## Reminder Scripts
| Script | Purpose |
|--------|---------|
| `rem-lists.sh` | List all reminder lists |
| `rem-list.sh` | List reminders (filters, sort, `--json`) |
| `rem-add.sh` | Create a reminder (list, due, notes, priority) |
| `rem-complete.sh` | Mark reminder(s) complete by exact name |
| `rem-delete.sh` | Delete reminder(s) by exact name (destructive) |
| `rem-cleanup.sh` | Delete completed reminders (dry-run by default) |
```bash
scripts/rem-lists.sh
scripts/rem-list.sh --list "Work"
scripts/rem-list.sh --overdue
scripts/rem-list.sh --completed
scripts/rem-list.sh --sort due --json
scripts/rem-add.sh --title "Buy milk"
scripts/rem-add.sh --title "Call mom" --list "Personal" --due "2026-06-29 18:00"
scripts/rem-add.sh --title "Submit report" --due "2026-07-02 17:00" --priority high
scripts/rem-complete.sh --title "Buy milk" --list "Personal"
scripts/rem-delete.sh --title "Buy milk" --force
scripts/rem-cleanup.sh # preview completed
scripts/rem-cleanup.sh --force # actually delete completed
```
Reminder `--due` accepts `YYYY-MM-DD` (defaults to 09:00) or `YYYY-MM-DD HH:MM`.
`--priority`: `none|high|medium|low` (or raw `0|1|5|9`). `rem-list.sh` filters:
default incomplete, `--all`, `--completed`, `--overdue`; sort with
`--sort due|title`. `rem-add.sh` prints the new reminder id.
## Destructive Operations
- `cal-delete.sh --uid` removes one event; `--title` removes **all** matching and
requires `--force`.
- `rem-delete.sh` matches by exact name, can remove multiple, requires `--force`.
- `rem-cleanup.sh` is **dry-run by default**; `--force` deletes all completed.
- Deletion is permanent — confirm intent with the user before running.
## Date Handling
Dates are built component-by-component in AppleScript (year/month/day/hour/
minute), avoiding locale-dependent string parsing; `day` is set to 1 first to
prevent month overflow. Read output (osascript/JSON path) is normalized to
sortable `YYYY-MM-DD HH:MM`. See `references/applescript-patterns.md` for the
raw AppleScript and extension points.
## Output Formats
- Default: tab-separated (TSV) rows for easy `cut`/`awk` piping.
- `--json` (on `cal-events.sh`, `cal-search.sh`, `rem-list.sh`): a JSON array of
objects with escaped values, for scripting/agent consumption.
## Limitations
- The osascript calendar-read fallback iterates calendars and can be slow over
wide ranges — install `icalBuddy` for fast reads (note: `--json` always uses
the osascript path for stable columns).
- Attendee/organizer writes, undo/redo, geofence reminders, per-event timezone,
and occurrence-level recurring edits are out of scope (see "When to Use a
Heavier Tool").
- Reminder match (complete/delete) is by **exact** name; read first, then act.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!