Automatically run automation (URL) on task completion / skip

Run automation on task completion / skip

Hello, for a long time I’ve thought of submitting a feature request for OmniFocus, but I’m not sure if it’s something I’m the only one longing for, so I’m here to validate the concept.

TLDR: I’d love to have OmniFocus run an automation as a consequence of completing or skipping a task. This would be particularly useful for recurring tasks.

This feature would make OmniFocus the starting point for all sorts of automated tasks; a few examples:

  • For some tasks, I find it useful to have the last completion date saved in an AirTable, or count how many times I’ve skipped it. Both things are achievable with their API, but I lack the “trigger” being OmniFocus completing or skipping the task.
  • I have a recurring Daily review task that I mark as completed after running a shortcut, but it could easily be the starting point.
  • Every day I download some files from a website, so I could launch that website while completing the task without clicking the URL in the note and then returning to the app to complete it;

The simplest and most versatile way to achieve this could be by having OmniFocus to open an URL on completion/skip, as that would allow to launch websites, run Shortcuts or trigger any sort of URL-scheme based automation.

Lots of bonus points if that could be triggered from notifications (even though skipping an instance of a recurring action is not currently possible from a notification, and that’s also something I’d love to be able to do).

I understand that technically the action would be marked as completed before actually doing it, but if it’s something that takes little time I’m personally okay with that, and this is a niche feature targeted to automators, so most likely they can handle themselves and decide when this is appropriate.

Probably the best way to achieve this would be to offer 2 URL fields for tasks (one for a URL to run when a task is completed, the other for when the task is skipped), but I understand adding fields to a data model is not something one does lightly, so the same thing might be achieved by the app automatically parsing some defined structure in the notes field (i.e. ON_COMPLETION:shortcuts://…, ON_SKIP:http://…) whenever a task is completed/skipped. But these are only ideas, and I’m sure Omni can come up with a much better implementation.

Finally, I believe this could close a gap I see in OmniFocus, which is by far my favorite app ever, but I feel is losing on some fronts because it doesn’t really play nice with web-based automations; just having some URL fields that ran automatically on certain conditions would unlock an amazing automation potential, in my opinion.

Anybody else feeling this could be a worthy addition to the app?

1 Like

Oh well, I think this settles the “validating the concept” part… no one cares ;)

Still think this would be a valid addition to OmniFocus, hope someone from the team sees this and considers it.

Wishing you all happy holidays!

1 Like

I like the idea. It’s what we’d call a “task termination exit” in z/OS mainframe terms.

Note: Most of Omni Group went on their holidays roughly the day you posted this. So I wouldn’t construe this as uninteresting to them.

1 Like

Thank you! Yeah, I didn’t really consider the holiday period, I’ll keep my fingers crossed :)

1 Like

Basically OF does not have an externally accessible API which is why like Things but unlike Todoist working with web automation is not really possible.

What may be possible is to run a shortcut to trigger a task completion (which runs locally) then either goes onto the web for the download part of triggers a Keyboard Maestro macro to do it which may be more reliable.

I think the secret may not be to start with OF but with shortcuts. That said I certainly wouldn’t want to see additional fields in OF just to do this sort of thing from OF

Thank you for your considerations, @TheOldDesigner!

Basically OF does not have an externally accessible API which is why like Things but unlike Todoist working with web automation is not really possible.

I know, but having an Internet-accessible API for OmniFocus is not really needed for what I’m referring to, as I wouldn’t want external triggers (à la IFTTT) to make something happen in OmniFocus, but vice-versa: make me trigger a URL on completion / skip occurrence of a task to make something happen somewhere else.

What may be possible is to run a shortcut to trigger a task completion (which runs locally) then either goes onto the web for the download part of triggers a Keyboard Maestro macro to do it which may be more reliable.

It’s possible, but I see two problems with it: using Shortcuts “flips” the starting point outside of OmniFocus, which is not something I really want to to because it would mean having separate lists, and relying on Keyboard Maestro would limit things to macOS, which admittedly is where I do 80%, but URLs and therefore Shortcuts would be platform-agnostic.

That said I certainly wouldn’t want to see additional fields in OF just to do this sort of thing from OF

Focus progressive-disclosure and customizable UI is great because it doesn’t really force anyone to deal with fields they don’t need. Having said that, I would prefer specific fields without needing to clutter the Notes field with some specific syntax, and in the long term I believe it would be better to maintain from a code standpoint, but I’m fine with any implementation approach Omni would decide to take.

Don’t get me wrong, I know most people don’t need to trigger a URL to make something happen, but OF is leaving something on the table in favour of other task managers (mostly Todoist) for what basically is a couple of additional fields (and possibly not even those) an an open(_ url: URL) call on completion/skip. Very little code to unlock lots of automation capabilities.

Something you can do right now is to trigger a JavaScript plug-in action within the app which would both complete any selected items and also trigger whatever automations you might want (including calling out to other apps, Shortcuts, and even web APIs).

But I agree that it would be nice to offer completion-triggered automations so you don’t have to remember to use your plug-in action all the time, which brings us to this:

Completion-triggered automation is something we’d love to do. But we do worry about people coming to rely on those automations and then having them be unreliable because they’re not always available. For example, what happens when you complete the item from your Apple Watch? Or from a notification while the device is locked? Would you just skip the automation in that case? Would there be a way to retry later from another device? If there’s some way to retry later, is there a specific sync device designated to handle the retries (so you don’t end up with two synced devices performing the automation at once)? If there’s a designated automation device, what happens when you stop syncing / retire that device?

How would you like to see this work?

2 Likes

Good morning @kcase, and thank you for taking the time to reply during the holidays and for considering my request!

First of all, I want to apologise: when I get excited about something, I stumble into the most classic mistake… " basically is a couple of additional fields (and possibly not even those) an an open(_ url: URL) call on completion/skip, yeah, right, until one stops and thinks about implementation details and side effects! 😬

Something you can do right now is to trigger a JavaScript plug-in action within the app which would both complete any selected items and also trigger whatever automations you might want (including calling out to other apps, Shortcuts, and even web APIs).

I was wondering about that after posting this… To this day, I’ve only slightly modified (and taken enormous advantage from) @kaitlin’s amazing scripts, but I think it’s time to dive in with what you suggested.

But we do worry about people coming to rely on those automations and then having them be unreliable because they’re not always available.

Now, I can see these complex decisions that come with this feature…
I’ve been considering the examples you cited (and I will keep thinking about it), and come up with another problematic case I’ll mention at the end, and I think it wouldn’t be unreasonable, considering this would be a niche power-user feature, to put in some limits to the availability of the feature. I’ll explain going through your examples:

what happens when you complete the item from your Apple Watch?

This is by far the most complex one to handle, in my opinion; the choice comes down to:
a. Not allow completing tasks “with completion automation” from the Watch app;
b. Allow completion but showing an alert informing the automation won’t run.
My preference would be for “a”, as it would be consistent with notifications behaviour, as I’m explaining below.

Or from a notification while the device is locked?

Since you cannot know when scheduling a notification if it will be shown on a locked or unlocked device, or on a Watch that doesn’t have certain capabilities, I believe it wouldn’t be unreasonable to fire all notifications for tasks that have an automation component without the “Mark as done” action button: to complete those, tap the notification an launch the app.
I heavily rely on Pushcat to run Shortcuts in specific moments and scenarios, and that app notifications’ cannot do anything on my Watch, but they’re still very useful: I see them and either run from the phone right away, or act as reminder for later when I pick up the phone. I think this could work for these special OF tasks too.

Would you just skip the automation in that case?

In general, no, I’d rather delay or prevent task completion in those scenarios, unless an alert can be presented, than simply “skip it”.

Would there be a way to retry later from another device?

I think this would add too much complexity on your part, as you clearly explained in this scenario, for a feature that wouldn’t probably deserve so much of your time and resources.

I understand my suggestions don’t sum up to an exhaustive solution for the problem, but while building a power-user feature I don’t think it will be unreasonable to place some rails and explain that you can complete tasks with automation only in-app in iPhone, iPad and macOS.
The more I think about it, the more I think it would work well for my needs (which of course is only the smallest subset of Users).

There’s one last think that came to mind… I can only imagine that, 5 minutes after adding that feature, someone would ask for a way to complete a task that has an automation payload without actually executing the automation… in that case, a context-menu “Complete without running automation” action would suffice, IMHO.

Thanks again for considering this, I really believe it would be a wonderful addition to OmniFocus, when you’ll have the time :)

Happy new year to you and the team!

3 Likes

As a basic premise, I don’t really know Javascript and I’ve always only tweaked scripts made by others, but in the last hour I’ve put together a stub of automation to achieve what I wanted.

It’s incomplete and makes some assumptions, as mentioned in the description below, but in my tests it is working well if the tasks are setup properly (meaning that they have the emoji I chose for making those kind of tasks “evident to me” and remind me to use the keyboard shortcut for the automation instead of the spacebar, and with one URL in the notes field), and behaves as expected with tasks set to be recurring.

/*{
	"author": "Cesare Forelli",
	"targets": ["omnifocus"],
	"type": "action",
	"identifier": "com.cdf1982.omnifocus.complete-and-launch-url",
	"version": "0.1",
	"description": "Mark the currently selected task as complete and open the URL in the notes. Only runs (and completes the task) if there's a ⚙️ emoji in the task name plus a non-empty notes field, and currently only works with one task selected (opening multiple URLs would require some delay). At the moment doesn't check  if there's a valid URL in the notes field, so it might fail. It's a 0.1 for a reason ;)",
	"label": "Complete and Launch URL",
	"mediumLabel": "Complete and Launch URL",
	"paletteLabel": "Complete and Launch URL",
}*/
(() => {
	let action = new PlugIn.Action(function(selection) {
	
		selection.tasks.forEach(function(task) {
		
			if( (task.name.includes("⚙️")) && (task.note != "") ){
			
				URL.fromString(task.note).open();
				
				task.markComplete();
			};
		});
    });


	action.validate = function(selection) {
	
		return (selection.tasks.length == 1)
	};

	return action;
})();

If a native solution never materialises, I can live with this thing properly improved, it’s actually a good chance for me to get my hands dirty with something I have little experience with.

Thanks again for taking the time and consider my request!

P.S. I know the ⚙️ in the title is a terrible filter, I’ll switch to a tag instead as soon as I have the time to dig a little deeper ;)

In case someone else will stumble upon the script above, here’s a better version that checks for a ⚙️ tag as pre-requisite for the automation to run:

/*{
	"author": "Cesare Forelli",
	"targets": ["omnifocus"],
	"type": "action",
	"identifier": "com.cdf1982.omnifocus.complete-and-launch-url",
	"version": "0.2",
	"description": "Mark the currently selected task as complete and open the URL in the notes. Only runs (and completes the task) if the task is tagged as ⚙️ and the notes field is not empty, and currently only works with one task selected (opening multiple URLs would require some delay). At the moment doesn't check  if there's a valid URL in the notes field, so it might fail.",
	"label": "Complete and Launch URL",
	"mediumLabel": "Complete and Launch URL",
	"paletteLabel": "Complete and Launch URL",
}*/
(() => {
	let action = new PlugIn.Action(function(selection) {
	
		selection.tasks.forEach(function(task) {
			
			var taskIsTagged = false;
			
			task.tags.forEach(function(tag) {
				
				if( tag.name == "⚙️") {
					
					taskIsTagged = true;
				};
			});
			
			
			if( (taskIsTagged == true) && (task.note != "") ){
				
				URL.fromString(task.note).open();
				
				task.markComplete();
			};
		});
    });


	action.validate = function(selection) {
	
		return (selection.tasks.length == 1)
	};

	return action;
})();