TDcal Logo   TDcal - ToDo Calendar Opal Logo


TDcal is a calendar and agenda client that supports the iCalendar and CalDAV standards.

TDcal is a set of command-line tools and a GUI program for editing calendar events as well as a synchronization daemon, a systray icon and a programming library.

TDcal is fully compliant with internet calendar standards (iCalendar, RFC5545) as well as the calendar sharing protocol (CalDAV, RFC4791) so it supports shared calendars, downloaded public calendars and private calendars.


TDcal Screenshot TDcal Screenshot


Development of TDcal started in 2013 with additional work done in 2017, 2018, 2020 and 2021.

TDcal's user interface is modeled on that of the ical(1) program written by Sanjay Ghemawat in 1993 which the TDcal author used for 20 years before needing a standards-based calendaring tool.

TDcal maintains many similar user-interface features found in ical(1) but replaces the internal calendar storage with a standards-based one, and adds support for remote iCalendar downloads as well as server-based CalDAV calendar synchronization.

TDcal downloads all calendar data and stores it locally so that you have full access to your calendars while offline; changes are saved and synced back to servers when you are next online.

TDcal is implemented in Perl and uses the Gtk graphics libraries. It has been designed to be lightweight, fast and independent of window-manager. It does not use a database management system, instead storing all calendar data as files in a sub-directory of your home directory.

In addition to the graphical interface shown above, TDcal includes a command-line calendar manipulation tool as well as a notification daemon and a systray icon. The Perl programming API is also fully documented allowing additional applications to be developed.

The code for the GUI program tdg is now Gtk3-based using only non-deprecated features.


TDcal was developed on the FreeBSD operating system. It known to work on Linux too, and should work on any POSIX-compliant system. The GUI code requires a system supporting the Gtk3 libraries.


TDcal is not yet released. Please see below for how to request an early copy. Once the 1.0 version is out, the following instructions will apply...

TDcal can be installed from the ports system either as a binary package or by installing from the source. To install from binary package, do this:

    # pkg install tdcal

To deinstall:

    # pkg delete tdcal
To install from the port, do this:
    # cd /usr/ports
    # portsnap extract deskutils/tdcal
    # cd deskutils/tdcal
    # make
    # make install clean

To deinstall:

    # cd /usr/ports/deskutuls/tdcal
    # make deinstall

If you are installing without using the FreeBSD ports framework, you will need to manually add the following dependencies:

    # pkg install deskutils/gxmessage
    # pkg install devel/p5-DateTime
    # pkg install devel/p5-DateTime-TimeZone
    # pkg install x11-toolkits/p5-Gtk3
    # pkg install devel/p5-Locale-gettext
    # pkg install security/p5-IO-Socket-SSL
    # pkg install net/p5-Net-Interface
    # pkg install textproc/p5-XML-Simple


TDcal is not yet released. Please see below for how to request an early copy. Once the 1.0 version is out, the following instructions will apply...

TDcal has been tested on Linux (specifically XUbuntu 21.04) and it works well.

Download the latest distribution file, below, and extract using:

    $ tar xvf tdcal-N.M.tar.xz

The existing Makefiles use FreeBSD make(1) syntax. They can be used on Linux using bmake(1).

Use the installation command:

    $ cd tdcal-N.M
    $ sudo PREFIX=/usr bmake install

The following package dependencies should be installed:


To deinstall:

    $ sudo PREFIX=/usr bmake deinstall

Getting Started

Quick Start

To start, a configuration file must be created which is done using any text editor. An example of a configuration file is shown below.

Any of the tools can be run to check the syntax of the configuration file. Running the command-line tool td is the simplest way to see any error messages.

The notification and synchronization daemon tdd as well as the systray icon tdt are typically started at login or in the window-manager startup configuration and these are left running the whole time you are logged in.

The next step is to import calendar event data. If your calendar is already on a remote server, the tdd daemon will fetch the calendar events and store copies of them locally on your computer. If your calendar is in a file, you can import it using the td command-line tool. If you are migrating from ical(1) you will need to convert the events in ical's .calendar file to iCalendar .ics format and then import it using the td command-line tool. See below for a tool to help do this.

To edit events in TDcal, the tdg graphical interface is typically used. This displays your calendars in a window and allows navigation through the events, editing them and adding new ones. Also, the td command-line tool can be used to add, edit and delete events from a terminal window, and it can also be used from shell scripts.

All changes to your calendars are stored locally on your computer. The changes are synchronized back to their CalDAV servers on a periodic basis by the tdd daemon which you started earlier. If desired, both the event editors, td and tdg can be told to start an immediate synchronization run whenever an event is changed.


The first manual to read is the general overview in TDcal(7).

The configuration file syntax is documented in td(5).

Each of the commands are documented in their manual pages: td(1), tdg(1), tdd(1) and tdt(1).

The Perl programming API is documented in the TDcal(3) manual page; that page references additional man pages for each of the TDcal libraries.

Configuration Example

To be useful, TDcal needs a configuration file that defines the calendars you wish to use. The configuration file also defines your preferred alarm/notification schedule, and calendar display preferences such as which day of the week is the first day and whether to split the weekend and display around the week.

The configuration file is named: ~/.td

This configuration file must be created using your favorite editor and should be mode 600 (because it contains passwords).

An example that configures a local private calendar, one shared on your own nextCloud server, and a downloaded public holidays calendar, would look like this:

    # TDcal configuration file

    alerts  60 30 15 5 0
    lperiod 14
    logsize 1000000

    cal     Local
    color   #ffdd00

    cal     MyNextCloud
    color   #00a0fa
    user    username
    pass    yadda-yadda-yadda-yadda-yadda
    alerts  90 60 45 30 15 10 5 0

    cal     MyNextCloud/contact_birthdays
    parent  MyNextCloud
    adalrts 17:00 10:00

    cal     US Holidays
    color   #04a004
    updfreq 10080

Full details of the configuration file syntax can be found in the manual page td(5).

Importing Calendar Data

If you have configured any calendars on remote servers, it is simply necessary to start the TDcal synchronization daemon tdd which can be done by running it from the command-line or by starting it from a login or window-manager startup script.

tdd fetches full calendars from the remote servers and then periodically synchronizes changed events back to the remote servers.

If you have calendar events in a local .ics file and wish to import these into a TDcal calendar, you can do this using the td command-line tool:

    td -c calendar -i file.ics

Once synchonized or imported, the calendar events can be viewed and manipulated using the tdg GUI interface or by the td command-line program which can also be used for scripted manipulations.

If you are migrating from ical(1) and you don't relish the idea of re-entering years (decades?) worth of calendar events, you could try the ical2icalendar(1) conversion tool offered here. This tool converts ical's .calendar data into standard .ics format. Use it something like this:

    perl ~/.calendar | td -c calendar -i -

This tool is not guaranteed to accurately convert everything: especially entries with complex repetition rules may not be properly converted. So, after use, you should go through all events and check their repetition rules are as desired.

TDcal Components

The TDcal package includes a synchronization daemon, a systray icon, a graphical editor interface, a command-line tool and a Perl API library.

The Synchronization and Notification Daemon, tdd

Once the configuration has been created, the tdd synchronization daemon should be started. This is usually accomplished by running it from your login or window-manager startup scripts. tdd will be running the whole time that you are logged in.

tdd connects to each calendar's server and performs synchronization uploads and/or downloads.

tdd also provides the pop-up event notification alerts.

The frequency of the synchronization runs as well as the timing of the alerts are all configured in the configuration file. Note that TDcal does not use alert times given in event VALARM properties; those are stored but ignored! You configure your own desired alert schedules both globally and on a per-calendar basis in the configuration file.

The Systray Icon, tdt

tdt provides a systray icon showing the calendar date.

The icon can be hovered over to see a pop-up showing forthcoming calendar events. Clicking on the icon opens the TDcal GUI program, tdg.

tdt is usually also started by running it from your login or window-manager startup scripts and leaving it running the whole time you are logged in.

The GUI Calandar Editor, tdg

TDcal's main interactive interface is its GUI program, tdg.

tdg provides a user-interface displaying a calendar, navigation buttons to change dates, and shows events for the day in an all-day panel and a 15-minute timeslot panel. Events can be edited, moved, resized, copied, moved to other days, deleted and even moved to other calendars from this interface.

The interface is intuitive to use, supporting Xorg mouse select/paste, ICCCM-style Ctrl-C/Ctrl-X/Ctrl-V copy/cut/paste, as well as its own Alt-C/Alt-X/Alt-V event manipulation copy/cut/paste.

Events can be moved using Shift-Button1 dragging and they can be resized using Alt-Button1 dragging.

All changes to events are done in the local copy of the calendar stored on your computer. Default behavior is that changes are synchronized to CalDAV servers on a periodic basis by the tdd synchronization daemon. tdg can be configured to send changes to servers immeidately if so desired.

The Command-Line Interface, td

The TDcal suite has a command-line tool, td, that is useful for manipulating calendars events by hand from the shell or from scripts.

td can import and export whole calendars in iCalendar .ics format, search for and display events and events can be extracted from the calendar into a file for manual or scripted editing and then put back into the calendar.

td has numerous options to control its behaviour. Run it with the -x flag for an explanation of the options and read its manual page for full details.

The Perl Programming API, TDcal

All four of the TDcal commands, as well as some additional tools in the source tree, make use of the Perl programming API library. Using the API, additional Perl programs can be written to interact with calendars and events using the TDcal model.

The library consists of the main library as well as several additional packages, such as TDcal/, TDcal/, TDcal/, etc, that implement specific functionality. Interested developers can start by reading the TDcal(3) manual page which then refers to additional manual pages for the other packages.

NLS Support

TDcal's tdg GUI as well as the tdd notifications support the use of NLS to display the program's messages in the user's native language. Anyone wishing to provide a translation is encouraged to do so.

The translation files are in the tdcal/po directory. Simply copy the TDcal.pot template to LL.po and edit it with translations of all messages. Also copy the help file to and translate that too. Then send them to the author at the email address below.

Use of UTF-8 encoding is strongly preferred and requested.

For more information, see the GNU gettext manual.

Notes on Various CalDAV Servers

TDcal is actively used and tested with calendars on the following CalDAV servers. These notes are excerpted from the td(5) manual page:

Works well.
Calendars containing non-ASCII characters in their display names such as ‘My Baïkal Calendar’ are likely to be displayed like ‘My Ba�kal Calendar’ due to the server substituting such characters with the UTF-8 Replacement Character. This is a bug in feature of Baïkal and not a problem with TDcal.
Works well.
You must log on to the web site and create an application-specific password.
Google no longer supported
Regrettably, Google Calendar is no longer supported since Google's switch to OAuth authentication in 2014. TDcal does not support OAuth authentication.
Works well.
If 2-factor-authentication is enabled, you must log on to the web site and create an application-specific password.
Works well.
If 2-factor-authentication is enabled, you must log on to the web site and create an application-specific password.
Works well.
You must log on to the web site and create an application-specific password.
Yahoo! Calendar's CalDAV implementation has some significant unusual aspects:
  • URL percent-encoding is incorrectly done twice, resulting in a calendar called ‘My Calendar’ being sent as .../My%2520Calendar/... instead of simply .../My%20Calendar/.... TDcal has work-around code to detect and correct for this problem in both calendar and event URLs.
  • Yahoo! Calendar also rejects events with repetition frequencies of ‘FREQ=HOURLY’ or smaller, returning a ‘500 Server Error’ when such events are uploaded. Repeating events only work with ‘FREQ=DAILY’ or larger.
  • Yahoo! Calendar also adds several iCalendar records to all events uploaded to the server. These additions mean that an entity tag for the new event is not immediately available on upload. The event must be redownloaded in order to obtain the changed version and its entity tag. This happens automatically for you, but it is an additional use of network bandwidth.

Source Distributions and Version History

Bug Tracker

Bug reports and feature requests can be submitted on the Opal Bug Tracker or sent by email to the developer at

Git server

TDcal is not yet released. Please see below for how to request an early copy. Once the 1.0 version is out, the following instructions will apply...

The lastest development version of the source can be downloaded from the Opal Git server:


Tarballs and Changelog


tdcal-1.0.tar.xz ... coming soon
First publicly-released version.


2021 Aug 05
TDcal is sufficiently stable for daily use and is known to run on FreeBSD and on Linux. It has been tested against the various CalDAV servers listed on this page.

The current version is tdcal-0.50.tar.xz 2021/09/22 08:30 UTC.

If you are interested in giving it an early try-out and are willing to send feedback, please contact the developer by email at Thanks!

Ongoing development work:
Much testing and further bug fixing.

Ongoing development work:

Ongoing development work:

Development resumed after gap of four years!

Initial development of the basic libraries and tools:
Basic functionality working and proven.

Contacting the Author and Port Maintainer

If you have comments or suggestions for changes please get in touch with the developer at