I’ll just chip in here, that I’d also like to be able to get hook links to obsidian notes. Would help with putting links to my notes into e.g. trello
Huge +1 from me too! I’ve only recently started using Obsidian after switching over from Joplin, and it is absolutely amazing!
I use NotePlan for Markdown notes and todos, and it has a great x-callback-url API: https://noteplan.co/faq/General/X-Callback-Url%20Scheme/ that allows any app to open a note in Noteplan from a URL like noteplan://x-callback-url/openNote?noteDate=20180204
If Obsidian did the same, note only would Obsidian be able to open NotePlan’s notes dir and visualise the graph, but Hook could glue the two together and allow NotePlan to open pages in back in Obsidian.
That would be an unparalleled level of Markdown knowledge management awesomeness!
I want to highlight this topic. The more I use both Hook and Obsidian, the more obvious and natural it seems to me to have Obsidian to do the native Hook linking. According to @LucCogZest, this is a relatively easy process from the development side. Obsidian developers, I’m not going to @ you because I know that’s rude, but readers, if you would like to see Hook and Obsidian work together, please let’s raise the visibility of this and try to get it on the roadmap.
Developer information is available here: https://hookproductivity.com//help/integration/other-app-developers/
I am a little lost here. Now that we have custom URL to vaults, notes, etc, isn’t this done?
No, it’s not done. There are workarounds – the Show in Finder trick and then use Hook from there – but Obsidian would be so enriched by having the full Hook functionality. For example, there is a feature in Hook where you can be on a web page, for example, and then use something called “Hook to New.” That creates a new note which is automatically deep-linked to that website on your computer. Currently, we can Hook to New in apps like DevonThink or BBEdit, and having Hook to New in Obsidian would be amazing.
I am not talking about the show in finder.
We have custom URL, such as:
obsidian://open?vault=Obsidian%20Help&file=Start%20here.md
We also have an API now, so you can write a plugin and access the custom URL automatically.
I am gonna move this to plugin ideas.
Thank you. I will work with the developers at Hook to see if they can build the plug-in and will let you know if there is anything else needed from the Obsidian side.
The steps to build a script in Hook for compatability are over at: Creating and Modifying Integration Scripts – Hook. The four parts are:
- Get Address
- Get Name (which is now optional if the name is returned as part of the address),
- Open Item
- New Item
The recent support for custom URLs in Obsidian should mean not having to do a custom Open Item. I think I saw support for a new item too, but would have to look around more.
The hard one is Get Address (and Get Name). My understanding is that Hook compatibility is done through Applescript, so Hook would need a way to ask Obsidian for the address and name of the currently viewed. I’m not sure if that’s possible for a plugin yet, or would have to happen to some degree in Obsidian itself.
This code could be used from a plugin to copy the current document (it would need some error handling if the editor doesn’t have the focus):
app.commands.executeCommandById('workspace:copy-url')
I still haven’t found a way to call that from Applescript.
I had a breakthrough! And it doesn’t involve any extra code in Obsidian so far!
- open
~/Library/Application Support/obsidian/obsidian.json
- look at
last_open
to see what vault was last viewed, and make note of it - look at
vaults
to find that vault - make note of the vault’s path
- open
path/to/vault/.obsidian/workspace
- look at the first item in
lastOpenFiles
to get the relative path - generate a obsidian with the vault and file path:
obsidian://open?vault=<vault id>&file=<relative path>
It doesn’t look like the obsidian URI supports creating new files yet. It could be done by using a similar approach, and then creating a file in the vault’s path.
That said, I got it working Here are Hook scripts for Obsidian
Open Hook -> Preferences -> Scripts -> “+” and then browse select Obsidian
For “Get Name”:
//JavaScript
(() => {
'use strict';
const main = () => {
const app = Application.currentApplication()
app.includeStandardAdditions = true
const homeDirectory = app.pathTo("home folder").toString()
const obsidianJSONPath = `${homeDirectory}/Library/Application Support/obsidian/obsidian.json`
const obsidianData = JSON.parse(app.read(Path(obsidianJSONPath)))
const vaultId = obsidianData["last_open"]
const vault = obsidianData["vaults"][vaultId]
const vaultPath = vault["path"]
const workspaceJSONPath = `${vaultPath}/.obsidian/workspace`
const workspaceData = JSON.parse(app.read(Path(workspaceJSONPath)))
const currentDocument = workspaceData["lastOpenFiles"][0]
const slashParts = currentDocument.split("/")
const basename = slashParts[slashParts.length - 1]
if (basename) {
const title = basename.replace(/\.md$/, '')
return title
}
}
return main();
})()
For “Get Address”:
//JavaScript
(() => {
'use strict';
const main = () => {
const app = Application.currentApplication()
app.includeStandardAdditions = true
const homeDirectory = app.pathTo("home folder").toString()
const obsidianJSONPath = `${homeDirectory}/Library/Application Support/obsidian/obsidian.json`
const obsidianData = JSON.parse(app.read(Path(obsidianJSONPath)))
const vaultId = obsidianData["last_open"]
const vault = obsidianData["vaults"][vaultId]
const vaultPath = vault["path"]
const workspaceJSONPath = `${vaultPath}/.obsidian/workspace`
const workspaceData = JSON.parse(app.read(Path(workspaceJSONPath)))
const currentDocument = workspaceData["lastOpenFiles"][0]
const uri = `obsidian://open?vault=${vaultId}&file=${encodeURIComponent(currentDocument)}`
return uri;
}
return main();
})()
This is great and really ties Obsidian into the hook ecosystem nicely. Thanks so much
Excellent! Thanks for this @technicalpickles!
That is so great, @technicalpickles!
I’ve set a Keyboard Maestro Macro to expand the string ;olink
into a link in whatever app I’m currently using it.
I was previously using System Events/AppleScript to do so, but it required an Obsidian App activation in order to complete its action.
Your JavaScript runs faster and without the need for activating Obsidian app. Many thanks!
Here’s the screenshot should anybody want to implement this as well
Actually, Hook is agnostic about the language. It can use any language/API that fits the bill.
Thanks for passing this on. A dev of ours had been studying the plugin. I’m sure she’ll find the JavaScript very useful.
Thank you for sharing this. May workaround was painful. This is just great. Kudos.
Hey @technicalpickles, once again thanking you for this script.
Also, I think I found a bug: your get name script is struggling to get accented characters (such as ã, á, â…) correctly. See attached image bellow for an example:
It should read 2020.2. Supervisões de…
Perhaps this is something easily fixable, perhaps it’s not… I don’t know JavaScript enough to judge it.
Anyway, this is still the best way to extract links to Obsidian notes via Automation
I don’t know how folks usually share and track their Hook scripts, but I pushed mine up to GitHub: technicalpickles/obsidian-hook-scripts
@ldebritto I don’t have any accented characters in notes yet, but I can take a look. Is that screenshot from Hook when you go to link? Does it display correctly in Obsidian?
Actually both scripts (Name and URL) fail on accented characters.
The screenshot from hook is this:
On Obsidian, it fails to retrieve the correct note:
That also will happen with Emoji on note titles.
I’ll mark your Git repo as watched!
Looked into it a bit, and I think this might be an Obsidian bug? I’m pulling things from .obsidian/workspace
(which is a JSON file), and the filename in lastOpenFiles
has the bad characters instead of the accents.
It looks like like the metadata cache in ~/Library/Application Support/obsidian/ObsidianCache/<vault id>.json
has the correct characters though. I’m not sure if there’s any way to work around it, since that is keyed by the filename, and the last file we know the name on is wrong