ToDo's On Your Desktop

I’m not going to lie and tell you that I’m great at task management. Frankly, I suck and I blame it on technology. If only there were a task system that could light a fire under my butt. We all know there isn’t, but the system that I’ve found to work best for me is Todoist. Todoist is really light and fast. Also, it has a simple API so it’s very extensible and already has a lot of tools surrounding it (quicksilver, launch, dashboard widget, mobile, gmail integration, etc).


The Problems

The problem that I have with task management is two fold. First, I need reminders. My programming brain is sharply trained to scoot information in and out, only keeping what is immediately necessary. It’s great to have a to do list but if it doesn’t remind me, it barely works. The good news is that todoist has a premium service that is only $3/month (yes only $3) that allows for reminders in any form you like (twitter, sms, email, jabber, etc). First problem solved.

The second problem that I have is that sometimes a reminder is not enough. I personally need to see my upcoming projects, tasks and calendar items in front of me anytime I can. It hit me the other day that I look at my desktop a lot. This got me wondering if I could use the todoist API to put my upcoming, date sensitive tasks right there, on the desktop, in front of me whenever I’m on my laptop.

The Solution

I did some googleing and found Geektool, which I had installed/uninstalled before but this time seemed to have a purpose. The end result is in the screen cap below.


To do this, I created a quick and dirty ruby script to hit the todoist api and put out a simple list of all time sensitive tasks. 1) I put the following script at ~/bin/todoist.rb.

require 'yaml'
require 'rubygems'
require 'rio'
require 'json'
require 'active_support'

def todoist_query(*args)
  token   = args.pop
  queries = %Q{["#{args.flatten.join('","')}"]}
  url     = "{queries}&token=#{token}"

lines, now   = [],
config = YAML::load(rio(File.join(ENV['HOME'], '.todoist')).read)
format = '%Y-%m-%dT%H:%M'
days   = ( => config['days'] || 3)).step(

todoist_query("overdue", { |d| d.strftime(format) }, config['token']).each do |type|
  next if type['data'].size == 0
  lines << (type['type'] == 'date' ? Time.parse(type['query']).strftime('%b %d').gsub(/\s0/, ' ').upcase : type['type'])
  type['data'].each { |i| lines << " - #{i['content']}" }
  lines << "\n"

puts lines

Like I said, it’s quick and dirty. 2) Now setup geektool to run the script at a given interval (I chose 2 minutes).


3) I created a file in my home directory to store my todoist token and the number of days I want to show. The main reason I separate the token from the ruby script is in case I feel like using it somewhere else on my system with another script. If my token ever changes, I can update it in one place and all the scripts will still use correct one. Anyway…I put the file at ~/.todoist and it looked something like this:

token: foobarbaztoken
days: 4

Now every two minutes the script runs and updates based on how I am updating my tasks at My tasks are continually in front of me, which helps keep them in my mind so that I actually get stuff done.

Other Uses

Some other uses I could see valuable for this would be calendaring. Google Calendar has an API so you could hit that and show your upcoming events right by your tasks. Maybe there is some site that posts a lot of updates and it’s hard to keep up with by feeds? Just use feedtools and a tinye ruby script to show the latest posts for your perusal when you get a few seconds. Just some thoughts.

Anyone else do something along these lines? Have some code to share or thoughts on how to do it better? Let me know.


  1. Whoa, why hadn’t I heard of GeekTool before? I am going to nerd out on that in a major way. The possibilities are endless.

  2. You should check out! :)

    Reminders are a good point. Should be fairly easy to do considering it’s based on twitter.

    You can always let me know what you would like to see added.

  3. Usefull, thank you!

Sorry, comments are closed for this article to ease the burden of pruning spam.


Authored by John Nunemaker (Noo-neh-maker), a programmer who has fallen deeply in love with Ruby. Learn More.


Release your software more often with fewer problems.
Flip your features.