🎁 Get the FREE AI Skills Starter Guide β€” Subscribe β†’
BytesAgainBytesAgain
πŸ¦€ ClawHub

Caldav

by @chakyiu

Manage CalDAV calendars and events, with special support for Radicale server. Use when the user wants to create, update, delete, or query calendar events, ma...

Versionv1.0.0
Downloads990
Installs1
TERMINAL
clawhub install caldav-skill

πŸ“– About This Skill


name: caldav description: Manage CalDAV calendars and events, with special support for Radicale server. Use when the user wants to create, update, delete, or query calendar events, manage calendars, or configure/administer a Radicale CalDAV server. homepage: https://github.com/python-caldav/caldav metadata: clawdbot: emoji: "πŸ“…" requires: bins: ["python3"] env: []

CalDAV & Radicale Management

Interact with CalDAV servers (calendars, events, todos) and manage Radicale server configurations.

Overview

CalDAV is a protocol for accessing and managing calendaring information (RFC 4791). Radicale is a lightweight CalDAV/CardDAV server. This skill enables:

  • Calendar CRUD operations (create, list, update, delete)
  • Event management (create, update, delete, query)
  • Todo/task management
  • Radicale server configuration and administration
  • Prerequisites

    Python Library

    Install the caldav library:

    pip install caldav
    

    For async support:

    pip install caldav[async]
    

    Environment Variables (Recommended)

    Store credentials securely in environment or config:

    export CALDAV_URL="http://localhost:5232"
    export CALDAV_USER="your_username"
    export CALDAV_PASSWORD="your_password"
    

    Or use a config file at ~/.config/caldav/config.json:

    {
      "url": "http://localhost:5232",
      "username": "your_username",
      "password": "your_password"
    }
    

    Scripts

    Calendar Operations

    # List all calendars
    python3 {baseDir}/scripts/calendars.py list

    Create a new calendar

    python3 {baseDir}/scripts/calendars.py create --name "Work Calendar" --id work

    Delete a calendar

    python3 {baseDir}/scripts/calendars.py delete --id work

    Get calendar info

    python3 {baseDir}/scripts/calendars.py info --id work

    Event Operations

    # List events (all calendars, next 30 days)
    python3 {baseDir}/scripts/events.py list

    List events from specific calendar

    python3 {baseDir}/scripts/events.py list --calendar work

    List events in date range

    python3 {baseDir}/scripts/events.py list --start 2024-01-01 --end 2024-01-31

    Create an event

    python3 {baseDir}/scripts/events.py create \ --calendar work \ --summary "Team Meeting" \ --start "2024-01-15 14:00" \ --end "2024-01-15 15:00" \ --description "Weekly sync"

    Create all-day event

    python3 {baseDir}/scripts/events.py create \ --calendar personal \ --summary "Birthday" \ --start 2024-02-14 \ --allday

    Update an event

    python3 {baseDir}/scripts/events.py update \ --uid "event-uid-here" \ --summary "Updated Title"

    Delete an event

    python3 {baseDir}/scripts/events.py delete --uid "event-uid-here"

    Search events by text

    python3 {baseDir}/scripts/events.py search --query "meeting"

    Todo Operations

    # List todos
    python3 {baseDir}/scripts/todos.py list [--calendar name]

    Create a todo

    python3 {baseDir}/scripts/todos.py create \ --calendar work \ --summary "Complete report" \ --due "2024-01-20"

    Complete a todo

    python3 {baseDir}/scripts/todos.py complete --uid "todo-uid-here"

    Delete a todo

    python3 {baseDir}/scripts/todos.py delete --uid "todo-uid-here"

    Radicale Server Management

    # Check Radicale status
    python3 {baseDir}/scripts/radicale.py status

    List users (from htpasswd file)

    python3 {baseDir}/scripts/radicale.py users list

    Add user

    python3 {baseDir}/scripts/radicale.py users add --username newuser

    View Radicale config

    python3 {baseDir}/scripts/radicale.py config show

    Validate Radicale config

    python3 {baseDir}/scripts/radicale.py config validate

    Check storage integrity

    python3 {baseDir}/scripts/radicale.py storage verify

    Direct HTTP/DAV Operations

    For low-level operations, use curl with CalDAV:

    # Discover principal URL
    curl -u user:pass -X PROPFIND \
      -H "Depth: 0" \
      -H "Content-Type: application/xml" \
      -d '' \
      http://localhost:5232/

    List calendars

    curl -u user:pass -X PROPFIND \ -H "Depth: 1" \ -H "Content-Type: application/xml" \ -d '' \ http://localhost:5232/user/

    Query events by time range

    curl -u user:pass -X REPORT \ -H "Depth: 1" \ -H "Content-Type: application/xml" \ -d ' ' \ http://localhost:5232/user/calendar/

    Create calendar (MKCALENDAR)

    curl -u user:pass -X MKCALENDAR \ -H "Content-Type: application/xml" \ -d ' New Calendar ' \ http://localhost:5232/user/new-calendar/

    Radicale Configuration

    Config File Location

    Radicale looks for config in:

  • /etc/radicale/config (system-wide)
  • ~/.config/radicale/config (user)
  • Custom path via --config or RADICALE_CONFIG env
  • Key Configuration Sections

    [server]
    hosts = localhost:5232
    max_connections = 20
    max_content_length = 100000000
    timeout = 30
    ssl = False

    [auth] type = htpasswd htpasswd_filename = /etc/radicale/users htpasswd_encryption = autodetect

    [storage] filesystem_folder = /var/lib/radicale/collections

    [rights] type = owner_only

    Authentication Types

    | Type | Description | |------|-------------| | none | No authentication (development only!) | | denyall | Deny all (default since 3.5.0) | | htpasswd | Apache htpasswd file | | remote_user | WSGI-provided username | | http_x_remote_user | Reverse proxy header | | ldap | LDAP/AD authentication | | dovecot | Dovecot auth socket | | imap | IMAP server authentication | | oauth2 | OAuth2 authentication | | pam | PAM authentication |

    Creating htpasswd Users

    # Create new file with SHA-512
    htpasswd -5 -c /etc/radicale/users user1

    Add another user

    htpasswd -5 /etc/radicale/users user2

    Running as Service (systemd)

    # Enable and start
    sudo systemctl enable radicale
    sudo systemctl start radicale

    Check status

    sudo systemctl status radicale

    View logs

    journalctl -u radicale -f

    iCalendar Format Quick Reference

    Events use iCalendar (RFC 5545) format:

    BEGIN:VCALENDAR
    VERSION:2.0
    PRODID:-//Example Corp//CalDAV Client//EN
    BEGIN:VEVENT
    UID:unique-id@example.com
    DTSTAMP:20240115T120000Z
    DTSTART:20240115T140000Z
    DTEND:20240115T150000Z
    SUMMARY:Team Meeting
    DESCRIPTION:Weekly sync
    LOCATION:Conference Room
    END:VEVENT
    END:VCALENDAR
    

    Common Properties

    | Property | Description | |----------|-------------| | UID | Unique identifier | | DTSTART | Start time | | DTEND | End time | | DTSTAMP | Creation/modification time | | SUMMARY | Event title | | DESCRIPTION | Event description | | LOCATION | Location | | RRULE | Recurrence rule | | EXDATE | Excluded dates | | ATTENDEE | Participant | | ORGANIZER | Event organizer | | STATUS | CONFIRMED/TENTATIVE/CANCELLED |

    Date Formats

    # DateTime with timezone
    DTSTART:20240115T140000Z  ; UTC (Z suffix)
    DTSTART;TZID=America/New_York:20240115T090000

    All-day event

    DTSTART;VALUE=DATE:20240214

    DateTime local (floating)

    DTSTART:20240115T140000

    Troubleshooting

    Connection Issues

    # Test basic connectivity
    curl -v http://localhost:5232/

    Check with authentication

    curl -v -u user:pass http://localhost:5232/

    Verify CalDAV support

    curl -X OPTIONS http://localhost:5232/ -I | grep -i dav

    Common Errors

    | Error | Cause | Solution | |-------|-------|----------| | 401 Unauthorized | Wrong credentials | Check htpasswd file | | 403 Forbidden | Rights restriction | Check [rights] config | | 404 Not Found | Wrong URL path | Check principal/calendar path | | 409 Conflict | Resource exists | Use different UID | | 415 Unsupported Media Type | Wrong Content-Type | Use text/calendar |

    Debug Mode

    Run Radicale with debug logging:

    python3 -m radicale --debug
    

    Python API Quick Reference

    from caldav import DAVClient

    Connect

    client = DAVClient( url="http://localhost:5232", username="user", password="pass" )

    Get principal

    principal = client.principal()

    List calendars

    for cal in principal.calendars(): print(f"Calendar: {cal.name} ({cal.url})")

    Create calendar

    cal = principal.make_calendar(name="My Calendar", cal_id="my-cal")

    Create event

    cal.save_event( dtstart="2024-01-15 14:00", dtend="2024-01-15 15:00", summary="Meeting" )

    Query events by date range

    events = cal.date_search( start="2024-01-01", end="2024-01-31" ) for event in events: print(event.vobject_instance.vevent.summary.value)

    Get event by UID

    event = cal.event_by_uid("event-uid")

    Delete event

    event.delete()

    Create todo

    todo = cal.save_todo( summary="Task", due="2024-01-20" )

    Workflow Examples

    Create Recurring Event

    python3 {baseDir}/scripts/events.py create \
      --calendar work \
      --summary "Weekly Standup" \
      --start "2024-01-15 09:00" \
      --end "2024-01-15 09:30" \
      --rrule "FREQ=WEEKLY;BYDAY=MO,WE,FR"
    

    Export Calendar to ICS

    # Via curl
    curl -u user:pass http://localhost:5232/user/calendar/ > calendar.ics

    Via script

    python3 {baseDir}/scripts/calendars.py export --id work --output work.ics

    Sync with Git (Radicale)

    Configure Radicale to version changes:

    [storage]
    hook = git add -A && (git diff --cached --quiet || git commit -m "Changes by \"%(user)s\"")
    

    Initialize git in storage folder:

    cd /var/lib/radicale/collections
    git init
    git config user.email "radicale@localhost"
    

    βš™οΈ Configuration

    Python Library

    Install the caldav library:

    pip install caldav
    

    For async support:

    pip install caldav[async]
    

    Environment Variables (Recommended)

    Store credentials securely in environment or config:

    export CALDAV_URL="http://localhost:5232"
    export CALDAV_USER="your_username"
    export CALDAV_PASSWORD="your_password"
    

    Or use a config file at ~/.config/caldav/config.json:

    {
      "url": "http://localhost:5232",
      "username": "your_username",
      "password": "your_password"
    }
    

    πŸ“‹ Tips & Best Practices

    Connection Issues

    # Test basic connectivity
    curl -v http://localhost:5232/

    Check with authentication

    curl -v -u user:pass http://localhost:5232/

    Verify CalDAV support

    curl -X OPTIONS http://localhost:5232/ -I | grep -i dav

    Common Errors

    | Error | Cause | Solution | |-------|-------|----------| | 401 Unauthorized | Wrong credentials | Check htpasswd file | | 403 Forbidden | Rights restriction | Check [rights] config | | 404 Not Found | Wrong URL path | Check principal/calendar path | | 409 Conflict | Resource exists | Use different UID | | 415 Unsupported Media Type | Wrong Content-Type | Use text/calendar |

    Debug Mode

    Run Radicale with debug logging:

    python3 -m radicale --debug