I’ve pushed Doing 2.0 out to the world. It’s the result of a year or so of tinkering on and off, with some extra love recently, and it comprises enough refactoring, fixes, and improvements to truly warrant the major version bump.

I’ve had a few manic episodes in recent months that have found me obsessively coding on personal projects for hours at a time. I’ve put out new releases of Marked 2 and Bunch, updated multiple open source projects, and spent a ton of time on projects at the day job. So much so that it’s been… (glances at homepage)… a month since I blogged.

I work on myriad projects, but Doing is always the common denominator. No matter what project I find myself hacking away at, I’m constantly tracking my time and progress using Doing. (I even use git commit hooks to add entries to my log whenever I make a commit in one of my projects.) And when I’m in “obsessive coding mode,” every time I use Doing, I think of new things I wish it could do. (Things I wish Doing did? Was doing?) Anyway, a thousand side-tracks to work on Doing have culminated in the first major version bump since its initial release.

To catch you up, Doing is my command line tool for tracking what I’m spending my time on. It has tools for adding entries, tagging them, searching them, tracking time, and outputting reports in various formats. It stores all of this in a plain text file using (slightly proprietary) TaskPaper formatting, easy to port and parse elsewhere.

The project page on this site used to have documentation for all of Doing’s commands and options, but trying to continue fitting it all on one page got very unruly. The documentation has been reorganized and moved to the Doing wiki on GitHub. (If you just want an overview of all possible commands, I did a little RDOC->Markdown conversion to generate an All Commands wiki page.)

There’s so much new stuff that I can’t fit it all into an announcement post like this. Read on for the highlights, though.

If you’d rather play than read, just run gem install doing to get the latest version (2.0.11 as of this writing). Then run doing help to see all available commands, and run doing help COMMAND to get info on each one. I’ve tried to keep it as self-documenting as possible.

Output Improvements

First off, there are some template improvements. In Doing you can define templates in the configuration to change how the output of various commands appears in Terminal, and 2.0 adds features and improvements for formatting dates, titles, and notes in new ways. There’s a whole printf formatting vibe going on with the %note placeholder now… See Templates on the wiki for details.

Here’s how my default template displays:

Doing show output with custom template

I also added a pagination option to the output. It has to be enabled in your config using paginate: true. If enabled, any time a command’s output is taller than the current terminal, the output will be paginated for you to scroll through with keyboard shortcuts.

Speaking of sprucing things up, Doing has a whole logger system now, complete with log levels and the ability to run verbosely or quietly. And the log output is colorized and formatted for nice command line feedback. All messages are delivered to STDERR so you can still pipe output to other commands.

Import/Export… and Plugins

In the process of refactoring the import and export capabilities of Doing, I decided that it would make the most sense to build it out as a plugin architecture. I don’t know if anyone will ever write their own plugins, but making it user-accessible was easy enough once I’d converted my own tools. You can create new importers, exporters, and even add custom subcommands now. See Creating Plugins for details.

The plugin architecture also adds Hooks, and you can use events like ‘post-config’, ‘post-read’, and ‘post-write’ to trigger your own scripts. These can be external things (like updating a BetterTouchTool widget whenever the Doing file changes), or you can actually access/modify the Doing file content and config options in memory and have the changes written out.

Using the new architecture, it was easy to add importers for Calendar.app, Timing.app, and even the ability to import from other Doing files (handy with the rotate command I’ll mention in a second). I’ve been regularly using Timing.app to update my Doing file with activities I wasn’t tracking on the command line.

Plugins have extended the available output formats as well, with pretty-printed JSON, Markdown and TaskPaper, improved HTML, and even a tag Wiki (via a demo plugin). I improved the interactive timeline output as well. It’s not perfect, but when it works, it’s cool… (if you have bcat installed, try doing show --output timeline | bcat)


Doing is great when you’re on top of it and constantly feeding it well-tagged, annotated data. But that’s rarely a reality for me. I often want to make a change to an item I entered yesterday, or need to end a timer on a task I forgot to mark finished, or add a retroactive entry, add a note, or any number of things that – if you wanted to modify anything other than the most recent entry — used to be easier to just open TaskPaper for. A lot of the improvements in 2.0 are designed to solve these kinds of problems and keep me on the command line.

First, almost every command now accepts flags like --search and --tag, allowing you to perform the command on entries matching a tag or text search, rather than just the most recent entry. And you can add --interactive to most commands to get a filtered menu of results, allowing fast navigation and multiple selections (using fzf, which is now included) to pinpoint the entries you want to tag, edit, delete, flag, cancel, etc.

There’s also a doing select command that centralizes a bunch of these tools into one interactive command. You can pass it filters or just have it display a menu of your entire Doing file, then use type ahead searching to select the entries you’re looking for. If you didn’t specify actions in the command itself, it will offer you a menu of tasks you can perform on the selected entries. Add/remove/rename tags, bulk edit entries, delete, cancel, and more. And you can perform multiple tasks at once, which saves a few more commands.

Time Tracking

I’ve been using Doing for time tracking for a long time. Every entry gets a start date when it’s created, and an end date is added when it’s completed with doing done or doing finish. Any @tags contained in the entry can then have an elapsed time assigned to them, so it’s easy to see exactly how much time I spent on, say, @doing in the last week (doing show @doing --totals).

Doing 2.0 brings a lot of improvements to time tracking details. The --back and --at flags are improved, and can be used with --took for easy retroactive time tracking. When adding or completing an entry, you can use these to easily fudge the start and end time. If I want to retroactively record a 30m entry from this morning, I can just run doing done --at 8am --took 30m A quick writing project. And I can start a new entry and indicate I’m already 15 minutes into it with doing now --back 15m Writing about @doing 2.0.

Sometimes I don’t want an entry to have its time tracked. All you need to do to avoid having an elapsed time is to add a @done tag with no value. To aid in this, you can now use doing cancel to cancel the current entry. You can use cancel with --search or --tag filters to get to older entries, and/or use --interactive to select entries to cancel from a menu.

I also added doing again to repeat the last entry with a new timer. again can use search filters to allow repeating an entry from anywhere in the Doing file, duplicating it, removing the @done tag, and starting it again as a new entry.

I haven’t documented it well yet, but you can configure certain tags to never get timers. Any time a never_time tag is present on an entry, it won’t have a date added when finishing it. This means you can have a tag like @idea that prevents elapsed time from being tracked on entries that are more notes than time slips. You can even configure a tag like @todo to keep track of future tasks, with commands like doing begin to turn @todo entries into doing now entries.

Other Stuff

The config command opens your configuration file in an editor. In 2.0, it also locates “local” .doingrc files in the current and parent directories (which merge with the main config when Doing runs) and offers a menu for selecting which file to edit. There’s also now a doing config get command that allows config to output a configuration value for you. Want to see which Doing file the current configuration (including local config) will affect? Just run doing config -d doing_file. It accepts a full key path with fuzzy matching, so you can run doing config -d plugin.say.voice to drill down, and can output in YAML, JSON, or raw text.

I also added a rotate command which is similar to archive, but instead of moving entries into the Archive section of the file, it moves them to an entirely different file, preserving parent sections and all meta. It generates one dated file per day, and any additional rotations on the same day are added to that file. It’s based on the idea of log rotation. Once your Doing file gets big enough, things slow down, and there’s not usually a need for that much historical data day to day. So now it can just dump it out to dated archive files using a command like doing rotate --before 6/1.

And then I went nuts with shell completion. I originally only had completion for Bash, back in the day. Zsh completion was contributed but fell out of date pretty quickly as I added new commands, and I’m not good enough with Zsh to maintain it. Well, I wasn’t, but I got better. I think. I don’t use Zsh enough to know for sure. Anyway, I wrote some scripts to generate the completion files for Bash, Zsh, and Fish, and you can run doing completion to output fresh scripts. doing completion --type zsh --file ~/.zsh-completions/_doing.zsh would output a Zsh completion script directly to a file, with every command (including ones generated by plugins) and its options. The Fish completions are the best, as that’s where I spend 99% of my time, but the others seem to be working well. There’s always room for improvement, so if you have time to look deeper into improving them, please lend a hand! There are just so many subcommands and options at this point that running Doing without autocomplete is… annoying.

Well, this really should be a whole series with a post on each area of interest to me, but I’ve never had a good feel for how many people actually care about Doing (850 stars on GitHub isn’t nothing, but I have no idea how many people actively use it). I put time into it because it’s a fun obsession and something I find useful every day. So I’ll keep building it for myself, and if you want to check it out, offer suggestions, or pitch in, I’d welcome your input.

I’ll probably write more soon and try to do a bit more justice to the new features, but my primary focus will be on improving the documentation. Which, by the way, is where you can find more details on the stuff I touched on here. Doing is open source and you can install it with a single command.