Using Keyboard Maestro to Create an Always Up to Date Task Calendar from My OmniFocus

OmniFocus 2 had a calendar you could subscribe to, which gave you a calendar view of your tasks. Unfortunately just because of internet connections and syncing times which was always a little flakey (completed tasks would hang around for a while) and didn’t have all of the options I wanted. Unfortunately very few people used this service so it was discontinued in OmniFocus 3 – but I have an alternative!

Someone in the OmniFocus Slack pointed me to this post in the OmniFocus forums to help you create calendar events from your OF database and I got stuck in.

The first thing I decided was that OmniFocus should have its own calendar, this made life much easier later so I highly recommend you do this too. The next step was to decide how long events should be input for if they have no estimated time. The old built in option used an hour which I found too long so I set mine to 30 minutes.

I am using Keyboard Maestro to run this script hourly, but to prevent duplicate events showing up it makes sense to delete the existing events first. There’s no finesse here, if it’s in this calendar it gets deleted – this is where having a dedicated calendar makes life easier, you could write AppleScript to just delete specific calendar events, or even to track which tasks in OmniFocus have been created or edited since the script last ran – but I was aiming for the simplest and fastest solution here.

On to the code itself

property calendar_name : "OmniFocus" -- This is the name of your calendar
property default_duration : 30 --minutes

-- Rosemary Orchard
-- Modified from a script by unlocked2412
-- This creates calendar events for tasks which have a due date, if an estimated time is not set then the task defaults to 30 minutes in length

tell application "Calendar"
   set calendar_element to calendar calendar_name
 tell calendar calendar_name
        set theEvents to every event
       repeat with current_event in theEvents
         delete current_event
       end repeat
 end tell
end tell

tell application "OmniFocus"
  tell default document
      set task_elements to flattened tasks whose ¬
           (completed is false) and (due date ≠ missing value)
        repeat with item_ref in task_elements
         set the_task to contents of item_ref
           set task_name to name of the_task
          set task_note to note of the_task
          set task_due to due date of the_task
           set task_estimate to estimated minutes of the_task
         set task_url to "omnifocus:///task/" & id of the_task
          if task_estimate is missing value then set task_estimate to default_duration
         set end_date to task_due
           set start_date to start_date - (task_estimate * minutes)
           tell application "Calendar"
                tell calendar_element
                  if not (exists (first event whose (start date = start_date) and (summary = task_name))) then
                       make new event with properties ¬
                           {summary:task_name, start date:start_date, end date:end_date, url:task_url} at calendar_element
                    end if
             end tell
           end tell
       end repeat
 end tell
end tell

To summarise: Every incomplete task with a due date is added to the calendar.

  • The name of the task becomes the name of the event.
  • The task note becomes the event note
  • If the task has an estimated duration this is used, otherwise the event is set to whatever the default_duration property is at the top of the list (30 minutes in this example)
  • The due date and the duration of the event are used to calculate the start date
  • The URL of the event is set to be a URL back to the task

Graphical view of the Keyboard Maestro Macro

I don’t use the calendar much myself (preferring Fantastical) so I also have Keyboard Maestro quit the calendar afterwards for me.

This Macro uses the cron timer in Keyboard Maestro to run hourly, I’ve added it to a specific group so it only runs on one of my Macs too. When you download it you will need to enable it, first make sure you create an OmniFocus calendar though, and if you give this calendar a different name then you’ll need to update the Macro too.

This approach has several advantages over the original OmniFocus implementation:

  • I can sync this calendar, and store it in whichever service I like.
  • I can control the default length of events.
  • I could choose to exclude certain events if I wished to.
  • It could be a jumping off point for other scripts – such as a calendar of events you have completed if you wanted one of those.

You could of course use other approaches to run the script automatically, or run it manually when you want to, it’s entirely up to you!

The script can be downloaded here.

31 thoughts on “Using Keyboard Maestro to Create an Always Up to Date Task Calendar from My OmniFocus

I have been using this for a few weeks and I very much like having this functionality, thank you for putting this together!

Unfortunately, I have recently been having trouble with itself. I would love to move this over to Fantastical 2 for Mac.

Is it as simple as switching out “tell Calendar” for “tell Fantastical 2”? I am all about Shortcuts, Keyboard Maestro, and Hazel but I am still intimidated by Apple Script. Thanks for your guidance!

I was able to use this script and find it very useful, but I’ve been trying to figure out how to add the project name with the task name to the calendar event. For example if my project is named “Children’s Book” and a task in this project is “Write outline” I want the calendar event to be “Children’s Book: Write Outline”.

I thought I could create two new variables in the script like this:

set project_name to containing project of the_task
set event_name to project_name & “: ” & task_name

Then I would change the “summary =” and the “summary:” to use the event_name variable.

I think because I’m new to AppleScript I’m having a hard time knowing what to search for on Google or in AppleScript books how to do this.

I can share my script with you if that helps

hey there – great script! Many thanks – one question – I use BUSYCal – so you think you can adapt this script to busy cal? would be so great and I would be ready to support your work
all the best

All the calendars are in you´re icloud it doesn´t matter what calendar app you use

– Even tough the script lunches “calendar” for a short perioud of time and put the Omnifous tasks to the “omnifocus” calendar in the Calendar app
– Then you just refresh Busy cal and all should be there.

But after I upgraded to Catalina this stopped working.. don´t know why

This is excellent, Rosemary. The only problem I see is that also “dropped” tasks with a due date are included in the calendar — is that meant to be so?

I’ve been trying to modify this script, so that only tasks in a certain project are added to the calendar. I don’t know much about AppleScript and I must be doing it wrong . . . . Has anyone else successfully modified this script to do that?

Thanks so much for this script! works well to get tasks into my calendar. FYI to get it to work I did have to change

set start_date to start_date – (task_estimate * minutes)


set start_date to task_due – (task_estimate * minutes)


I’m wondering if you know of any way of getting OF tasks into apple/google calendar without using a Mac though? (Perhaps iOS only?)


PS: I was missing the calendar integration in OF3.
In “GTD” David Allen says that the calendar is THE important tool to getting things done.


  • Lee Garrett
  • Michael Hite
  • Fernando

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.