Khal
khal
is a standards based Python CLI (console) calendar program, able to synchronize with CalDAV servers through vdirsyncer
.
Features:
- Can read and write events/icalendars to vdir, so
vdirsyncer
can be used to synchronize calendars with a variety of other programs, for example CalDAV servers. - Fast and easy way to add new events
ikhal
(interactivekhal
) lets you browse and edit calendars and events.
Limitations:
- It's not easy to get an idea of what you need to do in the week. At least not as comfortable as a graphical interface.
-
Editing events with
ikhal
is a little bit cumbersome. -
Only rudimentary support for creating and editing recursion rules.
- You cannot edit the timezones of events.
Installation⚑
Although it's available in the major package managers, you can get a more bleeding edge version with pip
.
pipx install khal
If you don't have pipx
you can use pip
.
Configuration⚑
khal
reads configuration files in the ini syntax. If you do not have a configuration file yet, running khal configure
will launch a small, interactive tool that should help you with initial configuration of khal.
khal
is looking for configuration files in the following places and order:
$XDG_CONFIG_HOME/khal/config
: (on most systems this is~/.config/khal/config
),~/.khal/khal.conf
(deprecated)- A
khal.conf
file in the current directory (deprecated).
Alternatively you can specify which configuration file to use with -c path/to/config
at runtime.
The calendars section⚑
The [calendars]
section is mandatory and must contain at least one subsection. Every subsection must have a unique name (enclosed by two square brackets). Each subsection needs exactly one path setting, everything else is optional. Here is a small example:
[calendars]
[[home]]
path = ~/.calendars/home/
color = dark green
priority = 20
[[work]]
path = ~/.calendars/work/
readonly = True
Some properties are:
path
: The path to an existing directory where this calendar is saved as a vdir.color
:khal
will use this color for coloring this calendar’s event. The following color names are supported:black
,white
,brown
,yellow
,dark gray
,dark green
,dark blue
,light gray
,light green
,light blue
,dark magenta
,dark cyan
,dark red
,light magenta
,light cyan
,light red
.priority
: When coloring days, the color will be determined based on the calendar with the highest priority. If the priorities are equal, then the “multiple” color will be used.readonly
: Setting this to True, will keepkhal
from making any changes to this calendar.
The default section⚑
Some of this configurations do not affect ikhal
.
default_calendar
: The calendar to use if none is specified for some operation (e.g. if adding a new event). If this is not set, such operations require an explicit value.default_dayevent_duration
: Define the default duration for an event (khal new
only).1h
by default.default_event_duration
: Define the default duration for a day-long event (khal new
only).1d
by default.highlight_event_days
: If true,khal
will highlight days with events. Options for highlighting are in highlight_days section.
The key bindings section⚑
Key bindings for ikhal
are set here. You can bind more than one key (combination) to a command by supplying a comma-separated list of keys. For binding key combinations concatenate them keys (with a space in between), for example ctrl n
.
Action | Default | Description |
---|---|---|
down | down, j | Move the cursor down (in the calendar browser). |
up | up, k | Move the cursor up (in the calendar browser). |
left | left, h, backspace | Move the cursor left (in the calendar browser). |
right | right, l, space | Move the cursor right (in the calendar browser). |
view | enter | Show details or edit (if details are already shown) the currently selected event. |
save | meta enter | Save the currently edited event and leave the event editor. |
quit | q, Q | Quit. |
new | n | Create a new event on the selected date. |
delete | d | Delete the currently selected event. |
search | / | Open a text field to start a search for events. |
mark | v | Go into highlight (visual) mode to choose a date range. |
other | o | In highlight mode go to the other end of the highlighted date range. |
today | t | Focus the calendar browser on today. |
duplicate | p | Duplicate the currently selected event. |
export | e | Export event as a .ics file. |
log | L | Show logged messages. |
external_edit | meta E | Edit the currently selected events’ raw .ics file with $EDITOR |
Use the external_edit
with caution, the icalendar library we use doesn't do a lot of validation, it silently disregards most invalid data.
Syncing⚑
To get khal
working with CalDAV you will first need to setup vdirsyncer
. After each start khal
will automatically check if anything has changed and automatically update its caching db (this may take some time after the initial sync, especially for large calendar collections). Therefore, you might want to execute khal
automatically after syncing with vdirsyncer
(for example via cron
).
Usage⚑
khal
offers a set of commands, most importantly:
list
: Shows all events scheduled for a given date (or datetime) range, with custom formatting.calendar
: Shows a calendar (similar to cal(1)) and list.new
: Allows for adding new events.search
: Search for events matching a search string and print them.at
: shows all events scheduled for a given datetime.edit
: An interactive command for editing and deleting events using a search string.interactive
: Invokes the interactive version ofkhal
, can also be invoked by callingikhal
.printcalendars
:printformats
new⚑
khal new [-a CALENDAR] [OPTIONS] [START [END | DELTA] [TIMEZONE] SUMMARY
[:: DESCRIPTION]]
Where start
and end
are either datetimes, times, or keywords and times in the formats defined in the config file.
If no calendar is given via -a
, the default calendar is used.
For example:
khal new 18:00 Awesome Event
Adds a new event starting today at 18:00 with summary Awesome event
(lasting for the default time of one hour) to the default calendar.
khal new tomorrow 16:30 Coffee Break
Adds a new event tomorrow at 16:30.
khal new 25.10. 18:00 24:00 Another Event :: with Alice and Bob
Adds a new event on 25th of October lasting from 18:00 to 24:00 with an additional description.
khal new -a work 26.07. Great Event -g meeting -r weekly
Adds a new all day event on 26th of July to the calendar work in the meeting category, which recurs every week.
Interactive⚑
When the calendar on the left is in focus, you can:
-
Move through the calendar (default keybindings are the arrow keys, space and backspace, those keybindings are configurable in the config file).
-
Focus on the right column by pressing
tab
orenter
. -
Focus on the current date, default keybinding
t
as in today. -
Marking a date range, default keybinding
v
, as in visual, think visual mode in Vim, pressingesc
escapes this visual mode.
If in visual mode, you can select the other end of the currently marked range, default keybinding o
as in other (again as in Vim).
-
Create a new event on the currently focused day (or date range if a range is selected), default keybinding
n
. -
Search for events, default keybinding
/
, a pop-up will ask for your search term.
When an event list is in focus, you can:
- View an event’s details with pressing enter (or tab) and edit it with pressing enter (or tab) again (if [view]
event_view_always_visible
is set toTrue
, the event in focus will always be shown in detail). - Toggle an event’s deletion status, default keybinding
d
, events marked for deletion will appear with aD
in front and will be deleted whenkhal
exits. - Duplicate the selected event, default keybinding
p
- Export the selected event, default keybinding
e
.
In the event editor, you can:
- Jump to the next (previous) selectable element with pressing
tab
(shift+tab) - Quick save, default keybinding
meta+enter
(meta will probably be alt). - Use some common editing short cuts in most text fields (ctrl+w deletes word before cursor, ctrl+u (ctrl+k) deletes till the beginning (end) of the line, ctrl+a (ctrl+e) will jump to the beginning (end) of the line.
- In the date and time fields you can increment and decrement the number under the cursor with
ctrl+a
andctrl+x
(time in 15 minute steps) - In the date fields you can access a miniature calendar by pressing enter.
- Activate actions by pressing enter on text enclosed by angled brackets, e.g. \< Save > (sometimes this might open a pop up).
Pressing esc
will cancel the current action and/or take you back to the previously shown pane (i.e. what you see when you open ikhal), if you are at the start pane, ikhal will quit on pressing esc again.
Tricks⚑
Edit the events in a more pleasant way⚑
The ikhal
event editor is not comfortable for me. I usually only change the title or the start date and in the default interface you need to press many keystrokes to make it happen.
A patch solution is to pass a custom script on the EDITOR
environmental variable. Assuming you have questionary
and ics
installed you can save the next snippet into an edit_event
file in your PATH
:
#!/usr/bin/python3
"""Edit an ics calendar event."""
import sys
import questionary
from ics import Calendar
# Load the event
file = sys.argv[1]
with open(file, "r") as fd:
calendar = Calendar(fd.read())
event = list(calendar.timeline)[0]
# Modify the event
event.name = questionary.text("Title: ", default=event.name).ask()
start = questionary.text(
"Start: ",
default=f"{str(event.begin.hour).zfill(2)}:{str(event.begin.minute).zfill(2)}",
).ask()
event.begin = event.begin.replace(
hour=int(start.split(":")[0]), minute=int(start.split(":")[1])
)
# Save the event
with open(file, "w") as fd:
fd.writelines(calendar.serialize_iter())
Now if you open ikhal
as EDITOR=edit_event ikhal
, whenever you edit one event you'll get a better interface. Add to your .zshrc
or .bashrc
:
alias ikhal='EDITOR=edit_event ikhal'
The default keybinding for the edition is not very comfortable either, add the next snippet on your config:
[keybindings]
external_edit = e
export = meta e