accli — Apple Calendar CLI
accli manages Apple Calendar on macOS via EventKit. All commands support --json for structured output. Exit codes: 0=success, 1=runtime error, 2=validation error, 10=auth error.
Platform: macOS only (darwin). Uses osascript + EventKit. Do not run on non-macOS systems.
First run: accli setup to grant Calendar permissions. Full Calendar Access is required in System Settings > Privacy & Security > Calendars. This gives the agent read and write access to all calendars on the device — install only if you intend to delegate calendar management to the agent.
Agent Safety Rules
Before any create, update, or delete operation:
- Use
accli searchoraccli eventto confirm the correct event ID - Run the command with
--dry-runfirst and show the user the preview - Require explicit user confirmation before executing the real mutation
- Scope all operations to specific
--calendar-idvalues — never operate on all calendars unless the user explicitly requests it
For search and export:
- Always pass
--calendar-idand narrow--from/--toranges unless the user explicitly asks for a full export - Treat exported calendar data (summaries, locations, descriptions) as private — do not include it in summaries sent to third-party services
Calendars
accli calendars [--json]
Returns list of calendars with id, name, source, index, writable. Always prefer --calendar-id <id> over calendar name — IDs are stable, names are not.
Events
accli events [<calendarName>] [--calendar-id <id>] --from <date> --to <date> [--json]
Lists events in a date range. Calendar is required (use name, --calendar-id, or set a default via accli config set-default).
Single Event
accli event [<calendarName>] <eventId> [--calendar-id <id>] [--json]
Fetches full event detail including alerts array (minutes before start).
Create Event
accli create <calendarName> --summary <text> --start <datetime> --end <datetime> \
[--location <text>] [--description <text>] [--all-day] \
[--alert <minutes>] [--alert <minutes>] \
[--recur daily|weekly|monthly|yearly] [--recur-count <n>] [--recur-end <YYYY-MM-DD>] \
[--json]
--alertis repeatable — adds one alert per flag (minutes before start)--recur-endand--recur-countare mutually exclusive- All-day events: use
YYYY-MM-DDfor--startand--end - Timed events: use
YYYY-MM-DDTHH:mm - Always confirm with user before creating — calendar events cannot be easily bulk-undone
Update Event
accli update <calendarName> <eventId> \
[--summary <text>] [--start <datetime>] [--end <datetime>] \
[--location <text>] [--description <text>] \
[--alert <minutes>] [--alert <minutes>] \
[--dry-run] [--json]
--alert on update replaces all existing alerts. Omit --alert to leave alerts unchanged.
Mandatory dry-run flow:
accli update Work <id> --summary "New title" --dry-run --json # show user
accli update Work <id> --summary "New title" --json # only after user confirms
Delete Event
accli delete <calendarName> <eventId> [--dry-run] [--json]
Mandatory dry-run flow:
accli delete Work <id> --dry-run --json # show user what would be deleted
accli delete Work <id> --json # only after user confirms
Search
accli search --query <text> [--from <date>] [--to <date>] [--calendar-id <id>] [--json]
Case-insensitive search across summary, location, and description. Scope with --calendar-id and a narrow date range. Do not expose raw results to third-party services without user consent.
Export
accli export --from <date> --to <date> [--calendar-id <id>] [--json]
Exports all events grouped by calendar. Response: { calendars: [{ id, name, source, events, truncated }], totalEvents, truncated }. Each calendar truncates at 500 events and sets truncated: true if hit. Use narrow date ranges and specific calendar IDs unless the user explicitly requests a full backup.
Free/Busy
accli freebusy --from <datetime> --to <datetime> [--calendar-name <name>] [--json]
Returns busy time slots across calendars.
Config
accli config set-default --calendar-id <id> [--json]
accli config show [--json]
accli config clear [--json]
Persists default calendar to ~/.acclirc (override with ACCLI_CONFIG_PATH).
DateTime Formats
- Timed:
YYYY-MM-DDTHH:mmorYYYY-MM-DDTHH:mm:ss - Date-only (all-day events, --from/--to):
YYYY-MM-DD
Error Codes
| Code | Meaning |
|---|---|
NOT_AUTHORIZED | Calendar access not granted or set to Add Only |
CALENDAR_NOT_FOUND | Calendar ID or name not found |
AMBIGUOUS_CALENDAR | Multiple calendars with same name — use --calendar-id |
EVENT_NOT_FOUND | Event ID not found in calendar |
MISSING_REQUIRED | Required flag missing |
INVALID_ARGUMENT | Invalid flag value |
INVALID_RANGE | Start is after end |