AppleScript for Pulling Today’s Completed Tasks From Things

A screenshot of an AppleScript editor window titled "Pull Today's Completed Action Items from Things and Create a Day One Entry." The script is designed to retrieve completed tasks from the Things3 app and create a Day One journal entry. The script contains code to set the current date, format it in ISO 8601 format, initialize a list of completed tasks, and fetch tasks from the "Logbook" list. Syntax highlighting shows text in different colors: green for comments, blue for commands, and purple for logic conditions.

Balancing life’s necessary chores with meaningful progress toward our goals can be challenging, especially when greeted by an overflowing task list each morning.

To tackle this, I’ve been exploring ways to not just manage my tasks in Things but also to ensure I’m making real headway on projects that matter. In this post, I’ll show you how an AppleScript is helping me do just that.

Chores vs. Progress

As I explained in a YouTube video, all my tasks (even chores/habits) are in Things. I am just more successful when all of my tasks are in one place.

The downside is that I often wake up with 50 or so tasks in my Today view, and it can be easy to complete a bunch of tasks that are important life maintenance things but make little to no real progress on new projects/work.

So, I have been experimenting with various ideas to reflect on my efforts each day and make sure I am making progress instead of just doing chores.

Clear to Neutral

Since changing careers, this subject is due for a new post, but I have written before about my Clear to Neutral process. This end-of-the-work-day routine helps me create a clean break between the work day and my personal time. It’s also a great opportunity to reflect on the day and plan for the future.

One of the things I do in my current version of clearing to neutral is journaling in Day One. Inspired by the book Triggers by Marshall Goldsmith, I have three prompts that force me to evaluate my accomplishments for the day. My prompts are:

  1. What did I achieve today?
  2. Were these the most important things I could have done today?
  3. How do these completed tasks contribute to my short-term or long-term goals?

I have tried several different prompts over the past six or so months, and these three are my favorite yet, but we will see.

AppleScript vs Shortcut

It turns out that I find it easy to lie to myself, especially if there is an impending deadline for a project I am procrastinating on. I can easily clean the microwave and do a bunch of other chores, so I can tell myself I got a bunch of stuff done today while those deadlines inch closer.

I needed an objective account of the work I do on a day so I can make sure I don’t try to convince myself that a day of checking boxes is the same as doing work.

While I could use the Logbook feature of Things to manually review my day, I found it difficult to look at the logbook and have a clear understanding of what tasks I did that made forward progress on my goals.

So, of course, I looked to an automation.

Chore Tag

To help me differentiate chore-type tasks from tasks that move me toward a goal, I use a “chore” tag to separate out these important but not progress-making tasks. The rest of this post depends on having this chore tag.

Shortcuts

As I have shared in the past, I am pretty mac-centric these days, and Shortcuts is not the first tool I reach for. However, Things has been working hard on its Shortcuts integration, so I started with Shortcuts.

You can see my Shortcut here, but it is incomplete. Or at least I abandoned it before I achieved the result I wanted.

As I said before, I want a list of all the actions I completed today that are not tagged with “chore.” But I would also love to have them grouped by the Area they are in, in Things.

This Shortcut allowed me to break out completed (not canceled) tasks from Things by Area, but if a task was part of a project in an Area, it would not appear in the list.

I am sure someone better with Shortcuts than me could make this work as intended, but I have been having a lot of success with ChatGPT and AppleScript, so I moved on.

AppleScript

After a bunch of trial and error, ChatGPT and I came up with this script, which pulls all of the completed (not canceled) tasks from today, whether or not they are part of a project. Then, it groups the tasks by Area, makes them into a bulleted list, and creates a new “After Work” journal entry in Day One with my prompts and the completed tasks inserted appropriately.

I’m very happy with the result, and I’m excited to share it with you! But first, I want to point out that this requires the Day One Command Line Interface tool to be installed. It was very easy to do, but you will need to complete that process before this script will work.

(*
This AppleScript interacts with Things3 and Day One to create a journal entry in the "Work Journal" using the Day One CLI.
The script pulls all non-chore completed tasks from Things3 for the current day, formats them into a Markdown structure,
and appends them to a predefined after-work journaling template.

The template includes:
- A list of non-chore completed tasks (grouped by area)
- Three questions for reflection: 
  - What did I achieve today?
  - Were these the most important things I could have done today?
  - How do these tasks contribute to my short-term or long-term goals?
*)

tell application "Things3"
    -- Get today's date and set the time to the beginning of the day
    set today to current date
    set time of today to 0

    -- Format the date in ISO 8601 (YYYY-MM-DD) format
    set isoDate to (year of today as string) & "-" & text -2 thru -1 of ("0" & (month of today as integer)) & "-" & text -2 thru -1 of ("0" & (day of today as string))

    -- Initialize a list to store completed tasks
    set completedTasks to {}

    -- Fetch all completed to-dos from the Logbook list that were completed today
    set todaysToDos to to dos of list "Logbook" whose completion date ≥ today and status is completed

    -- Process each of today's completed to-dos
    repeat with toDo in todaysToDos
        -- Get the tags associated with the to-do
        set toDoTags to tag names of toDo

        -- Check if the to-do does not contain "chore" tag
        if toDoTags does not contain "chore" then
            -- Get the name of the to-do
            set toDoName to name of toDo

            -- Determine the area of the to-do, starting with "No Area"
            set toDoArea to "No Area"

            -- Check if the to-do has a project, and if so, check the project's area
            if project of toDo is not missing value then
                set toDoProject to project of toDo
                if area of toDoProject is not missing value then
                    set toDoArea to name of area of toDoProject
                end if
            else if area of toDo is not missing value then
                -- If there's no project, but the to-do has an area, use that area
                set toDoArea to name of area of toDo
            end if

            -- Check if this area already exists in the completedTasks list
            set areaExists to false
            repeat with areaTask in completedTasks
                if item 1 of areaTask is equal to toDoArea then
                    -- If the area exists, add the to-do to this area
                    set areaExists to true
                    set end of (item 2 of areaTask) to toDoName
                end if
            end repeat

            -- If the area does not exist, create a new area entry and add the to-do
            if areaExists is false then
                set end of completedTasks to {toDoArea, {toDoName}}
            end if
        end if
    end repeat

    -- Generate the markdown output
    set markdown to "Here are the non-chore tasks that I completed today:" & return & return

    -- Add the tasks grouped by area to the markdown content
    if (count of completedTasks) > 0 then
        repeat with areaTask in completedTasks
            set areaName to item 1 of areaTask
            set markdown to markdown & "## " & areaName & return & return -- Set header to H2
            repeat with task in item 2 of areaTask
                set markdown to markdown & "- " & task & "  " & return & return -- Add two spaces at the end of each task to force line breaks
            end repeat
            set markdown to markdown & return -- Ensure each section ends with a line break
        end repeat
    else
        set markdown to markdown & "No non-chore tasks completed today." & return
    end if
end tell

-- Create the full content for the Day One entry
set fullEntry to "# After Work Entry" & return & "###### What did I achieve today?" & return & markdown & return & return & "###### Were these the most important things I could have done today?" & return & return & "###### How do these completed tasks contribute to my short-term or long-term goals?"

-- Use the Day One CLI to create a new entry in the "Work Journal"
do shell script "/usr/local/bin/dayone2 new " & quoted form of fullEntry & " --journal='Work Journal'"

AppleScript for a Markdown File

I was having some issues with Day One not properly formatting the markdown text when I copied and pasted it into my After Work entry. After several rounds with the Day One support team, we could not figure out why, which is where the Day One CLI tool came into the picture.

While the Day One CLI ends up working better for me, I wanted to share the version of the script that produces a markdown file on the desktop, too, in case that works better for your workflow.

tell application "Things3"
    -- Get today's date and set the time to the beginning of the day
    set today to current date
    set time of today to 0

    -- Format the date in ISO 8601 (YYYY-MM-DD) format
    set isoDate to (year of today as string) & "-" & text -2 thru -1 of ("0" & (month of today as integer)) & "-" & text -2 thru -1 of ("0" & (day of today as string))

    -- Initialize a list to store completed tasks
    set completedTasks to {}

    -- Fetch all completed to-dos from the Logbook list that were completed today
    set todaysToDos to to dos of list "Logbook" whose completion date ≥ today and status is completed

    -- Process each of today's completed to-dos
    repeat with toDo in todaysToDos
        -- Get the tags associated with the to-do
        set toDoTags to tag names of toDo

        -- Check if the to-do does not contain the "chore" tag
        if toDoTags does not contain "chore" then
            -- Get the name of the to-do
            set toDoName to name of toDo

            -- Determine the area of the to-do, starting with "No Area"
            set toDoArea to "No Area"

            -- Check if the to-do has a project, and if so, check the project's area
            if project of toDo is not missing value then
                set toDoProject to project of toDo
                if area of toDoProject is not missing value then
                    set toDoArea to name of area of toDoProject
                end if
            else if area of toDo is not missing value then
                -- If there's no project, but the to-do has an area, use that area
                set toDoArea to name of area of toDo
            end if

            -- Check if this area already exists in the completedTasks list
            set areaExists to false
            repeat with areaTask in completedTasks
                if item 1 of areaTask is equal to toDoArea then
                    -- If the area exists, add the to-do to this area
                    set areaExists to true
                    set end of (item 2 of areaTask) to toDoName
                end if
            end repeat

            -- If the area does not exist, create a new area entry and add the to-do
            if areaExists is false then
                set end of completedTasks to {toDoArea, {toDoName}}
            end if
        end if
    end repeat

    -- Generate the markdown output
    set markdown to "# Today's Completed Non-Chore Tasks (" & isoDate & ")" & return & return

    -- Add the tasks grouped by area to the markdown content
    if (count of completedTasks) > 0 then
        repeat with areaTask in completedTasks
            set areaName to item 1 of areaTask
            set markdown to markdown & "## " & areaName & return
            repeat with task in item 2 of areaTask
                set markdown to markdown & "- " & task & return
            end repeat
            set markdown to markdown & return
        end repeat
    else
        set markdown to markdown & "No non-chore tasks completed today." & return
    end if
end tell

-- Set the file path to the Desktop with the date at the start and no parentheses
set filePath to (path to desktop as text) & isoDate & " - Today's Completed Tasks.md"

-- Write the markdown content to the file with UTF-8 encoding
try
    -- Open the file for writing; overwrite if it exists
    set fileReference to open for access file filePath with write permission
    -- Clear the file content
    set eof fileReference to 0
    -- Write the markdown data to the file with UTF-8 encoding
    write markdown to fileReference as «class utf8»
    -- Close the file
    close access fileReference
on error errMsg number errNum
    -- If there's an error, try to close the file and print an error message
    try
        close access file filePath
    end try
    display dialog "Failed to create markdown file: " & errMsg buttons {"OK"} default button "OK"
end try

Iterative Improvement of Automations

I am really excited/proud of this result (which is why I am writing this post), but I want everyone who reads this far to know that these huge, complicated scripts always start with a tiny seed of an idea and often expand over time to be what you see in a blog post.

I recently found an amazing new script for working with Things to create a Weekly Review project. My first thought was, “How does someone know how to do this, I could never make something so cool!” While Evan is undoubtedly skilled and intelligent, I wanted to take a second to let you, the reader, know that you should start pulling on the digital threads in your life that seem interesting, you never know what you will create in the end. Also, ChatGPT is awesome for helping with these types of projects!

Closure

I think this process of reflecting on my day and purposefully thinking about how I am spending my time has been beneficial. Sometimes, I notice that the day was full of deceptive productivity, and I spent most of my time in maintenance mode. Other days, this practice has highlighted achievements that slipped by because I was on a roll, and things felt effortless.

Both forms of reminder are helpful for learning more about my brain and getting better at managing it.

0 replies

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.