khal-calendar
June 14, 2026 · View on GitHub
A DankBar widget that shows upcoming calendar events from a khal-managed vdir, with a full popout panel for viewing, creating, editing, and deleting events.

Features
- Works with any CalDAV server via vdirsyncer (iCloud, Google, Nextcloud, etc.)
- All khal calendars available — filter which ones appear in the widget
- Create, edit, and delete events directly from the popout
- Desktop notifications before upcoming events
- Middle-click an event to open URLs from its description or location
- Scrollable popout with momentum scrolling and auto-hiding scrollbar
- Per-calendar name display and event location display
- Configurable look-ahead window and refresh interval
Architecture
QML widget → khal CLI → local vdir ← vdirsyncer (user-managed) → CalDAV server
The plugin reads and writes events through khal against a local vdir directory. vdirsyncer handles CalDAV synchronization independently — configure it separately with a systemd timer or cron job.
Bar Display
- Horizontal pill: shows the next upcoming event with time and title (e.g.
14:00 Meeting) - Vertical pill: shows the total event count with a "cal" label
Popout Panel
- Grouped event list by day with time ranges
- Color-coded all-day and timed events
- Left-click an event to edit title, time, and location
- Middle-click an event to open URLs found in its description or location
- Add new events with calendar selection, date/time pickers, and optional location
- Delete events from the edit form
- Last updated timestamp with manual refresh button
- DankFlickable scrolling with mouse wheel, touchpad momentum, and auto-hiding scrollbar
Prerequisites
Setup
1. Configure vdirsyncer
Create ~/.config/vdirsyncer/config with your CalDAV accounts. Example for Google:
[general]
status_path = ~/.vdirsyncer/status/
[pair google]
a = google_remote
b = google_local
collections = ["from a", "from b"]
[storage google_remote]
type = google_calendar
token_file = ~/.vdirsyncer/google_token
client_id = YOUR_CLIENT_ID
client_secret = YOUR_CLIENT_SECRET
[storage google_local]
type = filesystem
path = ~/.vdirsyncer/calendars/google/
fileext = .ics
Run discovery and initial sync:
vdirsyncer discover google
vdirsyncer sync
Set up a recurring sync (systemd timer or cron):
# Example systemd timer: sync every 5 minutes
systemctl --user enable vdirsyncer.timer
2. Configure khal
Create ~/.config/khal/config:
[calendars]
[[google_local]]
path = ~/.vdirsyncer/calendars/google/*
type = discover
[locale]
timeformat = %H:%M
dateformat = %Y-%m-%d
longdateformat = %Y-%m-%d
datetimeformat = %Y-%m-%d %H:%M
longdatetimeformat = %Y-%m-%d %H:%M
[default]
default_calendar = YourCalendarName
Verify with khal list to confirm events appear.
3. Install the plugin
git clone https://github.com/szabolcsf/dms-khal-calendar.git
cp -r dms-khal-calendar ~/.config/DankMaterialShell/plugins/khalCalendar
Enable the plugin in DMS Settings → Plugins, then add it to your DankBar.
4. Configure plugin settings
In the plugin settings:
- Vdir base path: set to your khal calendars directory (default:
~/.local/share/khal/calendars/) - Calendar filter: comma-separated calendar names to show, or leave empty for all. Use
khal printcalendarsto see available names.
Settings
| Setting | Description | Default |
|---|---|---|
| Calendar filter | Comma-separated calendar names to show (empty = all) | — |
| Vdir base path | Path to khal's vdir calendars directory | ~/.local/share/khal/calendars/ |
| Look-ahead (days) | How many days into the future to show events | 7 |
| Refresh interval (minutes) | How often to fetch events | 5 |
| Show event location | Display location for events that have one | On |
| Show calendar name | Display which calendar each event belongs to | Off |
| Desktop notifications | Send a notification before upcoming events | On |
| Notify before (minutes) | How far in advance to notify | 15 |
How it works
Event listing
khal list <today> <today+Nd> --json ... fetches events. khal outputs one JSON array per day — each parsed and merged into the event list. The calendar filter passes -a <name> flags to restrict which calendars appear.
Event creation
khal new -a <calendar> <start> <end> <summary> --location <loc> creates events. All-day events use date-only format; timed events use YYYY-MM-DD HH:MM.
Event editing / deletion
The plugin reads the event's .ics file from <vdir>/<calendar>/<uid>.ics, modifies SUMMARY, DTSTART, DTEND, and LOCATION fields via sed, and writes back. khal picks up changes on the next operation. Deletion removes the .ics file directly.
Notifications
khal at <now> --notstarted --json ... checks for events starting within the notify window. Deduplication uses persisted state. Sends notifications for upcoming events.
URL opening
Middle-clicking an event scans its description and location for https?:// URLs and opens each via xdg-open.
Compositors
Tested on Niri. Should work on any compositor supported by DankMaterialShell.
License
MIT