An unnecessary AppleScript to convert an OmniFocus task into a project

I hacked this up and then discovered via a tweet from Ken Case of the OmniGroup that it’s completely unnecessary, because you can convert a task into a project in OmniFocus simply by using the outlining outdent shortcut of Command-[. I thought I’d post it anyway, in case anyone finds it to be a useful example of scripting OmniFocus (which I found somewhat hard to get started with) and also because I feel bad about wasting time on writing this thing and publishing it somewhere kind of sort of justifies the effort. 🙂

Using TextExpander to expand a sequence of OmniFocus tasks: A failed experiment

I recently got turned on to TextExpander by the Mac Power Users podcast.

One of my ideas was to use snippets in OmniFocus to create certain repetitive multi-action sequences. For example, when a project involves emailing someone and then waiting for a reply, it would be nice to type a short abbreviation and then enter a fill-in for the name of the person and then have TextExpander create two actions in OmniFocus; one called “Email ” with a context of “Online” followed by another called “Waiting for reply from ” with a context of “Waiting”. I theorized this should be doable because TextExpander lets you insert key presses like Tab and Enter into snippets.

Well, it didn’t work for me as expected. Strangely, it works with the first action; I get the title and context that I want. For the second action, however, I cannot get it to set the context. No matter how many tabs I insert into my snippet expansion, any text that I try to make it put in the context field of the second task seems to go in the title instead. Strange.

Here is the snippet:

If you get it to work or have any insights, please let me know…

My custom searches

I thought others might find a couple of my custom searches and fallback searches for interesting. When I type some text that doesn’t match anything, here’s what I get:

Marc's custom and fallback searches

Marc’s custom and fallback searches

The “Jira search” entry searches my company’s local Jira server. You can add one for yourself by clicking this link and editing the URL in Alfred Preferences | Features | Web & URL | Custom Searches (this is in version 1.3.1).

The “OF Inbox” entry uses an omnifocus:// URL to send the text to your OmniFocus Inbox. Here’s a link to add this to your Alfred config.

OmniFocus extension for PopClip

I just hacked together an OmniFocus extension for PopClip

The extension creates a new task with the selected task in the OmniFocus quick entry window. Just a tiny bit of AppleScript.


Unpack into ~/Library/Application Support/PopClip/Extensions/OmniFocus.popclipext and then open the extension by double-clicking in Finder or using the open command.

PopClip resources


A while back, I mentioned here and here that OmniFocus maintains some kind of cache of your data in a SQLite database.

I just hacked together a quick little prototype Python module for reading OmniFocus data:

Please feel free to fork it and send pull requests! Or file bugs. Or send ideas for improvements.

This could be used as part of a larger solution to pull all the data out of OmniFocus and publish it as some consumable format for the web (e.g.: XML, JSON, HTML, etc.). Or to have an OmniFocus CLI, which is what I’m most interested in.

Accessing OmniFocus data as a sqlite database

While playing with some OmniFocus AppleScripts last night, I realized that OmniFocus on the Mac uses a sqlite database (in addition to the zipped .xml files that it uses for synching). This is pretty interesting, because it could be a very convenient way to write tools that interact with OmniFocus (and use something like Python instead of AppleScript).

$ sqlite3 ~/Library/Caches/com.omnigroup.OmniFocus/OmniFocusDatabase2
SQLite version 3.7.3
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> .mode column                                                                                                                         
sqlite> .headers on
sqlite> SELECT AS task, AS context
   ...> FROM task JOIN context ON task.context = context.persistentIdentifier
   ...> WHERE LIKE '%email%' AND task.dateCompleted IS NULL;
task                                           context   
---------------------------------------------  ----------
Send Amanda new color photo via Cloud website  Email

Pretty cool. With a little Python and SQLAlchemy, I could probably create a nice little Python module for dealing with OmniFocus data.