Create Obsidian page from OmniFocus

I am curious how people are integrating between OmniFocus and Obsidian. I wanted to be able to create and later go back to an Obsidian page for each OmniFocus project. I didn’t see good examples published. The below OmniFocus plug-in solves it for me. Are other people using other scripts or shortcuts to solve linking between OmniFocus and Obsidian?

/*{
	"type": "action",
	"targets": ["omnifocus"],
	"author": "",
	"identifier": "local.obsidian-page",
	"version": "1.0",
	"description": "Create or open an Obsidian page for the selected project.\n\nIf an Obsidian URL is found in the note of the selected project (or parent project for selected task), the URL is opened. If a URL is not found, a new Obsidian page is created and its URL added to the project note.",
	"label": "Open in Obsidian",
	"shortLabel": "Obsidian",
	"paletteLabel": "Obsidian",
	"image": "doc.richtext"
}*/
(() => {
	var action = new PlugIn.Action(function(selection, sender){
		const vault = "Obsidian" ;
		const folder = "Active Projects"
	
		// Get the selected project
		const project = (selection.projects.length >= 1) ? selection.projects[0] : selection.tasks[0].containingProject ;
		
		// Do we already have a url?
		let note = project.note ;
		const pattern = /(obsidian:\/\/[A-Za-z0-9-._~:\/?#[\]@!$&'()*+,;%=]+)\b/ ;
		const match = note.match(pattern) ;
		let url = null ;
		if (match) {
			url = URL.fromString(match[0]) ;
		}
		
		// Create the URL if needed
		if (!url) {
			let file = folder ;
			if (file.slice(file.length-1) != "/") {
				file += "/" ;
			}
			file += project.name ;
			file += " (" + new Date().getFullYear() + ")" ;
			file = encodeURIComponent(file) ;
			
			let content = "# " + project.name + "\n\n"
			content += "[OmniFocus project](omnifocus://task/" + project.id.primaryKey + ")\n\n"
			
			const openURL = "obsidian://open?vault=" + encodeURIComponent(vault) + "&file=" + file ;
			const newURL  = "obsidian://new?vault="  + encodeURIComponent(vault) + "&file=" + file + "&content=" + encodeURIComponent(content);
			
			// Add to note
			if (note) {
				note += "\n" ;
			}
			note += openURL ;
			project.note = note ;
			
			url = URL.fromString(newURL) ;
		}
		
		console.log(url)
		url.open()
	});

	action.validate = function(selection, sender){
		return selection.projects.length >= 1 || selection.tasks.length >= 1 && !!selection.tasks[0].containingProject ;
	};
	
	return action;
})();
1 Like

I’ve never used Obsidian, but was so intrigued by your script, I wanted to give it a go. I’ve been looking for a good integration between OmniFocus and a notes app, and I’m excited to see what this might be able to do.

One thing I noticed, out of pure happenstance, was that I have some projects with a “/” in their name. This caused an issue for Obsidian where the name of my project was split between a folder name and the note (file) name.

For example, I track my expense report lifecycle through a template project that I use a Keyboard Maestro shortcut to create. My expense report projects are usually named /… this results in a project name like “Get Reimbursed for DCA/Client Visit”. When I run this script, a new folder is created under Active Projects called “Get Reimbursed for DCA”, and then under that folder, a note is created titled “Client Visit”.

All that to say, on line 36 I made a small change which seemed to resolve my issue:

Original

file += project.name ;

Modified

file += project.name.replace("/","-") ;

Thanks for your change.

It would be nice to do a similar thing with the native Notes app. You would have to bounce through shortcuts, which is less elegant. Getting a URL to a note is challenging. The best option I have see is to use the Bubble Gum shortcut as an intermediary.

Greetings! It appears that Obsidian offers URL support as a means to accessing/adding data. Your approach therefore seems sound. Good work!

For those 3rd-party applications and services that use REST APIs Omni Automation supports the necessary API to communicate as well as mechanisms for storing keys in the system keychain and plug-in preferences locally. As an example, here is a link to a plug-in that connects to a Hive account:

https://omni-automation.com/omnifocus/plug-in-replicate-task-in-hive.html

In addition, here’s a link to a section showing how to integrate with the Craft app via URLs and Craft eXtensions:

https://omni-automation.com/craft/index.html

Cheers!

3 Likes

I’d hacked something together that was quite similar using Keyboard Maestro, Shortcuts, OmniAutomation and Hook. What you have created (by comparison) is an efficient well-encapsulated functionally-sound piece of code, well done! FYI the latest Hook Version 3.8 beta with Shortcuts support and more allows you to use MacOS Shortcuts to create bookmarks and hook them together, and I see that OmniFocus can call Shortcuts (re: Omni Automation: Calling Shortcuts). You’d have to get the task id and generate the Omni Url (as people in this channel probably well know) then pass that over to Shortcuts. It’s just another layer you can apply to zip back and forward between OF, Obsidian etc. There are some issues in the beta for Hook, but it’s still worth considering.

1 Like

Thanks for this, can I ask does one need to set the ‘company’ to some sort of reference to your (my) vault in order to get this to create a page in obsidian? Or is there any other changes I need to make for it to work locally?

You should change the line

const vault = "Obsidian" ;

To the name of your vault. My vault is named ”Obsidian”. It should then run on your computer.

If you like, you can customize the file variable to control the name of the new page and the content variable to control the body of the new page.

The linked version on GitHub has some updates.

1 Like

Hey thanks! My first Omnifocus Plugin. That’s very cool.