Calendar Skill
Access calendar data from ICS files, CalDAV servers, and various calendar providers. Query events, check availability, and manage events on writable calendars.
Overview
| Feature | ICS | CalDAV |
|---|---|---|
| Query events | ✅ | ✅ |
| Expand recurrence | ✅ | ✅ |
| Free/busy lookup | ✅ (derived) | ✅ (native) |
| Create event | ❌ | ✅ |
| Update event | ❌ | ✅ |
| Delete event | ❌ | ✅ |
Provider Support:
- Outlook: ICS share links (read-only)
- Google Calendar: ICS share links (read-only) or CalDAV (read/write)
- Nextcloud: ICS share links (read-only) or CalDAV (read/write)
- Fastmail, iCloud, etc.: CalDAV (read/write)
Quick Start
- Create a config file at
~/.config/calendar-skill/config.yaml:
default_timezone: "America/Chicago"
calendars:
- name: "Work"
type: ics
url: "https://outlook.office365.com/.../calendar.ics"
mode: read
- Query today's events:
python -m calendar_skill events --start today --days 1
Configuration
Config File Locations
The skill searches for configuration in order:
- Path specified via
--configflag ~/.config/calendar-skill/config.yaml.calendar-skill.yamlin current directory
Environment Variables
All settings can be set via environment variables with CALENDAR_ prefix:
export CALENDAR_DEFAULT_TIMEZONE="America/New_York"
export CALENDAR_DEFAULT_OUTPUT_FORMAT="json"
Secrets
Passwords can be provided via:
- Config file (not recommended for sensitive data)
- Environment variables:
CALENDAR_CALENDARS__0__PASSWORD(index-based)
Recommended approach: Use environment variables for passwords:
# config.yaml
calendars:
- name: "Nextcloud"
type: caldav
url: "https://cloud.example.com/remote.php/dav/calendars/user/personal/"
mode: write
username: "user"
# password loaded from environment
# .env or shell
export CALENDAR_CALENDARS__0__PASSWORD="your-app-password"
Security tips:
- Always use app-specific passwords, never your main account password
- Revoke and regenerate app passwords if they may have been exposed
- Keep ICS "secret address" URLs private - they grant read access to anyone
Full Config Reference
# Timezone for all output (IANA format)
default_timezone: "UTC"
# Output format: "text" or "json"
default_output_format: text
calendars:
- name: "Display Name" # Required
type: ics | caldav # Required
url: "https://..." # Required (URL or file path)
mode: read | write # Default: read
username: "user" # For CalDAV auth
password: "secret" # For CalDAV auth
calendar_id: "primary" # For CalDAV with multiple calendars
CLI Reference
Query Events
# Today's events
calendar-skill events
# Next 7 days
calendar-skill events --days 7
# Specific date range
calendar-skill events --start 2026-01-27 --end 2026-01-31
# From specific calendar
calendar-skill events --calendar "Work" --days 3
# JSON output
calendar-skill events --format json
Free/Busy Lookup
# Check availability
calendar-skill freebusy --start "2026-01-27 09:00" --end "2026-01-27 17:00"
# Specific calendar
calendar-skill freebusy --start today --end tomorrow --calendar "Work"
Expand Recurring Events
# Get all instances of a recurring event
calendar-skill instances --uid "event-uid-123" --start 2026-01-01 --end 2026-03-01
Create Event (CalDAV only)
# Basic event
calendar-skill create --summary "Team Meeting" --start "2026-01-27 10:00" --duration 1h
# With details
calendar-skill create \
--calendar "Work" \
--summary "Project Review" \
--start "2026-01-27 14:00" \
--end "2026-01-27 15:30" \
--location "Conference Room A" \
--description "Quarterly project status review"
Update Event (CalDAV only)
calendar-skill update --calendar "Work" --uid "event-uid" --summary "New Title"
calendar-skill update --calendar "Work" --uid "event-uid" --start "2026-01-28 10:00"
Delete Event (CalDAV only)
calendar-skill delete --calendar "Work" --uid "event-uid"
calendar-skill delete --calendar "Work" --uid "event-uid" --force # Skip confirmation
Utility Commands
# List configured calendars
calendar-skill list-calendars
# Validate config and test connections
calendar-skill config-check
Agent Usage Patterns
Gathering Context for Daily Updates
# Yesterday's events (for "what I did")
calendar-skill events --start yesterday --end today --format json
# Today's events (for "what I'm doing")
calendar-skill events --start today --end tomorrow --format json
Checking Availability Before Scheduling
# Find free time for a meeting
calendar-skill freebusy --start "2026-01-27 09:00" --end "2026-01-27 18:00"
Creating Events from Natural Language
When a user says "Schedule a meeting with John tomorrow at 2pm for 30 minutes":
calendar-skill create \
--calendar "Work" \
--summary "Meeting with John" \
--start "2026-01-28 14:00" \
--duration 30m
Calendar Setup Guides
ICS Files (Local or Remote)
Any .ics file can be used as a read-only calendar source:
calendars:
- name: "Local Calendar"
type: ics
url: "~/calendars/personal.ics"
mode: read
- name: "Remote Calendar"
type: ics
url: "https://example.com/calendar.ics"
mode: read
Outlook (via ICS Share Link)
- Open Outlook Calendar settings
- Find "Shared calendars" → "Publish a calendar"
- Select the calendar and copy the ICS link
- Add to config:
calendars:
- name: "Outlook Work"
type: ics
url: "https://outlook.office365.com/owa/calendar/.../reachcalendar.ics"
mode: read
Google Calendar (via ICS - Read Only)
For read-only access, use Google Calendar's "Secret address in iCal format":
- Open Google Calendar → Settings (gear icon)
- Click on the calendar name under "Settings for my calendars"
- Scroll to "Integrate calendar"
- Copy the "Secret address in iCal format"
- Add to config:
calendars:
- name: "Google"
type: ics
url: "https://calendar.google.com/calendar/ical/YOUR_SECRET_URL/basic.ics"
mode: read
Note: Keep this URL private - anyone with it can read your calendar.
Google Calendar (via CalDAV - Read/Write)
For read/write access, use CalDAV with an app-specific password:
- Enable 2-Step Verification in your Google Account
- Go to Security → App passwords → Generate a new app password
- Add to config:
calendars:
- name: "Google"
type: caldav
url: "https://apidata.googleusercontent.com/caldav/v2/YOUR_EMAIL/events"
mode: write
username: "your-email@gmail.com"
password: "your-app-password"
Nextcloud (via ICS - Read Only)
Nextcloud public share links are web views, not ICS files. Use the DAV export URL:
- Share your calendar and copy the share link (e.g.,
https://cloud.example.com/apps/calendar/p/ABC123) - Convert to ICS URL:
https://cloud.example.com/remote.php/dav/public-calendars/ABC123?export - Add to config:
calendars:
- name: "Nextcloud Shared"
type: ics
url: "https://cloud.example.com/remote.php/dav/public-calendars/ABC123?export"
mode: read
Note: Public share links are read-only. For write access, use authenticated CalDAV.
Nextcloud (via CalDAV - Read/Write)
For full read/write access:
- Generate an app password in Nextcloud: Settings → Security → Devices & sessions
- Find your calendar URL: usually
https://cloud.example.com/remote.php/dav/calendars/USERNAME/CALENDAR_NAME/ - Add to config:
calendars:
- name: "Nextcloud"
type: caldav
url: "https://cloud.example.com/remote.php/dav/calendars/username/personal/"
mode: write
username: "username"
password: "app-password"
Tip: You can find the exact calendar URL in Nextcloud Calendar settings under "Copy private link".
Fastmail
calendars:
- name: "Fastmail"
type: caldav
url: "https://caldav.fastmail.com/dav/calendars/user/EMAIL/"
mode: write
username: "your-email@fastmail.com"
password: "app-password"
Generic CalDAV
Most CalDAV servers follow a similar pattern:
calendars:
- name: "CalDAV Server"
type: caldav
url: "https://caldav.example.com/calendars/username/"
mode: write
username: "username"
password: "password"
calendar_id: "calendar-name" # Optional
Troubleshooting
"No calendars configured"
Create a config file or set environment variables. Run calendar-skill config-check to verify.
Authentication Failed (CalDAV)
- Verify username/password are correct
- Many services require app-specific passwords (not your main password)
- Check that CalDAV access is enabled for your account
Events Not Appearing
- Check the time range: use
--startand--endexplicitly - Verify timezone settings match your calendar
- For ICS URLs, ensure the URL is accessible (try in a browser)
Recurring Events
By default, recurring events return the RRULE without expansion. Use the instances command to expand:
calendar-skill instances --uid "recurring-event-uid" --start 2026-01-01 --end 2026-12-31
Timezone Issues
All times are normalized to the configured timezone. If times seem off:
- Check
default_timezonein config - Use
--timezoneflag to override - Verify your calendar's timezone settings
Nextcloud Public Share Links
Nextcloud public share links (/apps/calendar/p/...) are web views, not ICS files. You need to:
- Convert the URL to the DAV export format
- Use
/remote.php/dav/public-calendars/TOKEN?exportinstead
Public shares are read-only. For write access, use authenticated CalDAV with an app password.
CalDAV "Node not found" Errors
If you get "Node with name 'X' could not be found" when creating events:
- The calendar URL may be incorrect - verify the full path to the calendar
- For Nextcloud: use
/remote.php/dav/calendars/USERNAME/CALENDAR_NAME/ - Check permissions - public shares typically don't allow writes