Tickler File

MAK (18 Dec 2004) - In the book "Getting Things Done", author David Allen describes a system of deferred reminders and loose task scheduling that he calls the Tickler File. One of the basic tenets of the book is to use your inbox *really* as an inbox, and not as a collecting point for random piles of everything you haven't done, reviewed, deferred, etc. Another is that calendars should be used only for items that MUST be done on a specific day. The idea is to get things that don't need your immediate attention out of sight and out of mind. The Tickler File is one of the tools that can be used to do so. Given the name, I thought it appropriate to implement one in Tcl. :)

Briefly, a Tickler File is a set of 43 folders: one folder for each of 31 days, and one folder for each of 12 months. They could be real folders or email folders or whatever, depending on what you're filing. In this case, I've implemented a Tickler File for email, designed to run on Unix. You place things that you want to be reminded of or to come back to you later in one of the numbered folders if you want to be reminded in the current month, or the folder for the month you want to be reminded in otherwise.

Each day, you take the current folder's contents and dump them into your inbox. On the first of each month, you dump the entire contents of the new month's folder into your inbox to be reviewed and processed to organize tasks for the month ahead, most likely sorting items back into individual day folders to come back to you on an appropriate day. In this way, your 43 folders represent a rotating loose schedule of things to come over the next 12 months. Some reasons you might do this:

  • Something needs to happen on a certain day, but it's a couple months off. You don't want to think about it now, so you just file it away in that month and you'll be reminded of it at the beginning of the month.
  • Something comes in that isn't an action item, but gives you some ideas for projects you don't have time to deal with now, or you just want to re-read it later. You can file it away for the future, forget about it (like you probably would anyway) and then it will come back to your attention in the future.
  • Among the things I use my physical tickler file for are to make sure bills are paid on time, but to not have to treat them as immediate action items. I'll just drop the bill into my tickler file for 5-7 days before its due. When it comes up, I know I need to pay it now.

The script below is designed to be run through cron once a day. You can run it once with "init" as an argument to set up your 43 folders after configuring the location for your incoming mail folders and where the tickler file folders should reside. Then set up your crontab to run it once a day (without the init argument) to process your file. If something comes into your inbox you want to defer later, just save it to the appropriate day or month's folder and then you don't have to think about it until it comes back to your inbox.

 #!/bin/sh
 # execute in tclsh from path \
 exec tclsh "$0" ${1+"$@"}
 #-----------------------------------------------------------------------------
 #  ticklemail.tcl
 #  A simple script to implement an email "Tickle File"
 #  Written by Michael Kirkham.  Released to public domain.
 #-----------------------------------------------------------------------------
 
 # Configuration - set these as appropriate for the location of your
 # saved mail folders and for your incoming mailbox.
 
 set mailQueueDir   /var/mail
 set savedMailDir   [file join $env(HOME) mail]
 set incomingMail   [file join $mailQueueDir $env(LOGNAME)]
 set tickleDir      [file join $savedMailDir Tickle]
 
 # Run once with "init" as an argument to set up empty folders to be used
 # for your tickle file.  31 folders for days of the month and 12 folders
 # for the months themselves.
 
 if {[lindex $argv 0] == "init"} {
    if {![file exist $tickleDir]} {
        file mkdir $tickleDir
    }   
    for {set day 1} {$day <= 31} {incr day} {
        set folder  [file join $tickleDir $day]
        if {![file exist $folder]} {
            set fh  [open $folder w]
            close $fh
        }   
    }   
    
    foreach month {Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec} {
        set folder  [file join $tickleDir $month]
        if {![file exist $folder]} {
            set fh  [open $folder w]
            close $fh
        }   
    }   
    
    exit
 }  
 
 set movedMessages      ""
 set processedFolders   ""
 
 proc processMessages { folder } {
    set folder [file join $::tickleDir $folder]

    if {[file size $folder]} {
        set fh [open $folder r]
        append ::movedMessages [read $fh]
        close $fh

        # Defer deleting the messages from the old folder
        # until they've been successfully saved to the
        # inbox so they don't get accidentally deleted.

        lappend ::processedFolders $folder
    }
 }

 # Once a day, run the rest of this script through cron to shuffle
 # saved messages from the current day's tickle file to the inbox.

 set now            [clock seconds]
 set 24hrs      [expr {24 * 60 * 60}]
 set today      [string trim [clock format $now -format %e]]
 set month      [clock format $now -format %b]
 set yesterDay  [string trim [clock format [expr {$now - $24hrs}] -format %e]]

 # On the first of the month, dump all the messages for the month
 # into the inbox to be re-processed into appropriate days.

 if {$today == 1} {
    # In case last month had less than 31 days, make sure that
    # the remaining folders that don't correspond to days of
    # that month are also dumped into the inbox, in case messages
    # were accidentally stored in them.

    for {incr yesterDay} {$yesterDay <= 31} {incr yesterDay} {
        processMessages $yesterDay
    }

    processMessages $month
 }

 processMessages $today

 # Save any messages pulled in to the incoming mailbox

 if {[llength $processedFolders]} {
    set fh [open $incomingMail a]
    puts $fh $movedMessages
    close $fh

    # Now clear out the processed folders

    foreach folder $processedFolders {
        set fh [open $folder w]
        close $fh
    }
 }

(MAK) (1 Jan 2005) - Turns out the %e clock format specifier sticks a space in one-digit days which caused errors. Fixed.