Requirements
- Target platform
- OpenClaw
- Install method
- Manual import
- Extraction
- Extract archive
- Prerequisites
- OpenClaw
- Primary doc
- SKILL.md
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...
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...
Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.
I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete.
I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run.
Interact with CalDAV servers (calendars, events, todos) and manage Radicale server configurations.
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
Install the caldav library: pip install caldav For async support: pip install caldav[async]
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" }
# 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
# 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"
# 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"
# 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
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 '<d:propfind xmlns:d="DAV:"><d:prop><d:current-user-principal/></d:prop></d:propfind>' \ http://localhost:5232/ # List calendars curl -u user:pass -X PROPFIND \ -H "Depth: 1" \ -H "Content-Type: application/xml" \ -d '<d:propfind xmlns:d="DAV:" xmlns:c="urn:ietf:params:xml:ns:caldav"><d:prop><d:displayname/><c:calendar-timezone/><d:resourcetype/></d:prop></d:propfind>' \ http://localhost:5232/user/ # Query events by time range curl -u user:pass -X REPORT \ -H "Depth: 1" \ -H "Content-Type: application/xml" \ -d '<?xml version="1.0" encoding="utf-8"?> <c:calendar-query xmlns:d="DAV:" xmlns:c="urn:ietf:params:xml:ns:caldav"> <d:prop><d:getetag/><c:calendar-data/></d:prop> <c:filter> <c:comp-filter name="VCALENDAR"> <c:comp-filter name="VEVENT"> <c:time-range start="20240101T000000Z" end="20240131T235959Z"/> </c:comp-filter> </c:comp-filter> </c:filter> </c:calendar-query>' \ http://localhost:5232/user/calendar/ # Create calendar (MKCALENDAR) curl -u user:pass -X MKCALENDAR \ -H "Content-Type: application/xml" \ -d '<?xml version="1.0" encoding="utf-8"?> <d:mkcalendar xmlns:d="DAV:" xmlns:c="urn:ietf:params:xml:ns:caldav"> <d:set><d:prop> <d:displayname>New Calendar</d:displayname> </d:prop></d:set> </d:mkcalendar>' \ http://localhost:5232/user/new-calendar/
Radicale looks for config in: /etc/radicale/config (system-wide) ~/.config/radicale/config (user) Custom path via --config or RADICALE_CONFIG env
[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
TypeDescriptionnoneNo authentication (development only!)denyallDeny all (default since 3.5.0)htpasswdApache htpasswd fileremote_userWSGI-provided usernamehttp_x_remote_userReverse proxy headerldapLDAP/AD authenticationdovecotDovecot auth socketimapIMAP server authenticationoauth2OAuth2 authenticationpamPAM authentication
# Create new file with SHA-512 htpasswd -5 -c /etc/radicale/users user1 # Add another user htpasswd -5 /etc/radicale/users user2
# Enable and start sudo systemctl enable radicale sudo systemctl start radicale # Check status sudo systemctl status radicale # View logs journalctl -u radicale -f
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
PropertyDescriptionUIDUnique identifierDTSTARTStart timeDTENDEnd timeDTSTAMPCreation/modification timeSUMMARYEvent titleDESCRIPTIONEvent descriptionLOCATIONLocationRRULERecurrence ruleEXDATEExcluded datesATTENDEEParticipantORGANIZEREvent organizerSTATUSCONFIRMED/TENTATIVE/CANCELLED
# 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
# 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
ErrorCauseSolution401 UnauthorizedWrong credentialsCheck htpasswd file403 ForbiddenRights restrictionCheck [rights] config404 Not FoundWrong URL pathCheck principal/calendar path409 ConflictResource existsUse different UID415 Unsupported Media TypeWrong Content-TypeUse text/calendar
Run Radicale with debug logging: python3 -m radicale --debug
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" )
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"
# 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
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"
Workflow acceleration for inboxes, docs, calendars, planning, and execution loops.
Largest current source with strong distribution and engagement signals.