Michael Naumov28 downloadsMake every tag a note: tag a note by linking it, with a tag hierarchy, a tag tree with counts, subtree search and a migration from existing tags.
A #tag is a bare string. It cannot carry a description, aliases or properties of its own, a misspelt one silently becomes a new tag, and renaming one is a search-and-replace across the vault. A note has none of those problems, but tagging with links to notes loses what #tags give you: #parent/child hierarchy, the Tags pane with its tree and counts, and suggestions as you type.
Tag Notes makes the note the tag, so your tag pages are the tags themselves. A note is tagged by linking tag notes from a list property, keywords by default; a tag note names its parents in broader. The plugin brings back the hierarchy, a tag tree with counts, "tagged X or anything under X" lists, an @ suggester, and a previewed conversion of your existing #tags. All of it is plain frontmatter links, so the data stays readable with no plugin installed, and renaming a tag note renames the tag everywhere.
The documentation is an interactive demo vault. Every feature has a note that explains what it does and why you would want it, with a button that prepares a supplied set of tag notes so you can try each command on them at once.
Start reading here — it is plain markdown, so it works on GitHub with nothing installed.
A copy of the vault ships with every release. You can access it via any of the following:
Tag Notes: Open demo vault command.tag-notes-demo-vault.zip from the Releases. It unzips into a single tag-notes-demo-vault-<version> folder.demo-vault/ in this repository.keywords list, a tag note lists its parents in broader, several parents are allowed, and a cycle is reported and broken without editing any note. Every tag has a direct count and a count with descendants, each note counted once: see Tag index.@ suggester: choose a tag note by name or alias, or create one, and the link lands in the tags property: see Tag this note.#tags of the whole vault or one folder into tag notes, #a/b into b with broader: [[a]], after a preview of every note it will change. In a vault kept in git, each run can be one commit that Undo a bulk operation... reverts: see Convert tags and undo with git.tag-notes code block lists the notes tagged with a tag, with or without its descendants, and Copy Bases filter for tag subtree exports a subtree as a core Bases filter: see Queries and Bases.Every setting is listed by its data.json key in Settings.
| Plugin | Features | How Tag Notes differs |
|---|---|---|
Breadcrumbs |
hierarchies from typed links such as up and down; implied and transitive relations; trail, matrix and tree views |
Overlaps on hierarchy: not about tags, so no tag counts, no "tagged X or below" list and no conversion of #tags; works beside it, with broader declared as an up field |
Index Notes |
generates index blocks from hierarchical #tags |
Same goal of listing notes by tag: the tag is a note rather than a #tag |
Notebook Navigator |
a file browser with a #tag tree among its navigation |
Covers part of it: browses #tag hierarchies; tag notes are not tags there |
Tag Along |
browses the vault as a folder tree built from #tags |
Covers part of it: the tree is of #tags, not of tag notes |
Tag Folder Explorer |
virtual folders from nested #tags |
Covers part of it: the tree is of #tags, not of tag notes |
Tag Ontology |
parents, children and related tags for #tags, kept in a JSON dictionary; roll-up counts; Graph view |
Same goal of a tag hierarchy: the hierarchy lives in the tag notes' own broader links, not in a plugin file; #tags are converted rather than kept as the source of truth |
Tag Page |
generates and updates a page listing each #tag's references |
Inverse direction: the page is generated from the #tag; here the note is the tag |
Tag Wrangler |
renames, merges and searches #tags from the Tags pane; tag pages, notes carrying a #tag alias |
Inverse direction: its tag page describes a #tag that stays the source of truth; here the note is the tag, and renaming it is a file rename |
TagFolder |
shows #tags as folders |
Covers part of it: the tree is of #tags, not of tag notes |
Unified Tag Links |
links #tags to concept notes that list the tag in their aliases, through a managed tag_links property |
Same goal of joining notes and tags: keeps the #tag as the source and derives the links; here the links are the tags, with a tree, counts and a one-shot conversion |
Last searched for similar plugins on 2026-11-01.
This plugin publishes a read-only API, declared in api.d.ts, for plugins and scripts that want to know whether a file is a tag note, a note's tags, the notes tagged with a tag with or without its descendants, a tag's parents, children, ancestors and descendants, and its counts.
import { watchPluginApi } from '@mnaoumov/obsidian-lib/plugin/plugin-api';
import type { TagNotesApi } from './api.d.ts';
const apiRef = watchPluginApi<TagNotesApi>({
apiVersionRange: '^1.0.0',
app: this.app,
component: this,
pluginId: 'tag-notes'
});
// `value` is always current: `null` while this plugin is not loaded, and non-`null` on its own once it is.
const api = apiRef.value;
if (api) {
console.log(api.getCounts(tag)); // { direct: 1, withDescendants: 3 }
}
The handle comes from the @mnaoumov/obsidian-lib plugin registry; Cross-plugin APIs covers watchPluginApi and the registry from the library's side. The contract version is 1.0.0, and it moves independently of the plugin's own version, so ask for a range.
If you would rather not depend on @mnaoumov/obsidian-lib for the handle, the registry is a documented wire protocol you can read directly — see Plugin API protocol.
The plugin is available in the official Community Plugins repository.
To install the latest beta release of this plugin (regardless if it is available in the official Community Plugins repository or not), follow these steps:
Add plugin button once and wait a few seconds for the plugin to install.By default, debug messages for this plugin (id: tag-notes) are hidden.
If you need to enable them refer to the documentation.
All notable changes to this project will be documented in the CHANGELOG.
Contributions are welcome — see CONTRIBUTING to get set up.
Open issues through the issue forms, not as blank issues.
To report a bug from inside Obsidian, run the Tag Notes: Report a bug command. It opens the bug form with the plugin version, the Obsidian version and your operating system already filled in.
Filing from the CLI or the API (gh issue create --body, or an AI agent filing for you) skips the form, and gh issue create --template cannot load an issue form. In that case, open the matching form in .github/ISSUE_TEMPLATE/, copy every field as a ### <label> heading in the form's order, and fill in each one. Always state the plugin version, the Obsidian version and your operating system.