OmniFocus: The Big Picture

OmniFocus is an organizational tool for managing your time and efforts. It provides personalized access and customizable views into its central database that stores and organizes your data using the containers and descriptors: projects, folders, tasks, and tags.

Using its integrated Omni Automation support, you can streamline and automate OmniFocus procedures, and transfer and receive data to and from other applications like the project management application OmniPlan.

This page is designed to provide you a quick overview of the structure of the built-in Omni Automation support in OmniFocus.

“Action” or “Task”

When interacting with the OmniFocus application’s user-interface (UI for short), you will encounter the term “Action” which refers to a new to-do item for a project. However, in the OmniPlan application, such a time-related element is called a “Task.”

The Omni Automation support in OmniFocus considers the terms “action” and “task” to be functionally synonymous, and refers to the scriptable element representing an “action” as a “task.”

In other words: a “task” is a something that needs doing, and “action” is the element in the OmniFocus interface that represents that need or to-do item. Scripts reference tasks, and the graphical user-interface of OmniFocus references actions. In the following documentation, consider tasks to be equivalent to actions.

The Big Picture

Here is a visual overview of the scripting relationships in OmniFocus. Note that certain intermediate database classes used in the scripting application interface (API) do not appear in this illustration, but instead are described in detail in the OmniFocus Omni Automation documentation.

OmniFocus-Hierarchy

From a scripting perpective, here are some concepts to keep in mind:

Application

The heart of OmniFocus is its database. Most of your scripts will target the database and the objects and data it contains. The Application class is generally only addressed by scripts in order to determine the operating system environment, pressed modifier keys, and for opening archived documents.

In Omni Automation script statements, the Application object is represented by the abbreviation: “app”

app.openDocument( document, fileURL, function(doc,wasOpen){ doc.windows[0].perspective = Perspective.BuiltIn.Projects db = doc.windows[0].selection.database db.projects.forEach((project)=>{ // processing goes here }) } )

Documents

Although documents are a top-level element of the OmniFocus application, the database, not the document, is the repository of the data. Typically, scripts reference the Document class to manage the data view and selection. In scripts, the current document is not referenced by appending the Application object, but is referenced instead as a top-level object, using the term: document

Document

For the sake of security, documents are not allowed to be accessed by scripts run in the consoles of other documents, so the application object will not return references to other documents.

Document Windows

In the OmniFocus scripting implementation, windows belong to documents, and their hierarchical reference chains include their parent document object:

Document > Window

And the current window is always the first item in the list (array) of open windows:

Perspective

A Perspective is a view into your OmniFocus database that appears in the perspective list (left-side of window) and whose contents are detailed in the outline (right-side of window).

OmniFocus comes with built-in perspectives: Flagged, Forecast, Inbox, Nearby, Projects, Review, and Tags; and two transient reference perspectives: Completed and Changed. Custom perspectives can be created in OmniFocus Pro.

Document > Window > Perspective

// Get the name of the current perspective document.windows[0].perspective.name //--> "Projects" // Change window view to show Inbox perspective document.windows[0].perspective = Perspective.BuiltIn.Inbox //--> [object Perspective.BuiltIn: Inbox] // Change window view to show Projects perspective document.windows[0].perspective = Perspective.BuiltIn.Projects //--> [object Perspective.BuiltIn: Projects]

Document Selection

A document’s selection object belongs to the Window class, which in turn, belongs to the parent implied document. The Selection class includes properties whose values are arrays of references to the specified object types selected in the window: projects, folders, tags, and tasks

Document > Window > Selection

document.windows[0].selection.database //--> [] document.windows[0].selection.folders //--> [] document.windows[0].selection.projects //--> [] document.windows[0].selection.tags //--> [] document.windows[0].selection.tasks //--> [] document.windows[0].selection.window //--> []

For example, here’s a simple script for getting the titles of the selected tasks:

selectedTasks = document.windows[0].selection.tasks taskTitles = selectedTasks.map((task)=>{return task.name})

Database

At the core of OmniFocus is a database that is used for the display and management of time-related data and schedules. To accomplish such data organization, OmniFocus relies on a variety of container components to segment the data and information, and to enable the creation of relationships between the various elements.

Folders, Projects, Tasks, and Tags are some of the scriptable database objects used as container for storing data and information. To provide scripting access to these database objects, the Omni Automation API for the central database includes the following properties whose values are references to the current set of related container types.

When using these properties in a script, remember that the Database is the topmost implied scripting object, which may be represented by the “this” enumeration. Therefore, database properties can be called simply entering them in a script statement.

For example, here is a script for iterating the current set of top-level Tasks in the InBox perpective.

inbox.forEach((task)=>{ if (task.taskStatus === Task.Status.Available){ // processing statements go here } })

To iterate all tasks in the Inbox hierarchy — even those tasks within other tasks — use the apply(…) function:

inbox.apply((task)=>{ if (task.taskStatus === Task.Status.Available){ // processing statements go here } })

NOTE: the apply(…) method can be called on the properties of the Database class whose value is a hierarchical collection: library, projects, folders, inbox, tags

tagNames = new Array() tags.apply((tag)=>{ if(!tagNames.includes(tag.name)){tagNames.push(tag.name)} }) console.log(tagNames)
omnifocus://localhost/omnijs-run?script=try%7BtagNames%20%3D%20new%20Array%28%29%0Atags%2Eapply%28%28tag%29%3D%3E%7B%0A%09if%28%21tagNames%2Eincludes%28tag%2Ename%29%29%7BtagNames%2Epush%28tag%2Ename%29%7D%0A%7D%29%0Aconsole%2Elog%28tagNames%29%7Dcatch%28err%29%7Bconsole%2Elog%28err%29%7D

For more information regarding the use of the apply(…) function, see the section on Finding Items.

Locating Database Items by Name

To make it possible to locate a specific top-level database element, such as a folder, project, task, or tag, identified by name, the Database class offers the following functions:

Here is a script example that returns a reference to a top-level tag specified by name. If the tag does not already exist, it is created.

tag = tagNamed("Kitchen") || new Tag("Kitchen")
omnifocus://localhost/omnijs-run?script=try%7Btag%20%3D%20tagNamed%28%22Kitchen%22%29%20%7C%7C%20new%20Tag%28%22Kitchen%22%29%7Dcatch%28err%29%7Bconsole%2Elog%28err%29%7D

This technique can be used with any of the top-level database elements: folders, projects, tags, and tasks.

By default, database elements created using the new item constructor are inserted at the end of the list of elements. Here’s a variation of the previous script that uses a positional indicator to insert a new top-level element (if it doesn’t already exist) at the beginning of the container of elements. The result is a reference to the either the existing element or the newly created element:

taskName = "Clear Footings" task = taskNamed(taskName) || new Task(taskName, inbox.beginning)
omnifocus://localhost/omnijs-run?script=try%7BtaskName%20%3D%20%22Clear%20Footings%22%0Atask%20%3D%20taskNamed%28taskName%29%20%7C%7C%20new%20Task%28taskName%2C%20inbox%2Ebeginning%29%7Dcatch%28err%29%7Bconsole%2Elog%28err%29%7D

Other Database Functions

In OmniFocus, many of the functions that are normally applied to documents, such as performing a save, are instead done by the database, along with other commands for organizing, moving, duplicating, and deleting database elements.

For example, here is a script that uses positional properties of the Inbox Array class to add new Task instances to the beginning and end of the InBox, and saving the current state of the database.

new Task("New First Task", inbox.beginning) new Task("New Last Task", inbox.ending) this.save()
omnifocus://localhost/omnijs-run?script=try%7Bnew%20Task%28%22New%20First%20Task%22%2C%20inbox%2Ebeginning%29%0Anew%20Task%28%22New%20Last%20Task%22%2C%20inbox%2Eending%29%0Athis%2Esave%28%29%7Dcatch%28err%29%7Bconsole%2Elog%28err%29%7D

Here’s a script that uses the deleteObject() method remove all items from the InBox:

inbox.forEach(tsk => deleteObject(tsk))
omnifocus://localhost/omnijs-run?script=try%7Binbox%2EforEach%28%28tsk%29%20%3D%3E%20%7BdeleteObject%28tsk%29%7D%29%7Dcatch%28err%29%7Bconsole%2Elog%28err%29%7D

Other OmniFocus Items

Specific descriptions and examples for the database container objects and other OmniFocus scripting topics can be accessed in the navigation list on the right side of this page.

tagNames = tags.map((tag)=>{return tag.name})
tags.forEach((tag)=>{ console.log(tag.name) console.log(tag.children) if(tag.children){ tag.children.map((tg)=>{return tg.name}) } })
UNDER CONSTRUCTION

This webpage is in the process of being developed. Any content may change and may not be accurate or complete at this time.

DISCLAIMER