Automating Your Obsidian Workspace

Contents

Obsidian is a popular tool for managing notes in Markdown format. It is cross-platform, uses files direct from a file system location, and has some rather useful features, including a range of plugins created by the developers and the wider community. In this post I am going to walk you through how I have used some of the community plugins to give me better control over a feature known as workspaces.

Obsidian Workspaces

In case you are unfamiliar with Obsidian and its workspace features, I am going to start with a little background.

Obsidian allows you to open and interact (create, read, update, delete, and search) with sets of notes in Markdown format. These sets are based on a folder structure, which can be whatever suits you, but each root of such a set is the root of what in Obsidian terms is known as a vault.

The Obsidian app itself applies a flexible pane model to its user interface. Each pane is almost like a window in its own right. You cannot drag it around anywhere within the main Obsidian app window like you could with the old Microsoft Windows multiple document interface (MDI), but you can split and align different panes to be different sizes and have varying content.

The layout can be as simple or as complex as you like. Here I have the Obsidian help vault open, and I have numerous panes open and options enabled.

Each Obsidian vault also stores Obsidian settings alongside the notes. This allows Obsidian to offer different functions, behave, and display differently based on the settings you have for a particular vault. For example, you may have a plugin that you use to support Internet research that are relevant to vaults you maintain on cooking, IT, and movies. But maybe there is a third plugin for allowing you to execute scripts that is only ever going to be of use when you are using your IT vault. Maybe you also want to have a different colour scheme applied to the app to help you quickly identify which vault you are looking at from just a glance to the screen?

As well as styling and extra functionality, Obsidian also has a concept known as Workspaces. This is also a plugin for the app, but one that was developed by the Obsidian developers. It allows you to save particular layouts for a vault, so you can switch between them. Specifically it stores the state of the pane layout (including which pane has focus), the sidebar states and the file open states. For example, you might have a particular arrangement of panes that you like to use for taking notes during a meeting, a different one for writing and researching your latest project, and another for reviewing your study materials? You would set these up as workspaces and then switch between them as required.

Enabling Workspaces in Obsidian

As noted above, workspaces are an additional set of functionality delivered by a plugin. To enable workspaces for a vault:

  1. Open Obsidian’s settings (the Open Settings command in the command palette).
  2. Select Core plugins from the list of available options in the navigation list.
  3. Scroll down or use the search option to find the Workspaces plugin.
  4. Select the Workspaces plugin to toggle it and enable the plugin.

Once you have a particular layout that you like, you can call the Save a workspace command from the command palette, provide a name and save the details. To load the workspace in, you call the Load a workspace command from the command palette and then select the workspace to load.

Naming Tip
If you prefix your workspaces with a unique identifier, it makes it very quick to search/filter your list of workspaces when loading them. I tend to use single-digit numbers as a prefix to make workspaces quicker to access.

Load List Tip
Using the same numeric basis, I tend to set the keyboard shortcut to load the list of workflows to be CTRL + 0 (Windows) or CMD + 0 (Apple OSes). This makes it easy to remember and access, and the selection of the workspace follows on logically.

The Dynamic Workspace Limitation

As previously noted, workspaces store a set of layout information that includes file open states. This means that the workspace cannot be set to do things like dynamically load a daily note for the current day, or set any subsequent configuration that isn’t stored as part of the workspace’s data set.

I tend to keep my pane layouts empty of specific files so I can quickly build up what I need for a particular task as my working needs can vary quite a bit. But in particular the desire to load my daily note into my two-pane layout with the notes on the left and the preview on the right is something I have a more than daily need for.

Side Note:
I tend to have both the editable note and the preview up as I often need to copy out of notes in a rich text format, view rendered diagrams (from Mermaid code), images, etc. When I only need to edit, I tend to use the Maximise Active Pane Plugin to focus on a pane rather than having a workspace for it. This approach gives me even more flexibility than a specific workspace would.

While there are limitations, a bit of automation know-how and a few additional community plugins, and even a dynamically populated workspace is not beyond reach.

Building the Automation

Before starting to build the plugin, make sure you have your workspace to be automated all set up. For my use case, my workspace is called 1-Main and I will be referencing that as I build my automation. The workspace looks like this.

Step 1 - Install Additional Plugins

To build the automation for a dynamic workspace, we start by installing two community plugins.

To install these community plugins you can follow these steps.

  1. Open Obsidian’s settings (the Open Settings command in the command palette.
  2. Select Community plugins from the list of available options in the navigation list.
  3. Select Browse.
  4. Enter the name of the plugin in the search field.
  5. Select the plugin in the list.
  6. Select the button to Install the plugin.
  7. Select the button to Enable the plugin.

Step 2 - Compose a URL to Load a Workspace

I provided some tips above to make it easier to load workspaces by name as Obsidian does not currently enable you to add keyboard shortcuts to specific workspaces. This seems to be the only way to access and load a workspace natively; well via a core plugin. However, the Advanced Obsidian URI plugin provides another way for us to load a workspace.

A URI or Uniform Resource Identifier is an identifier for accessing a resource. A URL is a Uniform Resource Locator, and is probably what most people are familiar with. These are a subset of URI, but for all intents, we are going to be generating something that looks and works like a special URL for interacting with Obsidian and that allows us to request that Obsidian loads a workspace for us.

The Navigation options for the Advanced Obsidian URI plugin allow us to specify a workspace by name to be opened by using the workspace parameter.

The schema is of the form obsidian://advanced-uri?vault=<your-vault>&<parameter>=<value>&<parameter2>=<value2>, so we can build our URI like follows for the 1-Main workspace.

obsidian://advanced-uri?vault=<your-vault>&workspace=1-Main

Because my example workspace name has no spaces or other non-URI friendly characters, I did not need to URL encode it, but if you do find you have spaces or other unusual characters, just use an online encoder to generate the parameter value.

You may have noticed that we haven’t specified the vault. vault is actually an optional parameter in that if you exclude it, it will work on the current Obsidian vault, but to remove ambiguity, we should specify that too. For this post I am using my demonstration vault “obsidian_demo”. The URI therefore becomes this.

obsidian://advanced-uri?vault=obsidian_demo&workspace=1-Main

If I put this URI into the Safari (web browser app) address bar on my Mac, I get a security prompt, but after selecting to allow, this triggers Obsidian to open my demo vault (or switch to it if already open), and load my workspace.

Step 3 - Build a Script

The next step in the process is to build a little wrapper to do the same job as our web browser, but to do it in a way that is automatable from within Obsidian. This wrapper for our URI is going to be in the form of a very short script.

Assuming you have not created any scripts before for use in Obsidian, the first thing we want to do is put the script file somewhere that Obsidian can find it. In other words somewhere inside the vault.

The script file is going to be a JavaScript script file and will have a .js file extension. Obsidian’s navigation only deals with Markdown files, so wherever we put this script file, it is not going to show up in Obsidian. While we could just dump it in the root of the vault, my preference is to place them in a specific folder. To that end I created a “Scripts” folder in my vault.

Do note that if you create a hidden folder (e.g. .scripts on a Mac), then the script files in that folder get hidden from the plugin that we are going to call the script from.

Once you have decided where you want to place your script, you can go ahead and create the file in that location within your favourite text editor. I named my script file workspace-load-1-main.js.

The content of the file is as shown below. Note the URI for opening the workspace. You should obviously change this to match your own URI.

module.exports = async () =>
{
	window.open("obsidian://advanced-uri?vault=obsidian_demo&workspace=1-Main");
}

Note For command line fluent people, you don’t need to set the executable bit on the file as Obsidian will read and evaluate the content. It is not run standalone.

You do not need to understand the detail of what this script does other than to know when it is run, Obsidian will make a request to open the URI, which will then itself trigger a request to Obsidian, to request that the Advanced Obsidian URI plugin trigger the load of the specified workspace.

So our call chain now looks like this:

## Mermaid Code to generate this diagram ``` graph LR subgraph 1[ ] A(Some Trigger in Obsidian) B[Call Script] C[Open URI] D[Load Workspace] A --> B --> C --> D style A fill:#ffffff,stroke-width:2px,color:#000000,stroke-dasharray: 5 5 end ```

{Some Trigger in Obsidian} > Call Script > Open URI > Load Workspace

Step 4 - Create a Macro to Call the Script

This is where I feel things become a little less intuitive as we dip into using the QuickAdd plugin. The primary purpose of this plugin is to allow you to quickly capture information and put it into notes. However, it also allows us to carry out a little bit of automation, such as calling our script via a macro.

Firstly, navigate to the QuickAdd configuration page.

  1. Open Obsidian’s settings (the Open Settings command in the command palette.
  2. Select QuickAdd from the list of available plugin options in the navigation list.

Unless you have used QuickAdd before, you should be presented with a rather barren looking window like this.

The next step is to create a new, empty macro which we can then configure.

  1. Select the button to Manage Macros.
  2. Enter a name for your macro in the Macro Name field.
    • I am going to call mine “Daily Set Up”, because as well as calling a script, I am going to enhance it further a little later on.
  3. Select Add Macro.

Next we populate our empty macro with instructions to run our script.

  1. Select the Configure button to open the macro configuration window.
  2. Select the script (for me workspace-load-1-main.js) in the User script field.
  3. Select the Add button.

The result should look something like this. A macro with a single action that is to run a script.

With that configured, press ESC twice to return to the main QuickAdd settings window. There is more work to be done.

Step 5 - Create a Quick Addition

We now have a macro we can run, but there is an additional piece of configuration that we need to carry out in the QuickAdd plugin to allow us to run the macro. This is why I feel that QuickAdd is a little unintuitive in that a macro isn’t something we can use, but rather something we can call, and as yet QuickAdd does not really provide much in the way of reuse around this, so my assumption is that either there is something on the roadmap that will require this disconnect, or I am just overlooking a more obvious reason.

Creating the quick addition is easy to do.

  1. In Name enter the name of your macro (for me “Daily Set Up”).
    • Using the name of your macro makes it easy to know which macro it is running.
  2. Select Macro from the drop-down list next to the name.
  3. Select the Add Choice button.

We now need to connect the macro to the quick addition.

  1. To the right of the new quick addition are a set of icons. Select the cog to open the configuration window for the quick addition.
  2. In the drop down list select the name of the macro you created.
    • If you only have one QuickAdd macro, it will be selected by default.
  3. Press ESC.

Step 6 - Test

The final step in the basic set up is to test that this works.

From the main Obsidian user interface, bring up the command palette and search for the Quick Add: Run QuickAdd option and select it. This will then display your QuickAdd options.

At this point you should see your quick addition listed (e.g. “Daily Set Up”). Selecting this will run the full automation, opening your workspace.

Enhancing the Automation

The chaining to trigger the workspace now looks like this.

## Mermaid Code to generate this diagram ``` graph LR subgraph 1[ ] CP([Command Palette]) subgraph 2[Quick Add] QA(Quick Addition) QM(Macro) end B[Call Script] C[Open URI] D[Load Workspace] CP --> QA --> QM --> B --> C --> D end style 2 fill:#c1cfc0,stroke:#87A8A4,stroke-width:2px ```

Now it may seem that all we have done is build something convoluted that in the same number of key presses does what the load workspace option we started with does. And you would be absolutely correct. It is seemingly like we have reinvented an over-engineered wheel. But you know what? We can use this new wheel to go faster and farther than the previous version. We just need to put in a little bit more work.

Step 7 - Add it to the Root of the Command Palette

The first thing we will do is to enable the quick addition entry to appear in the command palette when we search. This eliminates needing to go into the Quick Add: Run QuickAdd option first.

This is quite straight forward to do.

  1. Open Obsidian’s settings (the Open Settings command in the command palette.
  2. Select QuickAdd from the list of available plugin options in the navigation list.
  3. Select the lightning bolt icon to enable for the command palette.
    • The icon will change colour when enabled.

Now when searching in the command palette, we can see the QuickAdd entry has been surfaced.

When the entry is selected it will run the quick addition.

Step 8 - Assign a Keyboard Shortcut

Making it a command palette entry is really just a stepping stone to get us to a point where we can assign a keyboard shortcut. Obsidian allows any entry in the command palette to be assigned a keyboard shortcut.

Here’s how you do it.

  1. Open Obsidian’s settings (the Open Settings command in the command palette.
  2. Select Hotkeys from the list of available options in the navigation list.
  3. Use the filter field to search for the command palette entry you want to update.
  4. To the right of the entry is an icon of a key with an asterisk on it. Select that icon.
  5. Press the keyboard shortcut you want to use to trigger the command palette entry.

I opted to set my “Daily Set Up” entry to be triggered by CTRL + CMD + 1 on my Mac.

Step 9 - Enhance the Macro

Now we have a pretty fast way of triggering everything, which is a step above the standard approach, but now we need to add in the dynamic element.

For my 1-Main workspace, for this set up, I want to display the daily note for the current date (creating it if necessary), in both panes. In the left pane I want to have it in edit mode, and in the right frame in preview mode, with the two panes linked.

Now, at this point, I will let you in on a secret. My workspace is already configured to have the two panes linked, and open with two empty (“No file is open”) panes. How do you do that? Well there are two ways I know of. One is to modify the underlying JSON for workspaces, but the other is probably a little quicker in most cases and can be achieved in the user interface. It is not essential to what follows as we could automate it another way (which I am positive you will figure out as we go through), but I think this approach is quite efficient and it may be of use to some of you.

Once you have your layout for your workspace, if you want to have a pane that is empty rather than having a file in it, all you need do is to open a new file in the pane and then delete the new file. The pane will then show the “No file is open” information. Note that there is no command in the command palette to close a file, so this is the only way I have found to date of getting the pane to do this.

If you have two panes that you want to link (an option available on the More Options menu for a pane - the three vertical dots in the top right corner of the pane), but also show initially as empty, you simply need to link the two panes together before you delete the file. The link will remain in place. Unfortunately, the state is not maintained. It is not a workspace thing, but rather a broader Obsidian thing.

If I set one pane to be the preview of another, then switch to a new file, delete the file, and switch back to the previous file, both panes will now be in edit mode rather than one in edit and one in preview.

As you may have guessed from the title of this section, we are going to give the QuickAdd macro some additional instructions to finish setting up our workspace in a more dynamic way. Previously we used a user script to trigger the URL, but we actually have seven options available.

  1. Capture - Get some user content.
  2. Template - Build some content automatically.
  3. Wait - Do nothing for a period of time.
  4. Obsidian Command - Call a command palette entry.
  5. Editor Command - Run one of a small selection of editor commands.
    • Copy.
    • Cut.
    • Paste.
    • Select Active Line.
    • Select Link on Active Line.
  6. User Scripts - Run a script.
  7. Choices - Offer the user a choice of quick addition to run.

Opening a daily note (including its creation if necessary) is available from the command palette. The same is true of toggling between edit and preview mode. There are also pane navigation options in the command palette allowing you to shift the focus up, down, left and right between panes. With these commands we can build up a macro that after loading the workspace loads the daily note (it loads in both panes as we have that as part of the workspace set up), shifts focus to the pane we want to use for previewing, toggles from edit to preview mode, then shifts the focus back to the other pane for editing.

One thing to note at this point is that computers can be too fast at times. Things can occur in parallel and things can then occur out of order. An issue often referred to as a race condition. To help with that we can add delays in to say wait for this long, this long being an estimate of the maximum time it will take the previous step to complete, before moving on to the next step. Therefore you will see lots of wait entries in my final macro. The values are ones that work reliably for my computer, but because there is a dependency on your available resources, you should tailor these to work for your set up. You may be able to reduce the wait times if you have a faster computer. If you have the same computer, but with more utilised resources, you may find you have to increase the wait times a little. The wait times are in milliseconds, so overall the wait time will probably be under 2 seconds which for most people should not be too onerous.

Modifying Wait Times I didn’t think it was obvious, so in case that applies to you too, to change the duration of a wait period, click on the number after the “Wait for” entry and over type it with the length of delay that you want.

Here is what my macro looks like with these extra steps added in.

Step 10 - External Trigger

With the keyboard shortcut, you can trigger the whole process quickly from within Obsidian. But I am guessing the keen automators among you might be wondering if it is possible to trigger this from outside Obsidian. Could you for example include this on a start of the day schedule, or an Elgato Stream Deck/Better Touch Tool drive touch bar to switch your context or mode of operation. It should be no surprise that this is also possible.

We used the Advanced Obsidian URI plugin to load our workspace earlier, but we can also use this plugin to call any command palette entry using the commandname parameter.

Therefore to open my demo vault and run my “QuickAdd: Daily Set Up” entry, I can use this URI.

obsidian://advanced-uri?vault=obsidian_demo&commandname=QuickAdd%3A%20Daily%20Set%20Up

Opening a URI from the command line or your favourite automation tool should be relatively trivial from this point.

We then have the following.

## Mermaid Code to generate this diagram ``` graph LR subgraph PC[ ] subgraph OBS[ ] KS([Keyboard Shortcut]) CP([Command Palette]) subgraph QCK[Quick Add] QA(Quick Addition) QM(Macro) end B[Call Script] C[Open URI] D[Load Workspace] CP --> QA --> QM --> B --> C --> D KS --> CP end EX(External Trigger) EX --> |URI Call| CP end style PC fill:#DBEBFF,stroke:#62a9ff,stroke-width:2px style QCK fill:#c1cfc0,stroke:#87A8A4,stroke-width:2px style EX fill:#99c7ff,stroke:#62a9ff,stroke-width:2px ```

Conclusion

This might have been a surprisingly large number of steps to achieve something that at first glance seems relatively innocuous. I would have to agree that it would be nice if things like this were easier, but Obsidian is moving fast and there may be an easier way to do this in the future. For now I am happy to have a flexible solution that I can use today; in fact I’ve been using it for a few months at this point.

While the output of this may seem relatively small, it is something I was doing manually multiple times per day. Having these automations in place means I can set it and forget it. Everything works just the way I want it now and that bit of friction has been removed from my day. I am also using the principles demonstrated here in other areas of Obsidian use, so it has helped me push on in those areas too. For me the effort involved I think has already paid off, and by sharing it with you, hopefully that benefit will increase even more.

If you find this useful, and please do reach out on social media and let me know. Do also share it with any other Obsidian users that you feel may find it useful.

Author: Stephen Millard
Tags: | obsidian |

Buy me a coffeeBuy me a coffee



Related posts that you may also like to read