Fork me on Github

klog

klog is a plain-text file format and a command line tool for time tracking.
It is free and open-source software.

github.com/jotaen/klog

Introduction

The idea behind klog is to store data in plain-text files in a simple and human-readable format. The notation is similar to how you would write down the information into a physical notebook using pen and paper. Manipulating your data is as easy as opening the file in a text editor and making changes to the copy. By using the klog command line tool you can search, evaluate and manipulate your data from the terminal.

Let’s say you started a new job and want to use klog for tracking work times. For that, you create a file worktimes.klg with the following content:

FILE: worktimes.klg
2018-03-24
First day at my new job
8:30 - 17:00
-45m Lunch break

This means: at the 24th of March 2018 you came to the office at 8:30 in the morning and went home at 17:00 in the afternoon. Somewhere throughout the day there was a 45-minute lunch break. That effectively results in a total time of 7 hours and 45 minutes for that day.

As you see, klog files almost read like a lightweight journal. It supports various notations for tracking times, which are convenient to write and intuitive to understand. You can capture short summaries about your activities along the time data, which may help you later on to make sense of what you did back in the day. And by using tags you are able to run fine-granular evaluations on your data.

With the klog command line tool you can interact with your files. For instance, you could evaluate the resulting total time with the following command:

TERMINAL
klog total worktimes.klg Total: 7h45m (In 1 record)

Or you add an extra 30 minutes:

TERMINAL
klog track --today '30m' worktimes.klg

This appends a new entry to the respective record in the file.

Get klog

  1. Download the latest version and unzip
  2. Right-click on the binary and select “Open” (due to Gatekeeper)
  3. Copy to path, e.g. mv klog /usr/local/bin/klog (might require sudo)

Or, if you use Homebrew, run brew tap jotaen/klog.

  1. Download the latest version and unzip
  2. Copy to path, e.g. mv klog /usr/local/bin/klog (might require sudo)
  1. Download the latest version and unzip
  2. Copy to path, e.g. to C:\Windows\System32 (might require admin privileges)

As an alternative you can also use the Linux binary on the Windows Subsystem for Linux.

In order to not miss any updates you can either subscribe to the release notifications on Github (at the top right: “Watch” → “Custom” → “Releases”), or you occasionally check by running klog version.

File Format

Version 1.4 (Specification)

Time-tracking data in klog is stored in .klg files in a plain-text format.

Records

Records are the basic data structure in klog. They hold time-tracking information for a specific calendar date. Records appear as “blocks of text” in the file, with one (or multiple) blank lines between each other.

FILE: worktimes.klg
2018-03-24
First day at my new job
8:30 - 17:00
-45m Lunch break

2018-03-25
8h15m

2018-03-26
More onboarding. Also started
to work on my first small project!
8:30 - 11:15
11:15 - 12:20 Meeting with Sarah
4h

The computed total time of a record is the sum of all its entries. Every record consists of three parts:

  1. The date, formatted either YYYY-MM-DD or YYYY/MM/DD.
  2. Optionally, one or more lines of summary text.
  3. Any number of time entries.

Records can appear in any order in the file, so they don’t have to be sorted by date, for example. There might be multiple records for the same date in one file.

Entries

Entries are the actual time values that you track. Each entry represents an amount of time that you spent on something. Entries appear one per line and are indented by one level. They start with the time value and can optionally be followed by a summary text.

FILE: example.klg
2019-07-22
1h
8:00 - 9:00

Both entries in this example are worth 1 hour each, resulting in a total time of 2 hours for that day.

There are three types of entries:

There can be any number of entries per record – including none. The order of entries can be arbitrary and has no influence on the result. You can also freely mix the different types of entries.

The indentation is either 1 tab or 2–4 spaces. This must be consistent within the record; it may differ between records, though.

Summaries

The purpose of summaries is to capture arbitrary information alongside the data for future reference. Writing summaries is optional.

FILE: summaries.klg
2020-02-18
This record demonstrates various
ways of formatting summaries:
5h A short summary.
-120m This is a longer summary, which
is continued on the next line.
14:00 - ?
Summaries can also start on the
subsequent line.

Summaries can appear:

Summaries can have multiple lines of text, but they cannot contain any blank lines.

Tagging / categorising

Summaries can contain #tags that allow fine-granular filtering of the data.

FILE: sports.klg
2019-07-22
Did some #sports
2h #badminton session with Max
18:00 - 19:00 Went out for a #run

2019-07-23
8:30 - 10:30 Design draft #project=478
10:30 - ? Phone #call="Liz Jones"

A tag can contain letters, digits, underscores, or hyphens. It has two parts:

If a tag appears in the overall record summary, then all entries will match when filtering for that tag. If a tag appears in an entry summary, only the respective entry will match.

In the above example, the total time for the tag #sports would be 3h, and the total time for #run would be 1h.

Open-ended time ranges

In case you just begin an activity (without knowing when it will end) you can already log it as an open-ended time range.

FILE: reading.klg
2019-07-26
Started to read my new book
16:30 - ?

Open-ended time ranges are denoted by replacing the end time with a question mark, otherwise they work the same as normal entries. Note that there can only be one open-ended range per record, and it doesn’t count towards the total time as long as it’s open.

Tip: When evaluating files with the klog CLI, you can simulate open-ended time ranges to be closed “right now” by using the --now flag (or short: -n).

Should-total

For some use-cases it’s helpful to specify a certain overall time goal that you want to achieve. This is called “should-total” and appears after the date of the record. It is a duration value, followed by an exclamation mark and wrapped in parentheses. For example, let’s say you are supposed to work 7½ hours per day:

FILE: work.klg
2019-07-26 (7h30m!)
8:00 - 16:00 Work
-45m Lunch break

When evaluating the record, you can calculate the difference between should-total and actual total time in order to see whether you have reached your designated goal. A should-total value always applies to the entire record with all its entries.

Tip: With the klog CLI, you can use the --diff flag (or short: -d) to display the difference between should-total and actual total time. When using klog today --diff --now, it also forecasts the end-time at which your time goal will be reached.

Day shifting

Sometimes you start an activity in the evening and end it after midnight, just so that start and end time don’t belong to the same calendar date. For this case it is possible to “shift over” a time to the previous or to the next day by adding the < prefix, or the > suffix, respectively.

FILE: times.klg
2019-07-26
<23:30 - 8:00 Worked a night shift
22:30 - 1:45> Watched some movies

When filtering records, keep in mind that these entries are still associated with the date they are recorded under, so the total time for the above date 2019-07-26 is 11h45m. (If there are records for the adjacent days, their total time won’t be affected.)

FAQ

Where do I store my .klg files?

klog is not opinionated about the way you structure your data across files and folders, so you are completely free where you put them, or how you name them. For example, it can be useful to have separate files, e.g. one for each month, or for different kinds of activities. That allows you to come up with a structure that meets your personal needs.

Can I also put other text into my .klg files?

The file format is strict, so a .klg file can only contain records according to the specified rules. Text can be captured as summaries inside of records, but there can’t be free text next to records. This is an important prerequisite for the interoperability of tools.

Is it possible to use to-the-second precision, like 1h10m30s or 8:23:49?

No, this is not supported. The reason is that it would effectively prohibit mixing values with and without seconds, which leads to a lot of hassle. Keep in mind, klog is for tracking time of activities, it’s not a stopwatch.

Can I capture timezone information?

No. In case you are affected by a timezone change or a switch to daylight saving time you need to account for that yourself. Realistically, this doesn’t happen all too often anyway, so it’s a tradeoff for simplicity to omit the timezone information altogether.

What happens when I track more than 24 hours per day?

klog generally doesn’t impose too many restrictions. Examples of things that are allowed:

There might be valid reasons for such use cases, so klog deliberately is not stricter than necessary. What the command line tool does do, however, is to raise warnings about certain potential issues, for example when it detects an open-ended time range at a past date.

Command line tool

v5.2

The command line tool allows you to display and search records in files, pretty print and evaluate them, and apply some basic manipulations. The following sections demonstrate the basic functionality.

In order to learn about all flags and options, please run klog with the --help flag (which is also available on the subcommands).

Evaluate data

You can generally provide input data in one of the following ways:

In case there are syntax errors in the input data, klog cannot process it and displays an error message instead. Also, some commands emit warnings to draw your attention to potential logical issues in your data.

Tip: Most shells have native support for glob patterns, so in case you want to organise your records throughout multiple files (e.g. one file per month) you can process them all at once by passing the glob pattern *.klg.

Display files

klog print pretty-prints the data onto the terminal.

TERMINAL
klog print worktimes.klg   2018-03-24
First day at my new job
8:30 - 17:00
-45m Lunch break

Printing is a good way to double-check that the syntax in a file is all correct.

Total time

With klog total, you can evaluate the overall total time of all records.

TERMINAL
klog total sport.klg Total: 60h36m (In 15 records)

Remember that open time ranges are not taken into account by default. By using the --now flag, you can simulate all open time ranges to be closed “right now”.

In case you have set should-totals for your records, you can use the --diff option to calculate the difference between the should-total and the actual total:

TERMINAL
klog total --diff work.klg Total: 16h45m Should: 18h! Diff: -1h15m (In 6 records)

Calendar report

In order to print a chronological timeline of your data (like in a calendar), you can use the klog report command.

TERMINAL
klog report 2020.klg Total 2020 Jan Wed 28. 6h20m Sun 30. 3h50m Feb Tue 3. 7h Fri 5. 6h15m ======== 23h25m

The data can be aggregated by day, week, month, quarter or year, which can be controlled via the --aggregate flag. (The default is by day.)

Use the --fill flag to print a consecutive stream of all dates, regardless of whether there are records or not.

Ongoing day

klog today is similar to klog total, except that it displays the current day separate from all other days.

TERMINAL
klog today times.klg Total Today 5h7m Other 162h19m ======== All 167h26m

By using the --follow flag you can keep the shell process open and see your data being updated live. If the file contains open-ended time ranges, you can additionally set the --now flag for an ongoing simulation.

In case you have set should-total times, the --diff and --now flags together render a forecast of the end-time at which your designated time goal will be reached.

TERMINAL
klog today --diff --now times.klg Total Should Diff End-Time Today 5h7m 8h! -2h53m 18:00 Other 162h19m 160h! +2h19m =========================== All 167h26m 168h! -34m 17:26

Break down by tags

If you use tags in your summaries, you can aggregate the total times by tags.

TERMINAL
klog tags sports.klg #running 13h #biking 9h #sports 21h

If a tag appears in the overall summary of the records, then all entries of that record are counted. If a tag appears in the summary of an individual entry, then only that entry is counted.

If you use tags with values and want to see a fine-granular breakdown, use the --value flag.

Filtering records

All of the evaluation commands provide filter options which allow you to select a specific date range, or to only consider certain tags. For example, if you want to evaluate all records in sport.klg since January 2018 that are tagged with #biking, you would do:

TERMINAL
klog total --since=2018-01-01 --tag=biking sport.klg Total: 116h21m (In 37 records)

You can filter records in the following ways:

Manipulate files

The command line tool is able to manipulate your files, for example by creating new records or adding entries. Support for manipulation commands is deliberately basic, because due to the simple file format, it’s often most easy to just open your .klg file and edit the data by hand.

For all manipulation commands, you can specify the designated date via the --date flag. In case a record does already exist at that date, the entry will be added to that record. Otherwise, a new record is created “on the fly”. By default, klog assumes the records in your files to be in chronological order and automatically inserts it at the right position.

Add new entries

The most straightforward way to add a new entry to a record is by using the klog track command.

TERMINAL
klog track '1h30m' sports.klg klog track '8:00 - 16:00 Workday' work.klg klog track '14:45 - ?' times.klg
Tip: You should always use single quotes around the value, to make sure your shell treats it as atomic string and doesn’t substitute special characters. There is still one caveat: when tracking negative durations, you need to escape the leading minus with a backslash: klog track '\-30m'

Start and stop activities

By using klog start, a new open-ended time range is added.

TERMINAL
klog start work.klg

Once you are done, you can “close” that open-ended time range by running klog stop.

TERMINAL
klog stop work.klg

By default, the current time is used. You can otherwise set it explicitly with the --time flag. If you prefer rounded numbers instead of the exact ones, you can use the --round option, to round to the nearest multiple of 5m, 10m, 15m, 30m, or 60m.

If you just want to take a break without stopping the activity, the klog pause comes in handy.

TERMINAL
klog pause --summary 'Lunch break' work.klg

This adds a new pause record underneath the open-ended time range, without closing (stopping) the ongoing time range.

FILE: work.klg
2022-03-11
8:30 - ? Work
-17m Lunch break

The klog pause command is blocking, and the duration value of the pause is continuously updated in the file, until you exit the process via Ctrl+C. Note: it flushes changes to the file once per minute, and only after the first minute elapsed.

Create new records

klog create creates a new, empty record in a file.

TERMINAL
klog create reading.klg

You can set a should-total via the --should flag.

Bookmarks

Bookmarks are a powerful feature that allows you to reference often-used files from anywhere via a short alias. That way, you don’t have to specify the full path of a .klg file, or navigate to the directory where it’s stored.

Bookmark names are identified by the @ prefix.

Setup and use bookmarks

The following command would define a bookmark @work pointing to the file ~/work/2021-01.klg

TERMINAL
klog bookmarks set ~/work/2021-01.klg @work

With that bookmark, you can now use @work as input argument for klog commands. It will be automatically resolved to the designated file, regardless of your current working directory.

TERMINAL
klog total @work
Note: On Windows Powershell, the @ operator is reserved syntax. Therefore, when using Windows Powershell, you either have to escape bookmark names with a backtick (`@mybookmark) or wrap them in quotes ('@mybookmark').

Additionally, you can also specify one unnamed bookmark. This is useful in case you only use one .klg file anyway. (Internally, it’s identified by the special name @default.)

TERMINAL
klog bookmarks set ~/work.klg klog total

Navigate to your files

With bookmarks, you can also navigate to your files more easily. The following command will open the bookmark in your favourite editor (based on the $EDITOR environment variable).

TERMINAL
klog edit ~/documents/times.klg klog edit @times

You can also open the file explorer at the location of the bookmarked file.

TERMINAL
klog goto ~/documents/times.klg klog goto @times

Editor support

The following editor plugins are independent projects, which are created and maintained by other users of klog.

VSCode

Sublime Text

vim LogoVim


Your favourite editor is missing? Feel free to create your own editor plugin based on the klog file format. In case you need the klog logo, see here. Please share your tool here so that it can be linked from this list.

Extending

In order to tailor klog to your own needs and workflows, or to build your own custom tooling around it, there are various ways to extend or enhance the functionality of the klog CLI tool.

JSON subcommand

The easiest way to process klog data in your own application is to run the klog json command as subprocess. This converts klog data into a JSON data structure, which can be easily read with standard JSON parsers.

You can either specify a filename to read from, or you pass the data via stdin.

In order to learn about the output structure, just run klog json --pretty on a file – it should be self-explanatory. You should also try it on a file with syntax errors, to learn how the error structure looks.

Shell scripting

For recurring workflows, you could write your own shell scripts. The klog CLI has multiple features to make that process easier:

Go library

The klog CLI is written in the Go programming language. Therefore, in case your app is written in Go too, you can also integrate with the sources directly via Go modules.

Note: there is no separate release cycle of the source code itself, so the code structure and APIs can change anytime without prior announcement. Therefore, you should pin your dependency to a specific commit hash.