Automation in OmniFocus 2.14
OmniFocus 2.14 improves automation by adding support for two-way communication with other iOS apps.
In iOS, the primary way that apps talk to each other is through URLs. These are much like the URLs you enter into a web browser (in fact, you can enter these exact URLs into a web browser if you wish) and provide a mechanism for an app to transmit information to another app.
OmniFocus included support for automation through URLs on the day the App Store first launched, back in 2008. Back then, URLs were considered one-way mechanisms: one app could send something to another app, but that was it: the original iPhone would only run one app at a time, so the starting app was gone and would never hear anything back. But even that much was quite useful: for example, you could add a Safari bookmark which would send the current web page to OmniFocus. And many apps have taken advantage of this primitive mechanism from 2008 to send a new task to OmniFocus or to ask OmniFocus to show a particular item or perspective.
Well, how time flies! Fast forward eight years. Since 2008, the device hardware and the iOS operating system have both evolved significantly, and on most devices itās now possible to have multiple apps running at the same time (one in the background)āand on some devices, you can even have two apps simultaneously running side-by-side.
And over those eight years, the app ecosystem has evolved as well. Many appsālike Workflow, Editorial, Drafts, 1Writer, and Ulyssesānow support two-way communication by through the use of ācallbackā URLs, as proposed at x-callback-url.com. Using those apps you can build automation workflows that no longer stop the moment you transfer control to another app: when that app finishes its work, it uses a different URL to ācall backā to the next step in the workflow.
With OmniFocus 2.14, Iām very pleased to be able to say that OmniFocus now includes best-of-class support for callback URLs. At its simplest, this means that you can create a workflow that adds more than one item to OmniFocus. But we didnāt just add support for two-way communication between OmniFocus and other apps, we added support for doing for automating a whole lot more of the powerful capabilities of OmniFocus.
This means, for example, that you can now create a text file outlining an entire project, with placeholders for specific names, defer dates, due dates, and so on. You can then run a workflow that processes those placeholders and builds a new project (such as āRun a marathon on June 30ā) from that project template, and these project templates and their processing workflows can be shared with others.
But thatās just one possible workflow which is enabled by automation. You can also use the time estimates and dates already entered into OmniFocus to schedule tasks on a calendar. Or you could build a workflow which publishes the status of all the tasks in a project. Weāve just barely begun to explore the possibilities!
So thatās what this release is about.
Implementation Details
What follows is a description of the app-to-app interface that can now be used by other apps when talking to OmniFocus. The target audience for this is app developers, who need to see exactly what to do to get their app talking to OmniFocus.
URL Actions
OmniFocus URLs take the form omnifocus:///action?parameter=value&ā¦
. Parameter values should be URL-escaped. For two-way communication between apps, OmniFocus uses the protocol described by x-callback-url.com. The quick summary is that each command accepts optional query parameters x-success
, x-cancel
, and x-error
; their values indicate how OmniFocus should continue the current automation workflow.
Here are the supported URL actions:
Data Entry
-
/add?name=name&ā¦ - creates a single task
- name=string - the name of the new task
- note=string - its note
- estimate=time span - time estimate, e.g.
2h
for 2 hours or3w
for 3 weeks. - flag=bool - whether the item is flagged (
true
orfalse
) - parallel=bool - whether children are parallel (
true
) or sequential (false
) - autocomplete=bool - whether the item automatically completes itself when its children are complete
- defer=date - defer until date, e.g.
2016-04-19 5pm
ornext Thursday -3d
- due=date - due on date
- completed=date - completed on date
- repeat-method=method - the repeat method:
fixed
,start-after-completion
, ordue-after-completion
- repeat-rule=rule - an ICS repeat rule (see RFC2445), e.g.
FREQ=WEEKLY;INTERVAL=1
- project=string - the project to assign
- context=string - the context to assign
- attachment-name=string - attachment file name, repeated as necessary for multiple attachments
- attachment=attachment-data - base-64 encoded file content, repeated as necessary
- reveal-new-item=bool - whether to navigate to the newly created item (
true
orfalse
)
Callback: on success, the
result
query parameter will contain a URL that can be used to navigate to that task (e.g.omnifocus:///task/abc123
), while theparent
query parameter will contain the URL for the assigned parent project (if any). -
/paste - pastes a hierarchy of items into the Inbox or project list
- target=target - use
inbox
to create new inbox items, orprojects
to create top-level projects - index=number - where the new item should appear in the list:
1
(top) to n or-1
(bottom) to -n - content=TaskPaper string - the content to paste, in TaskPaper format (if unspecified, will read text from the pasteboard)
Callback: on success, the
result
query parameter will contain a URL that can be used to navigate to that task (e.g.omnifocus:///task/abc123
). - target=target - use
Navigation
- /home - navigates to the top level of the app
- /inbox - navigates to Inbox
- /projects - navigates to Projects
- /contexts - navigates to Contexts
- /nearby - navigates to Nearby
- /forecast - navigates to Forecast
- /flagged - navigates to Flagged
- /review - navigates to Review
- /search?q=string - opens the search view
- /context/context-id - navigates to a context
- /folder/folder-id - navigates to a folder
- /perspective/perspective-id - navigates to a custom perspective
- /task/task-id - navigates to a project or action
General
- /app-info - returns information about the current OmniFocus version
- /parse-date?input=string - parses a date (e.g.
next thu 5pm
, or7/1 -90d
) based on current locale settings
Sharing
While viewing a task or project, you can use the Share button to send that task to another app.
Several representations of the task are included on the pasteboard:
-
TaskPaper text - TaskPaper text is the most human-readable representation of a task, suitable for copying into any text editor. See below for details.
-
Navigation URL - A simple navigation URL will be placed on the pasteboard.
-
Reference URL - A long navigation URL with a fully populated set of parameters (just like the /add URL action). This URL does not include attachments at the moment; if those attachments would be useful to you, please let us know!
TaskPaper Format
TaskPaper text is a simple but flexible format for representing tasks as text. It can be edited with any text editor. Quoting from the TaskPaper Users Guide:
TaskPaperās file format is fairly simple. Hereās how TaskPaper reads a file:
Files are expected to use the UTF-8 encoding and use ā\nā to separate lines.
A task is a line that begins with a hyphen followed by a space ('- ') which can optionally be prefixed (i.e indented) with tabs or spaces. A task can have zero or more tags anywhere on the line (not just trailing at the end).
A project is a line that isnāt a task and ends with a colon (ā:ā), or a colon (ā:\nā) followed by a newline. Tags can exist after the colon, but if any non-tag text is present, then it wonāt be recognized as a project.
A note is any line that doesnāt match the task or project rules.
Indentation level (with tabs, not spaces) defines ownership. For instance, if you indent one task under another task, then it is considered a subtask. Tasks and notes own all objects that are indented underneath them. Empty lines are ignored when calculating ownership.
A tag has the form ā@tagā, i.e. it starts with an āatā character (ā@ā), followed by a run of non-whitespace characters. A tag can optionally have a value assigned to it. The value syntax immediately follows the tag word (no whitespace between) and is enclosed by parentheses: ā(ā and ā)ā. The value text inside can have whitespace, but no newlines. Here is an example of a tag with a value: @tag(tagās value)
As you can see, one issue with this format is that TaskPaper doesnāt have any mechanism for escaping arbitrary content, so this representation can be lossy. For example, a task name that includes the text @flagged
will see that text disappear from its name and the task will end up being flagged. And you canāt begin a note with a -
. (To prevent mishap, on export we substitute any leading -
characters in notes with en-dash ā
characters.)
In general, OmniFocus tries to use the same names for tags that it uses for parameters in the /add URL action, with a few modifications (like @done
) to match the way other apps interpret TaskPaper content.
OmniFocus currently supports the following tags:
- @estimate(time span) - time estimate, e.g.
2h
for 2 hours or3w
for 3 weeks. - @flagged - present when an item is flagged
- @parallel(bool) - whether children are parallel (
true
) or sequential (false
) - @autodone(bool) - whether the item automatically completes itself when its children are complete (named to match @done)
- @defer(date) - defer until date, e.g.
2016-04-19 5pm
ornext Thursday -3d
- @due(date) - due on date
- @done(date) - completed on date
- @repeat-method(method) - the repeat method:
fixed
,start-after-completion
, ordue-after-completion
- @repeat-rule(rule) - an ICS repeat rule (see RFC2445), e.g.
FREQ=WEEKLY;INTERVAL=1
- @context(string) - the context to assign
If youāve read this far, I hope youāve gained a clearer understanding of how all of this works. If anything was confusing or left you with unanswered questions, please donāt hesitate to contact us!