×

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 point-of-view, 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

Determine the Current Platform


app.platformName //--> macOS or iOS
Open Document and Iterate Projects


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

Get Document Name


document.name //--> "OmniFocus"

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.

Reference Other Documents


//--> these are not supported app.documents.length app.documents[0]

Document Windows

In the OmniFocus scripting implementation, the Window class is an element of the Document class, and so references to windows include their parent document object:

Document Windows


document.windows.length

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

Current Window


document.windows[0]

Perspective

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

OmniFocus comes with these 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.

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 custom perspective document.windows[0].perspective = Perspective.Custom.byName("Fairfield") //--> [object Perspective.Custom: Fairfield]

Document Selection

A document’s selection is a property of 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, tasks and others listed in the script example below.

Properties of the Selection Object
 

document.windows[0].selection.database //--> [object Database] document.windows[0].selection.folders //--> [array of folder references] document.windows[0].selection.projects //--> [array of project references] document.windows[0].selection.tags //--> [array of tag references] document.windows[0].selection.tasks //--> [array of task references] document.windows[0].selection.window //--> [object DocumentWindow] document.windows[0].selection.allObjects //--> [array of instances of all objects in the selection, if any] document.windows[0].selection.databaseObjects //--> [array of all DatabaseObject objects in the selection, if any.] document.windows[0].selection.document //--> [object DatabaseDocument]

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

Titles of Selected Tasks


var 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 (Application Programming Interface) 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 without any preceding hierarchy.

For example, here is a script for iterating the current set of top-level Tasks in the InBox Perpective, represented by the database property: inbox

Iterate Top-Level Tasks


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:

Iterate All Tasks in Inbox Heiratchy


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

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
Get Names of All Tags
 

var tagNames = new Array() tags.apply((tag)=>{ if(!tagNames.includes(tag.name)){tagNames.push(tag.name)} }) console.log(tagNames)

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

For your convenience, “flattened” versions of object hierarchies are available for easily parsing and processing database elements: flattenedTags, flattenedTasks, flattenedFolders, flattenedProjects, flattenedSections

The “flattened” properties return object hierarchies “flattened” into array of specific object type references, sorted by their order in the database. Use these database when it is necessary to process all of the existing instances of a particular class, such as Tasks:

Every Task Whose Title Begins with “Red”


//--> reference every task whose name begins with the word "Red" var str = "Red " var result = flattenedTasks.filter(task => task.name.startsWith(str))

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.

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
Reference to Tag Specified by Name
 

tag = tagNamed("Kitchen") || new Tag("Kitchen")

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

TIP: To scan the entire hierarchy of a class for the first item matching by name, execute the byName() function on the corresponding “flattened” property, such as in this example script that will return a reference to the first task whose name matches the provided value, creating a new task if required:

Reference to Task Specified by Name


task = flattenedTasks.byName("Build Shed") || new Task("Build Shed")

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:

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
Insert Task at Beginning of Inbox
 

taskName = "Clear Footings" task = taskNamed(taskName) || new Task(taskName, inbox.beginning)

Built-In Search Functions

The Database class provides three generalized search functions for locating folders, projects, and tags that “smart match” the indicated string.

Find Matching Tags


tagsMatching("Auto-") //--> [[object Tag: Auto-Open], [object Tag: Auto-Close], [object Tag: Auto-Update]]

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.

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
Create Tasks and Save
 

new Task("New First Task", inbox.beginning) new Task("New Last Task", inbox.ending) this.save()

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

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
Clear InBox
 

inbox.forEach(tsk => deleteObject(tsk))

Other OmniFocus Items

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