It’s important to write down everything you need to do. You won’t forget anything, you free your mind to think about other things, and you get to cross things off a list.
There’s something about crossing things off a list that’s very satisfying. It stimulates the reward centers of your brain, releasing a little dopamine for a job well done. You can see your progress as you progress through the day.
When you complete a task in OmniFocus, it might stay visible until the current view refreshes. Then it disappears. For a while, you can adjust the view settings or check a custom perspective (if you have OmniFocus Pro) to see what you’ve done, but eventually, the tasks will be gone for good.
This is good for focus (hide completed tasks so you only see what you still need to do) but it’s bad for tracking what you’ve done. Here’s a TextExpander macro that will help you keep a more permanent record of your accomplishments in an appropriate place.
The following script will build a list of all the tasks you’ve completed today, grouped by project.
Role — Family ✔ Have wedding rings cleaned ✔ Build a toy box camera Sharpen the Saw ✔ Read for 30 minutes
If a project will be automatically completed when all of its tasks are completed, the number of remaining tasks is included after the project.
January Budget (3 remaining) ✔ Balance checkbook ✔ Cover overdrawn envelopes Pay January Rent (completed) ✔ Write out check for January rent ✔ Drop off rent check
I have this script assigned to the TextExpander macro .ctasks (short for completed tasks). Create a new script, change the content to JavaScript, and paste the following code.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Build a summary of OmniFocus tasks completed today. | |
// | |
// This is intended to be run as a TextExpander macro, | |
// but will work anywhere you can invoke a JS script. | |
// | |
// v 1.0.2 (full release history at bottom) | |
var NoProjectMarker = "No Project"; | |
getTaskSummary(); | |
function getTaskSummary() { | |
var doc = Application('OmniFocus').defaultDocument; | |
var thisMorning = startOfDay(); | |
var tasks = doc.flattenedTasks.whose({completionDate: {'>=':thisMorning} })(); | |
if (tasks.length == 0) { | |
return "No tasks completed. Do something without writing it down?"; | |
} | |
// Group tasks by project, then extract progressed projects (projects with | |
// completed tasks) from allProjects. This gives us the list of projects | |
// in the same order as OmniFocus’s UI. | |
var groupedTasks = groupArrayByKey(tasks, function(v) { | |
var proj = v.containingProject(); | |
if (proj) { | |
return proj.id(); | |
} | |
return NoProjectMarker; | |
}); | |
var allProjects = doc.flattenedProjects(); | |
var progressedProjects = allProjects.filter(function(p) { | |
return p.id() in groupedTasks; | |
}); | |
// Build the summary | |
var summary = progressedProjects.reduce(function(s,p){ | |
return s + summaryForProject(p); | |
}, ""); | |
var tasksWithNoProject = groupedTasks[NoProjectMarker]; | |
if (tasksWithNoProject) { | |
summary += summaryForTasksWithTitle(tasksWithNoProject, "No Project\n"); | |
} | |
return summary; | |
// This needs to be in this scope because it captures groupedTasks | |
function summaryForProject(p) { | |
var projectID = p.id(); | |
var tasks = groupedTasks[projectID].filter(function(t) { | |
return projectID != t.id(); // Don't include the project itself | |
}); | |
return summaryForTasksWithTitle(tasks, projectSummaryLine(p)); | |
} | |
function summaryForTasksWithTitle(tasks, title) { | |
return title + tasks.reduce(summaryForTasks,"") + "\n"; | |
} | |
} | |
// Reducing function to summarize a list of tasks | |
function summaryForTasks(s,t) { | |
return s + lineForTask(t); | |
} | |
// Create a summary line for a project | |
function projectSummaryLine(project) { | |
var tokens = []; | |
tokens.push(project.name()); | |
var remainingStatus = remainingStatusForProject(project); | |
if (remainingStatus != "") { | |
tokens.push("(" + remainingStatus + ")"); | |
} | |
return tokens.join(" ") + "\n"; | |
} | |
// This is appended to the end of a project line | |
function remainingStatusForProject(project) { | |
if (!project.completedByChildren()) { | |
return ""; | |
} | |
var remainingCount = project.numberOfTasks() – project.numberOfCompletedTasks(); | |
if (remainingCount == 0) { | |
return "complete"; | |
} | |
return remainingCount + " remaining"; | |
} | |
function lineForTask(task) { | |
return " ✓ " + task.name() + "\n"; | |
} | |
// Group an array of items by the key returned by this function | |
function groupArrayByKey(array,keyForValue) { | |
var dict = {}; | |
for (var i = 0; i < array.length; i++) { | |
var value = array[i]; | |
var key = keyForValue(value); | |
if (!(key in dict)) { | |
dict[key] = []; | |
} | |
dict[key].push(value); | |
} | |
return dict; | |
} | |
function startOfDay() { | |
// The day started at midnight this morning | |
var d = new Date(); | |
d.setHours(0); | |
d.setMinutes(0); | |
d.setSeconds(0); | |
return d; | |
} | |
// Release History | |
// 1.0 Initial release | |
// 1.0.1 Fix for tasks without a project | |
// 1.0.2 Relaxed the type checking (!== is too strict) |
Now, anywhere you’re typing, you’re just a few keystrokes away from a complete list of everything you did today.
- Conclude your daily planner page in Evernote with everything you got done.
- Create an end-of-day journal entry in DayOne.
- Send a status update to coworkers who might be interested in what you got done.
- Record what you did in a work log.
Tracking what you need to do is essential for short-term productivity. Tracking what you’ve done is key to long-term growth.
Question: What do you learn from tracking what you’ve done? Share your thoughts in the comments, on Twitter, LinkedIn, or Facebook.