2025-10-28 09:30:15
The following article is predominantly a record for my future self. The solution as described was imagined and thought through by me, but development was helped by ChatGPT because I don’t have the necessary coding skills. As it took a long time with multiple iterations, I asked ChatGPT to summarise and document the flow of my attempts.
As such, the majority of this article is AI-generated, but proofread and edited by me, a human.
For years, I’ve kept OmniFocus as my single source of truth for tasks. Every commitment lives there — work projects, household jobs, even odd ideas that might grow into something.
But my work notes live in Obsidian. That’s where meeting records, brainstorms, and running logs of ideas go. The two systems complement each other perfectly — except when they don’t talk.
I wanted a way to extract the tasks I jot into Obsidian (- [ ] Do the thing) and have them appear automatically in my OmniFocus inbox. No manual copy-and-paste. No Quick Entry window. No duplicative reliance on the Tasks plugin for Obsidian. Just seamless capture.
In short, bridge the gap between where ideas start (Obsidian) and where they’re managed (OmniFocus).
I thought this would be quick and easy. It definitely wasn’t quick.
OmniFocus supports AppleScript. The theory was to have a script read tasks from the note, feed them to OmniFocus, and be done.
It didn’t go well.
AppleScript threw up errors like:
“Expected end of line but found plural class name.”
Keyboard Maestro tried to help, but AppleScript didn’t behave the same when triggered from automation tools. Even when it ran, nothing actually appeared in the Inbox. After several dead ends, I concluded AppleScript might be powerful — but it’s also brittle, opaque, and slow to debug.
That led me to OmniFocus’s x-callback-url API. This allows new tasks to be created via a simple URL such as:
omnifocus://x-callback-url/add?name=Test¬e=Hello&autosave=true
The autosave=true parameter was the key. It bypasses Quick Entry completely and saves the task directly into the Inbox.
That was exactly what I wanted: a silent, background handoff.
My first working prototype ran from LaunchBar.
I created an action that triggered a shell script, which in turn parsed the current Obsidian file and sent the tasks via the OmniFocus URL scheme.
At first, it looked promising. LaunchBar picked up the script, presented it as an action, and I could trigger it with a simple keyword. But then the gremlins arrived:
“The script does not implement a handler named 'run'”.After hours of troubleshooting, I realised the reliability wasn’t there. The script itself worked — but LaunchBar wasn’t the right launcher.
I rebuilt the automation inside Keyboard Maestro, which handles timing, focus changes, and system permissions much more predictably.
The macro:
Everything was almost perfect — except nothing happened. The logs said “No open tasks found.”
After several tests, I discovered the real culprit: macOS’s ancient Bash 3.2, which lacks mapfile. My whole parser depended on that command, so the script never captured anything.
The fix was to make it Bash-3.2-safe. The parsing logic was recreated in Perl, which handles UTF-8 and regex. Instead of mapfile, it outputs each task line to a temporary file and loops through them safely.
/usr/bin/perl -ne 'if (/^\s*[-*]\s*\[\s\]\s+(.+?)\s*$/){print "$1\n"}' "$FOUND" > "$TITLES_FILE"
Each task line is then URL-encoded and sent directly to OmniFocus:
open "omnifocus://x-callback-url/add?name=${NAME}¬e=${NOTE}&tags=Obsidian&autosave=true"
No Quick Entry panel, no intermediate prompts — direct to the Inbox.
The final piece was Alfred. After LaunchBar’s unreliability, I moved the trigger there. Alfred handled it flawlessly.
Now I just type cap in Alfred (for , and it fires the Keyboard Maestro macro that runs the script. Within a second, all unchecked tasks from my current Obsidian note appear in OmniFocus, tagged “Obsidian” with a backlink to the note.
 No friction, no crashes, and no mysterious “handler” errors.
No friction, no crashes, and no mysterious “handler” errors.
When the first test task appeared silently in my OmniFocus Inbox, I felt great satisfaction and relief. After all the false starts — AppleScript’s syntax chaos, Bash’s 2007 limitations, and LaunchBar’s quiet failures — it finally worked.
That single, silent task represented a perfect workflow: low friction, invisible automation, total reliability.
mapfile or other modern features.cap
It’s simple, fast, and utterly reliable — everything good automation should be.
When people talk about “seamless capture” in GTD, this is what they mean. The tools fade away, leaving nothing but flow. Now, if only I could have this work on Windows…