Automation Documentation: Hooking Automations with Obsidian

For anyone who follows me on this blog or anywhere else, you are probably familiar with the fact that I enjoy automating things. Having my devices do things for me. This has numerous benefits including saving me time and effort in the future, reducing the opportunity for human error, teaching me new skills, etc. But the fact is, when you start building up a large toolbox of automations it can be hard to keep track of the details. Some automations lend themselves to inline documentation, but what if you want to do something more?

In this post I am going to describe some of my set up around documenting automations using two tools on the Mac - Hook and Obsidian.

Documentation is Very Important

I cannot begin to stress how important it is to document things. I have been pushing quality documentation my entire professional career after having time and again discovered that documentation for things is either non-existent or woefully inadequate - be it insufficient in depth or hopelessly out of date. If you have a small amount of information, a thing that is capable of being understood with a quick scan, or something is not of any great importance, then I agree that it may ell not be worth the effort of documenting it. But, what if by not documenting it you end up building it again and again and again because you never remember where it is or that you have already done it. What about the things that are more complex and you would have to spend time refreshing yourself on? What if you need to pass something to someone else and they need to understand it as quickly as possible? Documentation is the key to unlocking so many things.

I am also not talking about the typical developer documentation auto generated from code with brief comments. I am talking about documentation that explains all the way from an overview down to the details. That gives examples, and helps the reader gain knowledge, not just providing data or information.

Once you are comfortable with automation you begin to discover opportunities to create more automations, but documenting them is often secondary. I know for me it has been that way for decades, which in hindsight makes me cringe. It wasn’t that I have not been documenting automations at all. Simply that my documentation has been fragmented and more limited than I would expect of myself.

More Than a Single Comment or Document

I have a tool of choice when it comes to documenting my automations (as well as other areas of my life) - Obsidian. Obsidian is an application that has been categorised as part of the “Personal Knowledge Management” domain of solutions. In basic terms it is a Markdown compatible editor that supports linking between content using wiki-style links. Now, Obsidian is highly configurable, has a thriving ecosystem and a strong community, so I really am only on the tip of the iceberg in describing it as an editor with linking - but that is exactly the key aspects I need.

When I had documented automations previously, they had been as blog posts on this site, text files that sat alongside a script, a note in Evernote, or a set of comments where an automation platform supported it. As you might expect, that was probably a bit of a mixed bag when it came to being able to find the information quickly. Especially if the automations spanned multiple platforms and the documentation could be held on multiple systems. It also meant that I was constrained by whatever the medium allowed - for example comments are often only permitted to be plain text and in some automations, relatively brief text or just a small window where larger volumes of text have to be scrolled.

Consolidating my notes into Obsidian gives me a consistent location to find the documentation, and importantly allows me to search across it with confidence. It allows me to build documentation in any way I choose with flexible editing options, and of course, I can interlink the documentation.

For example if I had a Keyboard Maestro macro that was running a shell script on a remote computer. I could now link two notes (one for each automation) in Obsidian together with a simple wiki-style link. That way if I am reading about one automation, I can quickly switch to reading information about the other.

Hook: The Documentor’s Accelerator

There is a little bit of not-so-secret-sauce to my approach, and that is a Mac application by CogSci Apps, known as Hook.

Obsidian allows you to easily create hyperlinks between notes (as well as supporting hyperlinks to resources external to Obsidian - e.g. a web page). But now imagine a tool that allows you to build links across your whole system. in a nutshell, that is the utility of Hook.

It provides you with easy access to getting a hyperlink to a particular resource. This means that if I had, for example, a PDF manual that was relevant to some automation documentation, I could select the PDF, activate Hook, grab the URL and put it into Obsidian.

In that sense, Hook is doing some automation for me as in each case I could put such URLs together myself. But, there are a vast number of variations and Hook reduces the friction that would involve to practically nothing.

But, that is not all that Hook does. There are a couple of other features I want to highlight that are of huge benefit to me in documenting my automations.

As well as providing a way to get a link to a resource, Hook also maintains its own database of hooked links. This effectively means that Hook establishes bi-directional hooking - if you are already familiar with Obsidian, this is analogous to back links. You can view and access the list of links via Hook.

This means that as long as the automation is “hookable”, you can use Hook to provide a quick access to other resources, such as supporting documentation.

New Hyperlinked Note in Obsidian

Another useful feature of Hook is to create a new note. This makes it easy to not only link to some documentation, but to also create the note to hold that documentation at the same time. Hook includes a lot of built-in options for how to specify this, including Obsidian.

By default, Obsidian is not assigning unique IDs to notes to allow Hook to reference them via a URL call. Rather it uses a (URL encoded) relative path in the URL to reference the note. In the screenshot above I have set new notes to be created in the root folder of my Obsidian vault.

Unfortunately, this means that if you move a file in an Obsidian vault (file system folder structure), that you in effect break the link URL. There are workarounds such as using meta data and the very useful Obsidian Advanced URI plugin, but I have taken a slightly different approach.

My notes are uniquely named, or at least should be. Now, the default Obsidian URL scheme will match just based on file name if no path is specified, but the path returned to Hook when hooking or calling to a hooked Obsidian note includes the relative path. To mitigate this and ensure that my links continue to work whether created as a new note from Hook or linked in the usual manner, I have made a modification to one of the Obsidian integration scripts.

You must be a Pro subscriber of Hook to be able to modify or add integration scripts. You can access them via the Hook app’s preferences.

The script below is a modified version of the standard Obsidian integration script (from integration set 218 available with the Hook 3.6 beta (4771)

-- to use Obsidian's advanced URL script, type this at the command line
-- defaults write com.cogsciapps.hook integration.obsidian.URL.scheme obsidian-advanced-URI

set sysinfo to system info
set osver to system version of sysinfo

considering numeric strings
    set isBigSur to osver  "10.16"
end considering

if not isBigSur then
    set myURL to "obsidian://hook-get-address"
    set myScript to "open '" & myURL & "'"
    do shell script myScript
    delay 0.4
    repeat 50 times -- poll clipboard for ~2.5 seconds
            if (the clipboard) is not equal to "" then
                exit repeat
            end if
        end try
        delay 0.05
    end repeat
    return the clipboard
end if

set prefUrl to ""
    set prefUrl to (do shell script "defaults read com.cogsciapps.hook integration.obsidian.URL.scheme")
on error errMsg
end try

if prefUrl is not "" and prefUrl is not "obsidian-default" and prefUrl is not "hook-file" and prefUrl is not "obsidian-advanced-URI" then
    -- An invalid value for com.cogsciapps.hook integration.obsidian.URL.scheme  has been set. There, we present the following options and set the default here.
    set thePrefChoices to {"obsidian-default (obsidian://)", "obsidian-advanced-URI (obsidian://advanced-uri)", "hook-file (hook://file/)"}
    set thePrefChoice to choose from list thePrefChoices with prompt "Please select one of the following URL schemes with which to interact with Obsidian:" default items {"obsidian-default (obsidian://)"}
    if thePrefChoice is not false then
        set x to thePrefChoice as text
        set AppleScript's text item delimiters to {" "}
        set prefUrl to text item 1 of x
        do shell script "defaults write com.cogsciapps.hook integration.obsidian.URL.scheme  " & prefUrl
    end if
end if

if prefUrl is "obsidian-advanced-URI" then
    set urlKey to "advanceduri"
    set callbackURL to "hook://x-callback-url/setCurrentNode%3FurlKey%3D" & urlKey & "%26plusencoded%3Dyes"
    set callbackURLError to "hook://x-callback-url/setCurrentNodeError"
    set myURL to "obsidian://hook-get-advanced-uri?" & "x-error=" & callbackURLError & "&x-success=" & callbackURL
    set myScript to "open '" & myURL & "'"
    do shell script myScript
    if prefUrl is "" or prefUrl is "obsidian-default" then
        set urlKey to ""
        set urlKey to "%26urlKey%3Dfile"
    end if

    -- @sylumer modification: works for unique file names only
    -- Will work when files are moved, but we'll resort to using the clipboard (like the pre-Big Sur approach)
    -- so we can modify the returned Markdown link to remove the folder path.
    -- Stop doing this>>
    --set callbackURL to "hook://x-callback-url/setCurrentNode%3FtitleKey%3Dname" & urlKey
    --set callbackURLError to "hook://x-callback-url/setCurrentNodeError"
    --set myURL to "obsidian://hook-get-address?" & "&x-error=" & callbackURLError & "&x-success=" & callbackURL
    --set myScript to "open '" & myURL & "'"
    --do shell script myscript

    -- Start doing this>>
    do shell script "open 'obsidian://hook-get-address'"
    delay 0.1
    set oldDelims to my text item delimiters
    set my text item delimiters to "&file="
    set newLink to (first text item of (the clipboard)) & "&file="
    set newLinkTemp to (last text item of (the clipboard))
    set my text item delimiters to "%2F"
    set newLink to newLink & last text item of newLinkTemp
    set my text item delimiters to oldDelims
    return newLink
end if

-- Don't bother with this>>
--return "hook://x-callback-url/setCurrentNode"

Note that in my set up I do not utilise a specific template for my new notes. I could do this, but I actually find tht my automations vary so much that a standard structure cannot deal with the variations that I have.


That is the basic premise and set up of my system of using Hook and Obsidian to help automate my automations. I’ve been using it in one form or another for a while now, and it seems to work well for me. I am far from having everything documented, but every time I work on something or naturally come across something while working on something else, I try and add some documentation for it into my system. The idea is that over time, I will fill in the many gaps in my documentation.

I plan to follow this post up with some additional posts about some additional approaches and configuration I am using to help with the documentation process.

Author: Stephen Millard
Tags: | hook | hookmark | obsidian | applescript |

Buy me a coffeeBuy me a coffee

Related posts that you may also like to read