43 Folders

Back to Work

Merlin’s weekly podcast with Dan Benjamin. We talk about creativity, independence, and making things you love.

Join us via RSS, iTunes, or at 5by5.tv.

”What’s 43 Folders?”
43Folders.com is Merlin Mann’s website about finding the time and attention to do your best creative work.

Michael Buffington: iGTD + Quicksilver + subversion

by Michael Buffington

This is the second entry in a multipart series about my recent obsessive love affair with GTD, the iGTD application and Quicksilver.

In the last entry I put the emphasis on getting my tasks written down quickly and out of my focus into a system I could trust. I could choose to spend some time later to review my tasks and do what I like to call "iGTD gardening", where I check up on all my projects and do a bit of weeding of duplicate or irrelevant tasks, and fortify those tasks with whatever information comes to mind as I'm looking at them.

Since I'm now in the habit of pushing new tasks to iGTD and immediately forgetting about them I have the refreshing ability to work on a task without ever thinking about anything else. iGTD then becomes my set of instructions to follow when I need guidance, and if I've tended my task garden well, it's a rich set of instructions with a lot of tedious thinking already finished.

This system works out alarmingly well until you're possessed by SSD (severe stupidity disorder) and delete your iGTD database without even a whiff of lingering vapors. Immediately you'll be consumed by a profound and unshakable dread as you realize your tether has been severed from the mother ship and you begin to drift into outer space, your Tang to be divided up amongst your colleagues (even the ones you loathe).

Luckily for most of us, iGTD makes database backups upon starting up the iGTD app and for a couple of other events, and luckier still, most of us don't suffer from SSD very often.

But I often do, and don't leave anything to chance.

Rather than risk losing my entire brain to an episode of SSD I employ a SMP (scheme of massive paranoia). It might seem quite heavy handed, but I send a backup of my iGTD data to a subversion repository whenever the iGTD database changes. In a nutshell, it means I have a comprehensive history of every save ever done to my iGTD database, and am nearly assured that I'll be able to save myself from myself with only the smallest amount of data loss.

Now I'll be the first to admit that what we're about to look at is a bit Rube-Goldberg-esque, and I'll admit there's a certain joy in that as well.

A few things to know before we move on:

  • I'm doing this all on Tiger, which means I have both Ruby and sqlite3 installed out of the box.
  • Your paths to both Ruby and sqlite3 might differ from mine.
  • This code likely has bugs. I whipped it up in a few hours.

Also, worth noting - I'll be adding to this body of code as I move on with more blog posts about iGTD. What may look a bit like an empty shell now will get some more meat as we go along.

And finally (I promise), all the code I talk about in this series will be downloadable at some point.

Create some Ruby!

Create a file called iGTD.rb in /usr/local/lib/ruby (or /opt/local/lib/ruby if you're using the Macports version of Ruby like me).

Write the following code:

class IGtd
def self.capture(string)
i = IGtd.new
puts string

def push_to_igtd(string)    
    `/usr/local/bin/sendtoigtd "#{string}"`  


That'll start off our iGtd library with something basic. It seems totally superfluous when you think about it, but remember, we'll be adding to this at a later date.

The newest version of iGTD (v. 1.4.5) comes with a command line utility that allows you to pass your task along the same way you push tasks into iGTD through the Quicksilver plugin. The above code simply wraps some Ruby around that command, executing it when we call it, which we'll come back to in a moment.

Now we're going to take advantage of a Quicksilver feature that you might not see documented many places - you can pass text to Ruby scripts saved as action in ~/Library/Application Support/Quicksilver/Actions. Up until recently I assumed you could only have AppleScript actions, but that's not the case.

Let's see some of that Action in action. Create a file called gtd.rb in ~/Library/Application Support/Quicksilver/Actions that looks like this:


require 'iGTD' IGtd.capture ARGV.join(" ")

This script takes whatever commands are passed in, joins them back up as a single string, and hands them to the IGtd.capture method we wrote above. Note that we join the string back up because Ruby splits up command line arguments into an array wherever it sees a space. So we simply reverse that process by adding the spaces back in.

Make sure you make the file executable. chmod ug+x gtd.rb should do the trick.

Once that's saved you should be able to invoke Quicksilver, press period to invoke text mode, hit tab, then type gtd. Your gtd Ruby script should show up in the list (if it doesn't you might need to restart Quicksilver [CTRL-CMD-Q]).

Now, despite the fact that you're using your own Ruby based action instead of using the iGTD Quicksilver plugin, your task will end up in iGTD.

Neat, but we're missing the paranoia. Let's add subversion commits into the mix.

At this point I have to assume that you've managed to get your iGTD.sql file located at ~/Library/Application Support/iGTD into a subversion repository, hopefully offsite. I'm gambling on the fact that you have some knowledge of subversion if you have any desire to do this at all.

Because the iGTD.sql file is binary, we want to dump it as raw text to be a bit more efficient with subversion. subversion only keeps track of differences between revisions with ASCII files, but keeps entire copies of binary files (which might not seem like much, but for a file that's in the 60-80k range, 6000 changes can turn into a 500MB subversion repository).

Having the iGTD.sql as an ASCII dump helps increase portability as well. You can rely on simple text editors to see your data with an ASCII dump, and in the worst scenarios, viewing raw SQL statements can be quite comforting if the alternative is viewing nothing at all.

Let's add the following method to our iGTD library (note that when you see a ↵ symbol that what should normally be on a single line is wrapping to fit the page - make sure you fix those lines if you're copying and pasting):

class IGtd
    def self.capture(string)
        i = IGtd.new
        puts string

def push_to_igtd(string)    
    `/usr/local/bin/sendtoigtd "#{string}"`

def commit_to_svn
# tidy up some of the paths
igtd_data_path = "/Users/mike/Library/Application Support/iGTD"
svn_path = "/opt/local/bin"
sqlite_path = "/usr/bin"

# dump the sqlite db to an ascii backup file
`#{sqlite_path}/sqlite3 "#{igtd_data_path}/iGTD.sql" ↵
    .dump > "#{igtd_data_path}/iGTD.sql.automatic.bak"`

# commit it to svn
commit_msg = `#{svn_path}/svn ci "#{igtd_data_path}/  ↵
  iGTD.sql.automatic.bak" -m "Automatic backup of  ↵
  iGTD.sql backup file done: #{Time.now}";`

# if no changes were made, svn won't output anything - it'd ↵
be nice to know that we at least tried.

if commit_msg == ""
  commit_msg = "Nothing to commit, therefore no svn commit was done."      

# now send the message to growl
`echo "#{commit_msg}" | /usr/local/bin/growlnotify`    
return commit_msg

end end

Now, whenever you push tasks from Quicksilver to iGTD through our gtd.rb action, subversion will commit the changes. I've added the luxury of being notified by Growl when the commit happens. Pay special attention to the paths in the script and make sure you're pointing to the proper places.

With this in place, not only are my backups effortless, but they're comprehensive. And because my subversion repository is on a remote server, I can reconstruct my task list as long as I have a computer and an internet connection. Given enough time to think about it, I'd probably get paranoid about my subversion server keeling over too. Entertaining those thoughts to their final conclusion would require I hire stone carvers and buy a large granite mountain to chisel my lists, so at this point I'm content with the offsite backup.

This extreme paranoia with an admittedly heavy handed solution helps increase my trust level with iGTD, but it also opens the door to doing other automatic tasks whenever I enter a task through my custom gtd.rb file.

In the next entry in this series I'll show you how you can enter a task in iGTD once and have it travel to both Stikkit and Basecamp with a few additions to the iGTD Ruby library discussed here, and even grab new tasks from Stikkit.

Following that entry will be something I consider quite special - getting tasks into iGTD from your mobile phone through SMS. Assume the bullfighter's stance and repeat after me: ¡muy emocionante!

About the Author

Michael BuffingtonMichael Buffington - A serial entrepreneur and creative technological consultant, Buffington most recently served as the Community Advocate for Values of N, makers of Stikkit and iwantsandy.com. He's now secretly building games for the masses.

Jason Kohles's picture

If you are paranoid about...

If you are paranoid about your subversion server keeling over, here is how I deal with that risk... I use this script in a post-commit hook, to automatically dump the repository to an archive, compess it, encrypt it, and then send it to my gmail account.


REPO="$1" REV="$2"

echo "Running gmail-backup-svn $REPO $REV" R=echo $REPO | sed s,/var/svn/,, # change if your repo is not in /var/svn export HOME=/home/jason # needed to find gpg keys if the hook doesn't run as you

( echo "From: email@example.com" echo "To: myexampleb+backup@gmail.com" echo "Subject: [SVN-BACKUP] $R" echo "" if [ -n "$REV" ]; then echo "Revision: $REV"; fi for I in seq 1 40; do echo ""; done

/usr/bin/svnadmin dump $REPO \
| /bin/gzip -c - \
| /usr/bin/gpg --armor --trust-model=always --recipient $GPG_KEY_ID --encrypt

) | /usr/sbin/sendmail -oi -oem -odq myexample+backup@gmail.com




An Oblique Strategy:
Honor thy error as a hidden intention


Subscribe with Google Reader

Subscribe on Netvibes

Add to Technorati Favorites

Subscribe on Pageflakes

Add RSS feed

The Podcast Feed


Merlin used to crank. He’s not cranking any more.

This is an essay about family, priorities, and Shakey’s Pizza, and it’s probably the best thing he’s written. »

Scared Shitless

Merlin’s scared. You’re scared. Everybody is scared.

This is the video of Merlin’s keynote at Webstock 2011. The one where he cried. You should watch it. »