Logging the OmniFocus Tasks You Did Today

Use TextExpander to Summarize Your Accomplishments

by Colter Reed
2:07 read (647 words)
by Colter Reed
2:07 read (647 words)

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.

July Budget (3 remaining)
 ✔ Balance checkbook
 ✔ Cover overdrawn envelopes

Pay July Rent (completed)
 ✔ Write out check for July 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.

// 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";
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 = [];
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] = [];
return dict;
function startOfDay() {
// The day started at midnight this morning
var d = new Date();
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.