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

- Skill: `luckierdodge/calendar` (Agent Skill, multi-file: 33 files)
- Install (CLI): `npx skillmds@latest add luckierdodge/calendar`
- Raw SKILL.md: https://api.skillmd.com/api/skills/luckierdodge/calendar/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Productivity
- Author: LuckierDodge (https://skillmd.com/u/luckierdodge)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/luckierdodge/calendar

---


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

2. 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

