I recently released Symlink Notes, an Obsidian plugin that adds a small piece of filesystem-like indirection to a vault: one Markdown note can act as a shortcut to another.
A shortcut is just an ordinary Markdown file with a symlink property:
---symlink: Problems/Weak Bedroom Wi-Fi.md---
Open that note and Symlink Notes opens the target instead.
Conceptually:
House/Wi-Fi.md | | symlink: Problems/Weak Bedroom Wi-Fi.md vProblems/Weak Bedroom Wi-Fi.md | +--> canonical content lives here
There is only one copy of the content. The shortcut doesn’t synchronize anything, embed anything, or duplicate the target. It provides another path to the same note.
Why not use a normal link?
Obsidian already has excellent links:
[[Problems/Weak Bedroom Wi-Fi]]
But a link and a shortcut solve different problems.
A link is something you put inside a note. Sometimes I want the note itself to occupy another useful location in the vault.
Suppose a note belongs canonically here:
Problems/└── Weak Bedroom Wi-Fi.md
But I also want it to appear naturally while browsing:
House/└── Wi-Fi.md
I don’t want two copies. I don’t want to decide which copy is authoritative. And I don’t necessarily want a stub note whose entire contents are a link I have to click again.
I want indirection:
House/Wi-Fi.md | +----------> Problems/Weak Bedroom Wi-Fi.md
That’s basically what a filesystem symbolic link provides.
So why not use one?
The filesystem is the wrong layer
Real filesystem symlinks are attractive on a desktop machine, but an Obsidian vault is increasingly not just a directory on one Unix-like filesystem.
My vault needs to work across platforms, including mobile.
A real symlink introduces assumptions about the filesystem underneath the vault: whether symlinks exist, how they are represented, whether the synchronization mechanism preserves them, and whether the application has access to the APIs necessary to resolve them.
Symlink Notes moves that indirection up one layer.
Instead of this:
filesystem | +-- symbolic link --> file
it does this:
Obsidian vault | +-- Markdown note | +-- symlink property --> Markdown note
There are no filesystem symlinks involved.
There are no Node.js filesystem APIs involved either. The plugin uses Obsidian’s public vault, workspace, metadata, and YAML APIs, and it runs on both desktop and mobile.
The important part is that the representation remains portable:
---symlink: Projects/ephemctl.md---
Without the plugin, that is still a perfectly normal Markdown document.
The extra behavior is provided by Obsidian, not encoded into the storage layer.
Following the target
Creating the shortcut is only part of the problem.
A useful reference also needs to survive changes to the target.
If:
Projects/ephemctl.md
moves to:
Software/ephemctl.md
Symlink Notes updates incoming shortcuts to point at the new location.
The same applies when the target is renamed or when one of its containing directories is moved.
The shortcut remains a path-based reference, but the plugin maintains that reference while it is running.
Only the symlink property is changed. Other frontmatter and body content in the shortcut are preserved.
That makes it possible for a shortcut to still carry metadata of its own if there is a reason to do so.
Chains
Shortcuts can also point to shortcuts.
A.md | +--> B.md | +--> C.md
Opening A.md resolves the chain and ultimately opens C.md.
Resolution happens when the note is opened rather than by flattening these relationships ahead of time.
That creates an obvious failure case:
A.md --> B.md ^ | | | +--------+
So Symlink Notes detects circular references and limits resolution to a maximum of 20 redirects.
Missing targets, invalid paths, loops, and excessively deep chains fail closed: Obsidian leaves the original shortcut open and displays a notice instead of trying to guess what the user intended.
Intentionally narrow paths
The symlink property accepts an exact vault-root-relative Markdown path:
symlink: Software/ephemctl.md
It deliberately does not try to become a generic URI system.
Absolute paths aren’t allowed. Neither are URLs, .. traversal, folders, or attachments.
That restriction is useful because it gives the property a very specific meaning:
This note redirects to another Markdown note inside this vault.
Nothing more.
That also makes the behavior much easier to reason about across platforms.
Creating one
Symlink Notes adds a Create symlink to active note command.
Run it against the canonical note, choose a destination folder, and the plugin creates the shortcut using the target’s filename.
For example:
Problems/└── Weak Bedroom Wi-Fi.md
could produce:
House/└── Weak Bedroom Wi-Fi.md
with:
---symlink: Problems/Weak Bedroom Wi-Fi.md---
The command refuses to overwrite an existing file or directory.
Once the shortcut exists, opening it from the file explorer, Quick Switcher, an internal link, or normal Obsidian navigation redirects the existing Markdown pane to the target.
The useful part is the abstraction
Symlink Notes is a small plugin.
That’s intentional.
It doesn’t introduce another database, invent a synchronization format, or attempt to replace Obsidian’s linking system. The canonical content continues to be an ordinary Markdown note, and the shortcut continues to be an ordinary Markdown note.
The plugin adds one bit of interpretation between them:
Markdown +vault-relative path +Obsidian navigation =portable note indirection
That’s enough to get most of the property I actually wanted from symbolic links without requiring the underlying filesystem to participate.
And because the representation is plain Markdown, disabling or removing the plugin doesn’t strand the data in a proprietary format. The shortcut simply stops redirecting and becomes a normal note containing a readable path to its target.
Symlink Notes 0.1.1 supports Obsidian on desktop and mobile. The source, release details, and installation instructions are available on GitHub under the MIT license.
For a shorter portfolio summary alongside my other tools, see the Projects page.
