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.

Stars 0
Forks 0

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

  1. Create a config file at ~/.config/calendar-skill/config.yaml:
yaml
default_timezone: "America/Chicago"
calendars:
  - name: "Work"
    type: ics
    url: "https://outlook.office365.com/.../calendar.ics"
    mode: read
  1. Query today's events:
bash
python -m calendar_skill events --start today --days 1

Configuration

Config File Locations

The skill searches for configuration in order:

  1. Path specified via --config flag
  2. ~/.config/calendar-skill/config.yaml
  3. .calendar-skill.yaml in current directory

Environment Variables

All settings can be set via environment variables with CALENDAR_ prefix:

bash
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:

yaml
# 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
bash
# .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

yaml
# 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

bash
# 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

bash
# 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

bash
# 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)

bash
# 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)

bash
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)

bash
calendar-skill delete --calendar "Work" --uid "event-uid"
calendar-skill delete --calendar "Work" --uid "event-uid" --force  # Skip confirmation

Utility Commands

bash
# List configured calendars
calendar-skill list-calendars

# Validate config and test connections
calendar-skill config-check

Agent Usage Patterns

Gathering Context for Daily Updates

bash
# 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

bash
# 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":

bash
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:

yaml
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)

  1. Open Outlook Calendar settings
  2. Find "Shared calendars" → "Publish a calendar"
  3. Select the calendar and copy the ICS link
  4. Add to config:
yaml
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":

  1. Open Google Calendar → Settings (gear icon)
  2. Click on the calendar name under "Settings for my calendars"
  3. Scroll to "Integrate calendar"
  4. Copy the "Secret address in iCal format"
  5. Add to config:
yaml
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:

  1. Enable 2-Step Verification in your Google Account
  2. Go to Security → App passwords → Generate a new app password
  3. Add to config:
yaml
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:

  1. Share your calendar and copy the share link (e.g., https://cloud.example.com/apps/calendar/p/ABC123)
  2. Convert to ICS URL: https://cloud.example.com/remote.php/dav/public-calendars/ABC123?export
  3. Add to config:
yaml
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:

  1. Generate an app password in Nextcloud: Settings → Security → Devices & sessions
  2. Find your calendar URL: usually https://cloud.example.com/remote.php/dav/calendars/USERNAME/CALENDAR_NAME/
  3. Add to config:
yaml
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

yaml
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:

yaml
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 --start and --end explicitly
  • 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:

bash
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:

  1. Check default_timezone in config
  2. Use --timezone flag to override
  3. 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:

  1. Convert the URL to the DAV export format
  2. Use /remote.php/dav/public-calendars/TOKEN?export instead

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

Expand your agent's capabilities with these related and highly-rated skills.

RyanTheRobothead/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.

0 0
Explore
RyanTheRobothead/skills

galahad

How to approach tests, types, lints, and coverage

0 0
Explore
RyanTheRobothead/skills

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.

0 0
Explore
mattpocock/skills

handoff

Compact the current conversation into a handoff document for another agent to pick up.

111,310 9,758
Explore
mattpocock/skills

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.

111,310 9,758
Explore
mattpocock/skills

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.

111,310 9,758
Explore

Didn't find tool you were looking for?

Be as detailed as possible for better results