Recently we’ve been reading “The CEO Within” at a book club at Toptal, where there was a chapter on todo tools. I haven’t been happy with my current setup, which is basically Asana + GCal. Yeah, it’s functional, but it doesn’t have that special something and it’s very slow.

Moving from asana + P&P

You know how you ride your bike for a while, and then notice that maybe your tires are underinflated, you pump them up and it turns out you were wasting so much effort by riding around on flats? Well that’s my feeling when I went from Asana to Taskwarrior.

Checking the next task is Asana was a matter of opening my main browser, navigating to a specific tab and then looking for the next important task. If that task was not important I could either navigate down the list or move the task down. I could also change the due date. All this took seconds, while the decision took fractions of seconds.

Currently checking my current task is a pressing Super+Z and moving on to the next task is 3 keystrokes. Makes my system able to keep up with my mind.

Because of these and more, I didn’t really allow Asana to be my daily driver since it would slow me down too much. It was pretty much a reminder system for each bill and chore that I had to do on a regular basis and also a system for putting stuff in for later.

Thus my quick todo was pen and paper which was often a quick access copy of Asana tasks. It was reasonably efficient, which is probably why I held on to it for so long.

The problem was, I really couldn’t do much about the speed of Asana, while Taskwarrior is nimble enought I can make it do anything an integrate into my very brain.

Speed of operation

If you’re using Taskwarrior and you feel separate from the tool, it’s on you. Here’s a few tips that I can give you in order to get the maximum out of TW:

  • The shell should be at your fingertips: Have a dedicated personal TW only terminal, like Guake or Tilda.
  • Make aliases - Look at you usage patterns and make aliases to what you do on a regular basis. You’ll find a few at the end of this post to get you started and give ideas.
  • Write your own tools (see next section).
  • Have a nice routine, tailored to what you want to do. Improve it with time as you grow and get to know the tool.

The power

With the power and the interoperability of the command line, there’s no end to what you can achieve. I will give you a few ideas here that I setup for my own personal flow, but you will want to start customizing this ASAP.

Task based on time-of-day and day of week.

This one’s pretty obvious. I work from home so I have to keep vigilant as to not overwork. Well this can be easily achieved by changing the priority values of projects. You can see the full script here but here’s the heart of it:

if is_weekend?
  configs << 'rc.urgency.uda.project.Me.Skills.coefficient=4'
  configs << 'rc.urgency.uda.project.Fun.coefficient=4'
  configs << 'rc.urgency.uda.project.Toptal.coefficient=-8'

if hour >= 19 # should be winding down now
  configs << 'rc.urgency.uda.project.Toptal.coefficient=-5' unless is_weekend?
  if hour >= 22 #too late for work, good time for relax
    filters << 'project!~Toptal'
    configs << 'rc.urgency.uda.project.Fun.coefficient=5'

Basically: push down urgency on the weekend for work related stuff on the weekend and in the evening, cut everything from work after 20:00. I challenge anyone to find a tool that will allow you to do this - the closest I’ve got so far is to use contexts (like @work) but those require manual switching.

Current task keyboard shortcut.

This is a wonderful way of keeping focused on the task at hand. A split second keystroke and you’re reminded of what you should be doing. This has thwarted many a yak shave. If you find yourself doing something else than you currently have in TW you have 2 options:

  • continue with the yak shave - only do this when you can finish within 2-5 minutes,
  • add a new task to TW - you can either start on this task immediately if you feel it’s better to not lose context or just let it sit there if you feel it’s not that important and can be caught later on.


Mobile is complicated (for now)

I’ve always felt that I have to have at least as good access to my todo when I’m on my mobile and on a computer. I have to admit that I’ve been lying to myself all those years.

I HATE working on mobile devices. Everything screams inefficiency when I’m doing it. The lack of keyboard, the small screen, everything sucks. Having said that, there are a few things that I want to have on my mobile: - A quick way to enter todos for later processing. - A way to look at my TW tasks for specific contexts I’m likely to work on mobile.

Entering todos on mobile

Currently I just make do with adding ideas into Simplenote (my go to note manager) and then working at them from home. I might take a stab at something more complicated this later on. I currently also use Android, which allows me to add notes via Google Assistant that will end up in Simplenote. Fast and clean.

Task preview on mobile

Currently this has not been a priority for me. I honestly don’t have that much mobile tasks to work on and the amount of work is not worth it. In case you need this functionality, here’s some preliminary research I did:

  • Read only dead simple task list. Add a hook for on-add to dump the mobile tasks (a tag probably) and upload the file to an accessible remote location. Have the location bookmarked.
  • Use WingTask. Has more goodies and is a full on mobile client.

No sharing

I’ve seen people trying to share tasks in TW. I don’t think any approach is worth trying. TW is a more low level tool, personal and only for you. You can customize it with the weirdest habits that you want without asking permission. Do your work, then come back to the other tool to catch the rest of the team up on what you did.

My flow

Before I start, let me just point you to the Workflow Examples page on the Taskwarrior website, which gives some alternative workflows from people working on the software itself. It’s pretty eye opening that even the creators use the software in quite a diverse way.

Adding the tasks - in bulk

Before you start doing and organizing tasks, you need to add them. This will vary wildly according to whether you’re starting fresh or importing from something else. My use case was moving from Asana, which mostly meant I was moving tasks within whole projects.

Here’s a little script that will help you, put it into your aliases file:

function ta_proj() { echo "$2" | vipe | tr '\n' '\0' | xargs -0 -n1 -t task add "project:$1"; }

This basically allows you to do: ta_proj Home.Financial and it will open a shell editor. You can then enter a list of tasks that will land in the Home.Financial project. Once you’re done bulk inputting your tasks, we can move on to managing them.

Adding tasks: daily:

It starts with a review

tasksh is a companion tool that tracks your tasks and makes certain that you have to review them periodically.

The period will vary from person to person, I set mine to 3 weeks. Set it too low and you will spend a lot of time on reviews. Set it too high and you’ll have incentives to have lots of bad tasks created.

Every morning I run tasksh and make sure the task for review are:

  1. Actionable - The task has enough information gathered and preparation done so that you can start working on it immediately. This takes a bit of experience and for each task is different. I try to make my tasks last no more than 20-30 minutes, but this is more of a private preference. The key here is not not get bogged down with research and yak-shaving and to have something concrete accomplished at the end of the task.
  2. Assigned a project - after some tweaking, this will assure that the tasks you do are ordered in a proper manner and you will hardly need to do readjustments. It also assures that when you want to timebox a specific project you can query for specific tasks. Or if have some kind of date/time priority changes like I showed before this will have the data to work on it.
  3. Still valid - if you haven’t touched a task in a while and you don’t really want to do it, then why do you still have it? Deleting tasks is as good as completing them, you’re trimming away the fat and making space for new more exciting things.

The daily priorities

I then look at the 10 next tasks from my todo list (task limit:10 next). I check whether the order look right and I play with the priorities a bit. Sometimes that just means changing the priority for a single task, sometimes for a whole project or recurring task.

The goal is to have the next command give you a list of tasks that you can act on with minimal changes.

Make one final check that all items are actionable. Use the GTD definition: it needs to be a small concrete task that you can start working on immediately, without additional research or preparation. If the task does need additional things, create them as tasks and mark the original task as dependent on the task so that it goes down in priority.

I can’t stress how important this is: this is your goal for the day. It needs to reflect what you need to be doing with the proper order.

Capture - simple tasks

Capturing tasks is one of the more important parts of any good task system. It needs to effortless and quick. It also needs to strike a balance between quick entry and not making a mess.

On one end of the spectrum, you can just add tasks into one big bucket without much thought and end up with a badly maintained list that will be hard to prioritize. On the other end, you take too much time to enter a flawlessly worded and organized task.

My approach to this is usually on the faster side. I enter tasks with a description good enough to not forget what the’re about, but don’t assign any projects or special tags. These will be assigned the next day on the review phase. I currently have 3 aliases for day-to-day task adding.

  • alias ta="task add" - run of the mill quick add new task, no project, nothing, just a description
  • alias tan=task add +next - usually this is something quick but important
  • alias ta_tt="task add project:Toptal" - project specific task add. I have at most 2-3 of these on hand only for the most used projects.

I also have a more complex ta_proj alias to bulk-add tasks that I’ve already described earlier. I’m also planning a helper task to more easily created more complex task hierarchies. The current system of dependent tasks is pretty fiddly to add more tasks quickly, but that’s a topic for another post.

In summary

Taskwarrior is a great piece of sofware and it’s well worth your time. If you spend a lot of time in the console anyway and have some programming chops, you might just fall in love with it.

PS. Aliases

Here’s my current list of aliases and their usage. Take this as a starting point for your own customizations.

  # Taskwarrior
  alias t='task'
  alias tsh='tasksh'
  alias tt='task next limit:10'
  alias ta='task add'
  alias tpr='task projects'
  alias tp_='task _projects'
  function tp() { task "proj:$1"; } 
  alias tdd='task +OVERDUE list' # Show all tasks that are overdue. This is sometimes more urgent than the urgency.
  alias tan='task add +next'
  alias tac='task add project:Pro.Consulting'
  function ta_proj() { echo "$2" | vipe | tr '\n' '\0' | xargs -0 -n1 -t task add "project:$1"; }
  alias tnv="task next rc.verbose=nothing limit:1 | festival --tts" # Uses festival to say the current task.
  alias tnn="notify-send \"$(tn rc.verbose=nothing limit:1\"" # sends a notification with the current most urgent task, this makes sense more as a keyboard shortcut than invoked in the console
  alias ta_tt='task add project:Toptal' # use something like this for projects you add to daily
  function tu()  { taskid=$1; shift; task $taskid modify $@; } # shortcut to modify tasks 
  function tun() { task $1 modify +next; } # make very urgent
  function tuh()  { task $1 modify priority:H; } # make a bit more urgent
  function td()  { task $1 done; } # set to done
  function ty()  { task $1 start; } # I usually only use start as a way to remember what I started + bump urgency, don't use the statistics it gives
  function tw()  { task $1 rc.recurrence.confirmation=off modify wait:tomorrow; } # put off until tomorrow
  function tw1h()  { task $1 rc.recurrence.confirmation=off modify wait:+1h; } # put off for one hour