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.

(*
Things3 to Day One Work Journal Integration
Version: 2.0
Created by: Mike Burke (https://www.themikeburke.com) and Claude (Anthropic)
Last Updated: 2025-02-02

License: MIT
Copyright (c) 2025 Mike Burke
Permission is hereby granted to use, copy, modify, and share this script freely,
provided the above copyright and attribution notices are preserved.
Full license text: https://opensource.org/licenses/MIT

Description:
This AppleScript automates the creation of daily work journal entries by pulling completed tasks from Things3 and creating a structured entry in Day One. It filters out specified routine tasks and organizes the remaining tasks by their respective areas, providing a clean daily work log with customizable prompts for reflection on achievements and energy management.

Functionality:
1. Retrieves and processes completed tasks from Things3
2. For each task completed today, it:
   a. Extracts the task name and organizational context (area/project)
   b. Groups tasks by their associated area
   c. Preserves and transfers:
      - Task names
      - Area/Project hierarchies
      - Completion status
   d. Filters out tasks with specified tags (default: "chore")
   e. Handles multiple scenarios:
      - Tasks within projects: Uses the project's area
      - Standalone tasks with areas: Uses the task's direct area
      - Tasks without areas: Groups under "No Area"
   f. Generates a formatted Markdown entry with:
      - Task listings grouped by area
      - Customizable reflection prompts
      - Consistent Markdown formatting for Day One

Usage:
1. Install and configure the Day One CLI:
   - Default installation path is /usr/local/bin/dayone2
   - Verify your installation path and update the script if needed
2. Customize the script (optional):
   - Modify the filter tag ("chore") to match your Things3 organization
   - Adjust the entry title ("After Work Entry")
   - Customize reflection questions to match your journaling practice
3. Ensure Things3 is running and contains completed tasks
4. Run the script after your workday to generate a structured journal entry

Note: 
- Requires Things3, Day One (with CLI installed), and macOS
- Tasks must be completed on the current day to be included
- The script assumes a "Work Journal" exists in Day One
- Customization points are clearly marked in the script with comments
- Default filtering uses a "chore" tag, but this can be modified to match 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
		
		-- CUSTOMIZATION POINT: Task Filtering
		-- Modify the tag name "chore" below to match your Things3 tag for tasks you want to exclude
		-- Remove this condition entirely if you want to include all tasks
		if toDoTags does not contain "chore" then
			-- Get the name of the to-do
			set toDoName to name of toDo
			
			-- CUSTOMIZATION POINT: Default Area Name
			-- Change "No Area" below if you prefer a different label for unorganized tasks
			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
	
	-- CUSTOMIZATION POINT: Entry Introduction
	-- Modify the introduction text below to match your preferred entry style
	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
			-- CUSTOMIZATION POINT: Header Level
			-- Modify the "##" below if you prefer a different header level for areas
			set markdown to markdown & "## " & areaName & return & return
			repeat with task in item 2 of areaTask
				set markdown to markdown & "- " & task & "  " & return & return
			end repeat
			set markdown to markdown & return
		end repeat
	else
		-- CUSTOMIZATION POINT: Empty Day Message
		-- Modify this message for days with no completed tasks
		set markdown to markdown & "No non-chore tasks completed today." & return
	end if
end tell

-- CUSTOMIZATION POINT: Entry Structure
-- Modify the entry title and reflection questions below to match your journaling practice
set fullEntry to "# After Work Entry" & return & "###### What did I achieve today?" & return & markdown & return & return & "###### What energized or depleted me today?" & return & return & "###### How can I best use my remaining energy today?"

-- CUSTOMIZATION POINT: Day One Configuration
-- Verify that the Day One CLI path matches your installation
-- Update the journal name if you use a different journal for work entries
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.

(*
Things3 to Desktop Markdown Export
Version: 2.0
Created by: Mike Burke (https://www.themikeburke.com) and Claude (Anthropic)
Last Updated: 2025-02-02

License: MIT
Copyright (c) 2025 Mike Burke
Permission is hereby granted to use, copy, modify, and share this script freely,
provided the above copyright and attribution notices are preserved.
Full license text: https://opensource.org/licenses/MIT

Description:
This AppleScript exports completed tasks from Things3 to a dated Markdown file on your desktop. It filters out routine chores and organizes tasks by their respective areas, creating a clean daily log that can be used with any Markdown-compatible system or note-taking application.

Functionality:
1. Retrieves and processes completed tasks from Things3
2. For each non-chore task completed today, it:
   a. Extracts the task name and organizational context (area/project)
   b. Groups tasks by their associated area
   c. Preserves and transfers:
      - Task names
      - Area/Project hierarchies
      - Completion status
   d. Filters out tasks with the "chore" tag
   e. Handles multiple scenarios:
      - Tasks within projects: Uses the project's area
      - Standalone tasks with areas: Uses the task's direct area
      - Tasks without areas: Groups under "No Area"
   f. Creates a formatted Markdown file with:
      - ISO 8601 dated filename (YYYY-MM-DD - Today's Completed Tasks.md)
      - Tasks grouped by area with consistent header hierarchy
      - UTF-8 encoding for universal compatibility

Usage:
1. Ensure Things3 is running and contains completed tasks
2. Run the script after your workday
3. Find the generated Markdown file on your desktop:
   - Filename format: "YYYY-MM-DD - Today's Completed Tasks.md"
   - Contains a hierarchical list of completed non-chore tasks
   - Organized by area with Markdown formatting

Note: 
- Requires Things3 and macOS
- Tasks must be completed on the current day to be included
- Writes to desktop with UTF-8 encoding for maximum compatibility
- Will overwrite existing file with same name if present
- Default filtering uses a "chore" tag, but this can be modified to match your workflow
*)

(*
[Previous documentation header would go here]
*)

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 for filename
	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
		
		-- CUSTOMIZATION POINT: Task Filtering
		-- Modify the tag name "chore" below to match your Things3 tag for tasks you want to exclude
		-- Remove this condition entirely if you want to include all tasks
		if toDoTags does not contain "chore" then
			-- Get the name of the to-do
			set toDoName to name of toDo
			
			-- CUSTOMIZATION POINT: Default Area Name
			-- Change "No Area" below if you prefer a different label for unorganized tasks
			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
	
	-- CUSTOMIZATION POINT: File Header
	-- Modify the title format below to match your preferred document style
	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
			-- CUSTOMIZATION POINT: Header Level
			-- Modify the "##" below if you prefer a different header level for areas
			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
		-- CUSTOMIZATION POINT: Empty Day Message
		-- Modify this message for days with no completed tasks
		set markdown to markdown & "No non-chore tasks completed today." & return
	end if
end tell

-- CUSTOMIZATION POINT: File Naming
-- Modify the file name format below to match your preferred naming convention
set filePath to (path to desktop as text) & isoDate & " - Today's Completed Tasks.md"

-- Error handling for file operations
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.