CalDAV Integration
calrs connects to any CalDAV server to read your calendar for free/busy computation and optionally write confirmed bookings back.
Connecting a calendar source
From the web dashboard
- Go to Dashboard > Calendar sources > + Add
- Select your provider (BlueMind, Nextcloud, Fastmail, etc.) — the URL is auto-filled
- Enter your username and password
- Click Add source
The connection is tested automatically before saving. Use “Skip connection test” if your server doesn’t respond to OPTIONS requests (e.g., BlueMind).

From the CLI
calrs source add --url https://nextcloud.example.com/remote.php/dav \
--username alice --name "Work Calendar"
# Skip connection test if needed
calrs source add --url https://mail.company.com/dav/ \
--username alice --name "BlueMind" --no-test
Provider URLs
| Provider | CalDAV URL |
|---|---|
| BlueMind | https://mail.yourcompany.com/dav/ |
| Nextcloud | https://cloud.example.com/remote.php/dav |
| Fastmail | https://caldav.fastmail.com/dav/calendars/user/you@fastmail.com/ |
| iCloud | https://caldav.icloud.com/ |
| Zimbra | https://mail.example.com/dav/ |
| SOGo | https://mail.example.com/SOGo/dav/ |
| Radicale | https://cal.example.com/ |
Tip: Use app-specific passwords for Fastmail and iCloud.
Google Calendar is not currently supported
Google dropped Basic Auth for CalDAV in 2020 and now requires OAuth2. Google “app passwords” only work for IMAP/SMTP, not CalDAV, so they will fail with 401 loginRequired against the CalDAV endpoint. OAuth2 support for CalDAV sources is not implemented yet.
If you need Google Calendar availability in calrs, a working pattern is to bridge it through a CalDAV server that can subscribe to a Google calendar (for example, Nextcloud’s calendar app), and point calrs at that server.
Auto-discovery
calrs follows the CalDAV standard (RFC 4791) for discovery:
- PROPFIND on the base URL to find the
current-user-principal - PROPFIND on the principal to find the
calendar-home-set - PROPFIND on the calendar home to list all calendars
- Filters to actual
calendarcollections (skips inbox, outbox, tasks, etc.)
Syncing
# Sync all sources
calrs sync
# Full re-sync (ignore sync tokens)
calrs sync --full
From the dashboard, click Sync on any source to trigger a sync.
Sync pulls all VEVENT data from your calendars and stores it in the local SQLite database. Events are upserted by UID (and RECURRENCE-ID for modified instances), so re-syncing is safe.
Multi-VEVENT resources
Some CalDAV servers (notably BlueMind) bundle recurring events and their modified instances into a single CalDAV resource containing multiple VEVENTs. calrs splits these and stores each VEVENT as a separate row:
- The parent event has the RRULE and is stored with its UID
- Modified instances have a RECURRENCE-ID and are stored alongside the parent with a composite unique key
(uid, recurrence_id) - This ensures modified occurrences correctly block (or free) availability
CalDAV write-back
When a booking is confirmed, calrs can automatically push it to your CalDAV calendar as a VEVENT. When a booking is cancelled, the event is deleted.
Setup
- Sync your calendar source at least once (so calrs knows which calendars exist)
- On the dashboard, find your source under “Calendar sources”
- Use the “Write bookings to” dropdown to select which calendar should receive bookings
- Select “None” to disable write-back
How it works
- On confirmation: calrs generates an ICS event and PUTs it to
{calendar-href}/{booking-uid}.ics - On cancellation: calrs DELETEs the event from the same path
- The booking tracks which calendar it was pushed to, so cancellation always targets the right calendar
- If no write calendar is configured, write-back is silently skipped (emails still work)
- Write-back works for individual bookings, group round-robin bookings, and pending-then-confirmed bookings
Managing sources
# List all sources
calrs source list
# Test a connection
calrs source test <id-prefix>
# Remove a source (cascade-deletes calendars and events)
calrs source remove <id-prefix>
From the dashboard: Sync, Test, and Remove buttons are available for each source.
Credentials
Passwords are hex-encoded and stored in the SQLite database. This is not encryption — it prevents accidental display in logs but does not protect against database access. Secure your data directory appropriately.