Michael R. Cook Ruby and Golang Developer

TimeWarrior 1.0.0 - A golang time tracker

After barely programming in Go these past two years I really wanted to get back into using the language, and figured a good starter project would be to port my Ruby time tracker to Go. So a few weeks back I started rewriting that old CLI application in Go, and have now released TimeWarrior 1.1.0 on Github.

TimeWarrior is a CLI based time tracking application used to record timeslips for your freelance and personal projects. Timeslips for a project are stored in their own project data files, with each timeslip saved as a valid JSON string.

Project and Task names are given as CamelCase; separated by a period. You would start a new timeslip like this:

$ tw s MyProject.SomeTask

You can pause and resume a timeslip at any time (the p and r shortcuts are available), and once work on a task is complete, you can mark it as done:

$ tw d "Some nice description of the work"

It’s also possible to adjust the time you’ve currently worked on a pending timeslip with the adjust command:

$ tw adjust 10m

I recommend you visit the Github repository which has full installation and usage instructions.

At the moment you will need to build the executable yourself, but hopefully I’ll have ready-made downloads for Windows and macOS soon, once I’ve run some tests on a Windows machine!

Please note that there’s currently no reporting functionality. I have a simple old script for my own needs, which I’ll eventually look into adding to the app.

If you’re impatient and you’d like to implement a report command yourself, please feel free to submit a PR!

The Backstory

As I wrote above, this Go version is a rewrite of an old Ruby GEM; two major versions that I’ve been running now for the past five years.

Back in 2012 I’d started with a lot more freelance/consulting work and was tracking all my time using the excellent Sigma tool from Arrow UK, which integrated directly with the online accounting software I used at the time. However, not only did I want more control of this data, I also wanted to start tracking time for my own projects, so needed something more independent.

After some research I found the very nice TaskWarrior app, but this is really a TODO list rather than a time tracker. In fact there were a number of other possible solutions but none that would allow me to generate simple timeslips, so I wrote my own.

TaskWarrior did have some nice features, which I used as inspiration for my own app: I liked how they used the Project.Task format for naming of the project/task as well as their pending/complete file format - okay, so you might also notice that the name is similar; originally TimeWarrior was just a WIP name, but well, it seems to have stuck over these last 5 years!

Here’s an example of that first timeslip data format:

$ cat time_warrior/completed.data
[description:"Some task" end:"1330647345" entry:"1330646400" modified:"1330647345" project:"ProjectName.SomeTask" status:"completed" uuid:"93802d17-7f67-453e-9678-c86b135fe6d0"]

This worked well for a while, but I didn’t like the commands and that data format was not so nice to parse. So with new ideas in hand, I created v2. The UI was update, which was actually very similar to the new Go version, but I also refreshed timeslips format from a custom string to a valid JSON string:

$ cat time_warrior/completed.data`
{"project":"ProjectName","task":"SomeTask","comment":"some work on a task","started":"1441148400","duration":"1560","finished":"1441149960","modified":"1441149960","status":"completed","uuid":"8a0f6ad1-84fc-4eec-bc9a-87fa38215d0c"}

Although the key names changed, it’s mostly the same. I refrained from wrapping everything in an array [{"project":"Name" ...}] to reduce the need to parse the file contents when adding a new timeslip, which also meant there was less chance for data loss.

The latest Go version of TimeWarrior saves timeslips in a project based data file, and renames a couple of field names.

$ cat time_warrior/time_warrior.json
{"project":"TimeWarrior","task":"GoRewrite","description":"App setup","started":1442660653,"worked":6877,"finished":1442669388,"modified":1442669388,"status":"completed","uuid":"0ad1db06-4d76-4edb-bf3b-6f54a9d5a2e2"}

Project data files are generated from the CamelCase project name, by converting to snake_case. duration is renamed to worked and comment to description.

The CLI commands are also mostly the same, with the biggest change to starting a new project, changing from tw s -p Project.Task to tw s Project.Task …fewer key strokes is always a good thing!

A new adjust command was added for this release - I was always forgetting to pause/resume a timeslip so needed to edit the .pending file and manually adjust the time. Now there’s a command for that!

Although the first public release of TimeWarrior has been given a version of 1.0.0, to me this is really v3.0.0.

Leave a Comment

About Me

Hi, my name is Michael and this is my personal blog. Here I’ll be posting my coding thoughts and experiments, specifically in regards to building websites in Ruby (Rails, Roda, Sinatra, etc). This site is powered by Thunderaxe, a blogging platform I’m building using the Roda Ruby framework, which I hope to be open sourcing in the near future.