.     .       
.-.-...-..-| .-,.-.
' ' ''' '`-'-`'-'  
Minder is a simple, no-frills calendaring system. It gets its input from plain-text files, and it sends e-mail reminders about upcoming events. You can customize the timing, destination, and content of the messages it sends.


Copyright © 2015 Adam Hartz

Minder is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License; either version 2 of the License, or (at your option) any later version. Minder is distributed in the hope that it will be useful, but without any warranty; without even the implied warranty of merchantability or fitness for a particular purpose. See the full text of the license for more details.


Download the Script

Most recent version (0.0.2): zip, tgz

You can also browse the Git repository online, or you can clone the Git repository with the following:

$ git clone https://gitlab.com/adqm/minder.git

Install the Script

Minder is installed in the usual way, using Python 3.4 or later:
$ sudo python3 setup.py

Set Up Email Configuration

Before you can use Minder, you have to give it credentials to log into an e-mail account. These options are specified in the file .config/minder/email.ini. The necessary options are:

Optionally, you can specify a port number for Minder to use to connect.

An example file is shown below:
from = Gandalf the Grey <gandalf@doorsofdur.in>
server = smtp.doorsofdur.in
port = 587
username = gandalf
password = mellon
Importantly, this file must be readable by its owner, and it must have no more than -rwx------ (0700) permissions (it should not be readble by anyone but its owner).


Command Line Arguments

usage: minder [-h] [-c] [-n] [-s] [-d TODAY] [-l LAST_RUN] [-r]
              [file [file ...]]

minder: a simple calendaring system
version 0.0.2

positional arguments:
  file         Files containing minder calendars

optional arguments:
  -h, --help   show this help message and exit
  -c           Update the cache and exit
  -n           Do not send email; rather, print messages to console
  -s           Send a summary of a day's events
  -d TODAY     The date to consider as the current date
  -l LAST_RUN  The date to consider as the "last run" date
  -r           Recursively search provided directories for *.mnd calendars

Setting Up Cron

Minder is intended to be run as a cron job. A typical configuration would have minder run once every minute, using the default calendar (~/.config/minder/default.mnd). In a crontab, this would look like:
* * * * * /usr/local/bin/minder

Of course, you can invoke minder using any of the command line options to customize the output (for example, to look in multiple calendars for reminders).

Adding the following line will cause Minder to send an additional email at 5am each day, containing a summary of that day's events:

0 5 * * * /usr/local/bin/minder -s



The core element in a Minder calendar is the event.

Every event is prefixed by some number of asterisks followed by whitespace. Events are specified by a "datespec" and a name, and can be customized through many options. The following is a simple event called "Meeting", which happens on 2 July 2016 at 2pm:

* 2 July 2016 2pm {Meeting}
Among other ways (see below for details), this same event could have been specified as follows:
* Jul 2 '16 14:00 "Meeting"
Minder can handle repeated events by specifying only part of a time/date, or by specifying multiple options for a piece of the time/date. For example, the following event happens every Monday and Wednesday in January at 4am and 7pm:
* Mon Wed January 4am 7am "Weird Event"
And the following (more realistic) event happens every Friday at 5pm:
* Fri 5pm {Go Home}
Events can be grouped by common features. Events containing more asterisks inherit from events with fewer asterisks. For example, the following creates two events on 5 August 2029, one at 7pm and one at 10pm.
* 5 Aug '29
** 7pm {First Event}
** 10pm {Second Event}
Returning to a previous number of asterisks stops the inheritance. The following event happens every day at 11pm (it does not inherit 5 Aug '29, and nor do any events that follow)
* 11pm {?}
Each event has a number of "rules" associated with it. These can be used to modify the characteristics of an event. Rules are prefixed with a single hyphen (-) surrounded by whitespace.

Some rules are used to control the content and timing of the emails that Minder sends regarding an event. These rules are "sendto", "subject", "message", and "remind". The following for the following event, reminders will be sent 1 minute, 1 hour, and 3 hours before the start of the event, with the specified subject line and message.

* Wed 1pm {Regular Meeting}
  - subject "Reminder About Meeting"
  - message "Remember that you have a meeting."
  - sendto "someone@email.domain"
  - remind 1m 1h 3h
The message and the subject line can be customized to report details of the event in question. This is done using Python's string formatting syntax. For example, the default message (used when no message is specified) is:
   - subject "Reminder: {NAME} on {HUMAN_TIME}"
   - message "Reminder: {NAME} on {HUMAN_TIME}"
{NAME} and {HUMAN_TIME} are replaced with the name of the event (in the above case, this would be "Regular Meeting") and the date/time of the event, in a human-readable format.

Other rules control the timing of the event. These rules are "omit", "replace", "begin", "end", and "include".

The "omit" rule causes the event not to trigger on a particular date. For example, if the regular 1pm Thursday meeting were canceled for some period of time, adding an "omit" rule will make sure that no reminders are sent for certain instances of the event:

* Thu 1pm {Another Regular Meeting}
  - omit 5 Feb 2015 # cancel on a particular day
  - omit 2016 # cancel for an entire year
  - omit 1 Mar 2015 to 31 Mar 2015 # cancel the entire month of march

The "include" rule has the opposite effect: if the event occurs once outside its normal time, "include" can be used to send reminders about that new time:

* Fri 1pm {Yet Another Meeting}
  - include 2 May 2015 1pm # extra meeting on saturday...
"begin" and "end" specify ranges for an event. The event will not trigger before its "begin" date, nor after its "end" date
* Sunday 7pm {Sit on the Beach}
  - begin 1 July 2015
  - end 1 September 2015 # we only want to do this during the summer...
"replace" is a quick way to handle reschedulings (rather than using "omit" and "include" directly):
* Monday 9am {Monday Morning Party}
  - Replace 3 August with +1day # Party moved to Tuesday
Rules are also inherited through the mechanism shown earlier (number of asterisks).