Extension API

Several Timewarrior reports are written as extensions, which uses an API to provide filtered data and configuration to the external command. This is a one-way process, the extension has no way to communicate back to Timewarrior. Future rules will allow this.


Simply placing an executable script/program in the ~/.timewarrior/extensions. directory is sufficient to configure and enable the extension. Alternately a symlink can also be placed there. The name of the program is left-most matched, so that this extension:


can be run using all of the following commands, depending on the uniqueness of the name:

$ timew report my_report.py
$ timew report my_report
$ timew report my_r
$ timew my_report.py
$ timew my_report
$ timew my_r


Timewarrior provides all configuration and filtered data in JSON format to the standard input of the extension. There are no command line arguments used, and no environment changes. The extension must be a standalone executable entity, as Timewarrior will fork/exec and not invoke a shell.

All standard output generated by the extension is captured and presented verbatim by Timewarrior. There may be additional text prepended or appended.

Input Format

The input format looks like this:

name1: value1
name2: value2

{ ... },
{ ... },

Each line is terminated by the newline character U+000A. There is an initial block of name/value pairs, which is a copy of the complete current configuration data. It has the form:


Between the and are the characters U+003A and U+0020. This configuration block includes the Timewarrior version, so that multiple releases maybe supported by the extension. Additionally, other data is included with the 'temp.' prefix, indicating that it is not part of the configuration data, but may be of use to the extension. For example:

temp.db: /home/user/.timewarrior
temp.report.end: 20160401T000000Z
temp.report.start: 20160430T235959Z
temp.report.tags: "This is a multi-word tag",ProjectA,tag123
temp.version: 0.1.0

After the configuration block, there is a single blank line to separate it from the JSON data.

The JSON data is a single JSON array, containing zero or more Interval objects that look like this (line breaks used here for clarity):

"tags":["This is a multi-word tag","ProjectA","tag123"]},

Here the presence of the "end" data means this interval is closed, i.e. not actively being tracked. There is one JSON object per line. The timestamps are ISO format UTC. Any active interval is not necessarily the last element in the array.


A well-behaved extension is one that follows these guidelines, and conforms to the general pattern of behavior exhibited by Timewarrior. The guidelines are:

  • Obey the 'verbose' setting, and if the value is neither of on/1/yes/y/true, then consider it 'off', and generate minimal output, which should tend toward no output at all.
  • Obey the 'debug' setting, and if the value is either of on/1/yes/y/true, then emit helpful feedback, but only that which can be useful for debugging a problem, which should tend toward no output at all.
  • Obey the 'confirmation' setting, and if the value is either of on/1/yes/y/true, then obtain user permission interactively before proceeding with any data modification. Do not rely on, or implement a 'force'-like feature.
  • Use the temp.version to selectively offer functionality that correlates with the release.