Agent skill
calendar
Access calendars via ICS files/URLs and CalDAV servers. Query events, check availability, and manage events on writable calendars. Supports Outlook, Google Calendar, and Nextcloud.
Install this agent skill to your Project
npx add-skill https://github.com/RyanTheRobothead/skills/tree/main/skills/calendar
SKILL.md
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
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
daily-update
Draft a daily standup update using a user-specified template and gathered context. Use when preparing for standups, writing async status updates, or summarizing daily progress. Supports context from calendar events, task/issue trackers, free-form notes, and Obsidian daily notes.
galahad
How to approach tests, types, lints, and coverage
code-ratchets
Implement code quality ratchets to prevent proliferation of deprecated patterns. Use when (1) migrating away from legacy code patterns, (2) enforcing gradual codebase improvements, (3) preventing copy-paste proliferation of deprecated practices, or (4) setting up pre-commit hooks to count and limit specific code patterns. A ratchet fails if pattern count exceeds OR falls below expected—ensuring patterns never increase and prompting updates when they decrease.
handoff
Compact the current conversation into a handoff document for another agent to pick up.
setup-pre-commit
Set up Husky pre-commit hooks with lint-staged (Prettier), type checking, and tests in the current repo. Use when user wants to add pre-commit hooks, set up Husky, configure lint-staged, or add commit-time formatting/typechecking/testing.
obsidian-vault
Search, create, and manage notes in the Obsidian vault with wikilinks and index notes. Use when user wants to find, create, or organize notes in Obsidian.
Didn't find tool you were looking for?