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 doingto get the latest version (2.0.11 as of this writing). Then run
doing helpto see all available commands, and run
doing help COMMANDto get info on each one. I’ve tried to keep it as self-documenting as possible.
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:
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
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
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
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
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
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,
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.
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
--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
--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.
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
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.
config command opens your configuration file in an editor. In 2.0, it also
.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
config to output a configuration value for you. Want to see which
Doing file the current configuration (including local config) will affect? Just
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
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
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.