iCal-to-CalDAV bridge daemon. Converts public iCal (ICS) subscription URLs into a CalDAV server, so calendar clients like DankCalendar, khal, Evolution, and Thunderbird/Lightning can consume any public .ics feed without proprietary API locks.
Apache2 licensed.
Many calendar providers only offer iCal subscription URLs (Google Calendar free/busy, academic calendars, government ICS feeds) but no CalDAV. Desktop clients prefer CalDAV for bidirectional sync. This daemon bridges that gap:
iCal URL (Google free/busy, academic .ics, etc.)
│
▼
ical-to-caldav
(fetches + parses + caches)
│
▼
CalDAV server (:8080)
│
▼
DankCalendar / khal / Evolution / Thunderbird
# Build
make build
# Configure
cp ical-to-caldav.yaml.example ical-to-caldav.yaml
$EDITOR ical-to-caldav.yaml
# Run
./icaltocaldav --config ical-to-caldav.yaml
# In DankCalendar: dcal account add caldav
# URL: http://localhost:8080/caldav/sources/<source-id>/listen: ":8080"
data_dir: "~/.local/share/ical-to-caldav"
refresh_interval: "30m"
sources:
- id: google-freebusy
name: "Google Free/Busy"
url: "https://calendar.google.com/calendar/ical/.../public/basic.ics"
color: "#1a73e8"
- id: university
name: "University Calendar"
url: "https://example.edu/calendar.ics"
color: "#34a853"
refresh_interval: "1h"| Layer | Choice |
|---|---|
| Language | Go 1.23+ |
| HTTP | chi |
| iCal parsing | github.com/jszwec/ics |
| Cache | Badger (embedded KV) |
| License | Apache 2.0 |
ical-to-caldav/
├── cmd/icaltocaldav/ # main entrypoint
├── internal/
│ ├── source/ # fetcher + iCal parser
│ ├── caldav/ # CalDAV HTTP server (RFC 4791)
│ ├── store/ # Badger persistence
│ └── config/ # YAML config
└── Makefile
Implements the subset of RFC 4791 needed for read-only calendar access:
PROPFINDon calendar-home-set and calendar collectionsREPORTcalendar-query with time-range filterGETon calendar object resources (.icsfiles)
Write operations (PUT, DELETE) are out of scope for v1 — the daemon is a
read-only bridge.
Issues and PRs welcome. Follow the LOUST contribution standards.
- DankMaterialShell — desktop shell
- DankCalendar — calendar daemon + QML UI
- khal — CLI calendar client (CalDAV/iCal)
- vdirsyncer — CalDAV/iCal sync