Obsidian plugin· Released · beta · not yet released
Topic Map
Finds the topics your books and notes share, draws them as a map, and answers a question with cards that quote their passage.
What's changed in Topic Map
Unreleased
not yet released
Everything built so far, for the 1.0 release.
New
- Add-on passes. A lens that uses a domain library can read some of its domains in later passes (
addons). An index run now runs them. Each pass reads only the passages the first read let through the lens's gate, and one written{domains: [craft], select: craft}reads only those the craft screen picks in each book: every passage scored 3 oncraft_notable, a spread of 2s up to 5% of the book, and the book's first and last passage. What a pass reads is kept under its own key, so adding or changing an add-on never reads the first pass again, and a run stopped mid-pass carries on without paying twice. The dry run counts and prices each pass's reads, and Undo a run takes them back. See Add-on passes in the lenses guide. - Each card's neighbors, exactly. The map now finds each card's 30 most alike cards on whole vectors, the same lists a card-by-card comparison gives (they were taken on the first quarter of each vector, which agreed on about 84% of each list). It takes about 80 seconds for 60,000 cards. The lists are saved on their own beside the map and kept while the vectors, cards and topics stay the same, so laying the map out again, or a new version of the layout, no longer finds them again. Maps saved before are laid out again once.
- Redraft a catalog tree from itself. When a re-index changes a catalog's clusters,
catalog tree --from-treecarries the tree over to them: a type whose cards still make up most of a new cluster keeps its id, name, place and variants; new clusters become new types with fresh ids, beside the types that hold their cards; and what can't be kept (a type whose cards scattered, a variant whose versions all left) is listed with why and left in the tree as it was. A dry run prints all three lists first; the real run writes the tree file and notes in one run that one Undo takes back. Renames and moves now pin what they changed (pinned: [name],pinned: [parent]in the tree file), so that choice is on record; trees made before this pick up their pins from the run log once. - Move a catalog node. Move on a sub-family or type card puts it under another family or sub-family: pick the new parent from a list grouped by family, see every file it would change, then move. The tree file, both family notes and the cards follow, the node keeps its id, and Undo a run takes it back. Other plugins can move nodes through the API (
moveCatalogNode, and thetopic-map:catalog-movedevent). - Catalog polish. A catalog note's source-name map is now
source_aliases, so Obsidian no longer warns about its ownaliasesproperty; an oldaliasesmap is still read and renamed at the next run. A card's about shows up to three lines, with the whole text when you point at it. The<!-- catalog:… -->markers no longer show as gray text in Live Preview; put the cursor on a marker's line to see it again. - Words, a third way to see the map. Beside Themes and Network, Words shows a collection's topics as a field of words: each family's name big at the middle of its topics, every topic's name where its dot would be, sized by its cards and colored by its family, small ones faint until you zoom in. Select a topic and its linked topics travel in around it, strongest closest (↗ for another family), with its strongest cards under it; select a card for its box with Read passage and Open in book, or walk from topic to topic with a trail to come back by. List shows the same as an outline you can use from the keyboard, with chips that jump to what a row links to. On the library map each book is its title in its shelf's color, and a book gathers its similar books. Words draws without WebGL, so it works where the canvas can't. A link takes
lens=words, and so does thetopic-map.open_maptool. - The map's Network shows topics. On a collection with topics, Network now draws one dot per topic, sized by its cards and colored by its family, linked to the topics its cards are most like (a link's strength is measured against the two topics' sizes, and each topic keeps its strongest few). It replaces a field of every card that was unreadable on a large collection, and lays out in a fraction of the time. Select a topic to light its linked topics and list them, strongest first with ↗ for another family, and its strongest cards; Show its cards goes to Themes on it. A card picked in Find selects its topic. Collections without topics yet, and the library map, keep the card network. Maps saved before are laid out again the next time they open.
- Catalogs as cards. A tree catalog's note now shows its families as a grid of cards, each topped with its family's color, with its icon, name, a line about it, and its cards, sources and rarity. Select a family to see its sub-families, then their types, then a type's variants; Back and the trail above the cards go up again, and a type opens its section in the family note. Give a family
icon:(one emoji or a few letters) andcolor:(a quoted"#rrggbb") in the tree file, or it gets a color from the theme. Without the plugin, the cards read as a plain list. Rename on a card renames that family, sub-family, type or variant everywhere: the tree file, the catalog note, the heading in its family note and, for a family, the note's file name, so links follow. Undo a run takes a rename back. Other plugins can read and change the names through the API (catalogNames,catalogNodeName,renameCatalogNode, and thetopic-map:catalog-renamedevent). - Passage links name their vault. Topic notes' passage links now carry
vault=, so a link opens in the vault it belongs to when several vaults run Topic Map (Obsidian opens that vault if it's closed). Links already in notes get it at the next Write; links without it still open in the current window. - One note per family by default. Find topics now writes a note for each family with its topics as
##sections, about a tenth of the notes it wrote before, so plugins that index the whole vault hold far fewer. Setup → Folders → Topic note layout brings back one note per topic. A topic links as[[Family name#Topic name]]; the panel's Open in family note goes to its section. The next Write after a change replaces the notes in the other layout (the dry run counts what it writes, replaces and removes; Undo a run takes it back), and a note you edited is kept. - Repeated terms show once. When several passages or books use the same term with the same meaning, search shows it once with how many books and versions, and Versions lists each. The panel has a Groups tab, and a topic lists its key terms; topic notes fold a term's versions under one line at the next Find topics. A name used for two meanings stays two. Say Not the same or Join with… in the panel and later indexes keep your answer; Undo on the Runs tab takes it back. Setup → Search → Show every card turns it off. Grouping uses no model and costs nothing. The tools and the API (0.2.0) give each card its group.
- Traces name each job. With traces on in Model Hub (API 0.11), each job's run span says what the job is and on which collection (
run plugin:topic-map: index Garden notes), never any note text. An older Model Hub just leaves the name off. - Also from Insurgently: the settings tab, the README and the guide link the other plugins of the family (Model Hub, Library Hub, Learning Editor).
- Open in book. A card from a book opens the book in Library Hub's reader, in a new tab, at the card's quote (else its chapter, else the book's start, which it says). It sits beside Open passage in search, and in the passage dialog. It needs Library Hub 0.5; with an older one, Topic Map says so and shows the passage. For a note or a Base row, the passage dialog has Open note, at the passage's heading.
- A link to every passage.
obsidian://topic-map-passage?corpus=…&unit=…&card=…opens a card's passage from any note or page. Each card in a topic note now has a passage link, and the claims and misfit cards in the panel's topic view open their passage when selected. - Topic names are paid for once. Find topics keeps each name beside the index and reuses it when a topic's cards, the lens's naming prompt and the naming model are the same, so a second run names only what changed. Families are named again when their topics or siblings changed, and loose topics still get their second try. The dry run says how many names it would reuse ("18 of 22 names reused from earlier runs, 4 to name"). Names paid for before a spend limit stopped a run are kept. More options → Name topics again asks for every name afresh.
- Keyword matching (Setup → Search): Words and meaning also ranks the cards, passages and book titles that use your question's own words and names, so a person, an acronym or a coined term comes up first; a near-miss spelling of a name or title still counts. Search, Other books, Draft and the
topic-map.searchandtopic-map.neighborstools all follow it, and the tools takemodeto choose per call. It is off (Meaning only) by default: measured on a test collection, it ranked name and term searches clearly better but broad questions across books a little worse. - Topics check themselves. Find topics removes the strongest card-vector directions (which follow how cards are written, not what they say) before clustering. It measures how many families and topics to make, names each family again with the others in view, merges clear overlaps (undoable) and lists the rest for you. It also labels topics mostly from one book, tries loose topics once more, and checks terms from the collection's context for topics spread across families. Each run's quality numbers are kept beside its cost. A collection can pin families it always wants (
families:) and tune the rest undertopics:. In the panel, the Runs tab shows what changed since the last Find topics, and overlapping families wait on the Topics tab, answered once and remembered. The Find topics dialog has Fewer · Auto · More and pinned families, written to the collection note on Write. - Your collections in Claude. Topic Map registers five read tools on Model Hub (
topic-map.collections,search,neighbors,get,read), so Claude Code, Claude Desktop or Codex connected to Model Hub’s MCP server can search your collections, follow a card to other books and read its passage. Needs Model Hub’s API 0.6. An API for other plugins (0.1.0): collections, search and reading, estimates, starting and watching an index run, a quote check, making a collection for a set of books, and Undo by run. - The Topic Map panel, in the right sidebar: a collection’s size, cards by facet and by document; its topics, with each topic’s facets, documents, disagreements and misfits; and its runs with cost and Undo. Commands, grouped: every command sits under an area (Collection, Use, This topic, Lenses, Topic Map), with a grouped palette (Commands…) and right-click entries on collection and topic notes. The Open jobs palette command is now the panel’s Runs tab (Settings → Collections keeps its Open jobs button).
- How big a collection can be. The Index dialog says, before you index, when a collection will be large (Find topics' and search's time, its size on disk, memory) with measured numbers; a collection's dialog says the same of its index. A collection too large to hold in memory is refused by Search and Find topics, with the reason. Suggest a split… proposes parts from the collection's subfolders, nested tags, or a property's values, writes them as new collections whose indexes start with what was already read, and is undone whole.
- Memory limits follow your computer. "Too large to search" now judges the card vectors against your computer's RAM (large past 1/32 of it, too large past 1/10) and the passages and cards against a fixed ceiling, and says which; when the RAM can't be read, 8 GB is assumed and said. The memory Find topics takes while it runs (the vectors and their decorrelated copy) is counted too, and said when it is more than the computer can spare.
- Keep up to date: a switch per collection that indexes what changed on its own, off by default, within a daily spend limit set in Setup. Shelves are compared every half hour; notes and Bases follow the vault's changes.
- Cheaper, Balanced or Better for a run: one pick on the Index dialog that asks OpenRouter for its lowest-priced or its fastest provider, and for Better reads passages one tier up; the dialog says what applies when the reading task's models don't go through OpenRouter. Model Hub's settings are untouched.
- Where things act: Search… and Draft… in the collection's dialog, Preview passages… inside the Index dialog, Open jobs on the Collections tab. The commands are in the palette, grouped by area.
- Each collection's row carries an icon for its kind of source: books, notes or a Base.
- A collection's row and dialog say how much its index takes on disk.
- Setup says when Obsidian's own update check has found a newer Model Hub or Library Hub (plugins from the community directory).
- Setup: Convert AZW3 and MOBI books, Ask each time or Never, in place of a question before each run.
- Each index run on the Collections tab shows what it cost, beside when it ran, and whether it was Cheaper or Better; the run log records both.
- Lenses: the built-in
nonfictionandfictionlenses as Model Hub skills; Customize this lens… makes your own thatextendsone; Check my lenses names each problem with its line and rewrites an older format on request. - Collections from Library Hub books or shelves, a folder or tag of notes, or a Base view; Preview a collection's passages shows the passages and what is left out, writing nothing.
- Index a collection…: a dry run first, then a cancellable job with progress, cost so far and a spend limit; a passage is extracted again only when its prompt changes.
- Survey a collection…: proposes the collection's context and book fields with a quote behind each, written only on Write.
- Open search: cards by facet with filters from the collection's fields, the passage behind a card, its neighbors in other books and its disagreements.
- Find topics in a collection…: two-level clustering, named topics and seeds as notes, Graph view color groups per family, and Open local graph on this topic.
- Draft a write-up…: cited cards, sections from the lens's
SKILL.md, every quote checked against its passage. - Every write is a dry run first, with a run log and Undo a run….
- Requires Model Hub (API 0.9); registers its model roles (
topic-map.extract,.split,.name,.survey,.write,.embed) on built-in Hub tiers, again whenever Model Hub reloads. Models… in settings opens Model Hub’s role editor, where New tier… makes a tier of your own. - Library Hub is optional: book collections need it, and settings say so plainly when it isn’t there.
- Settings: the collection notes, topic notes and drafts folders; a status panel for Model Hub, Library Hub, Calibre’s Content Server (through Library Hub) and the folders.
- Settings in four tabs: Collections (with New collection… and each collection's runs), Lenses, Models and Setup.
- Guide pages for every task, in
docs/guide/and on the docs site; the guide links in settings open them.
Fixed
- The library index keeps its spend limit.
startLibraryIndexrefuses a run it can't price (an embedding model with no listed price) withspend-cap, asstartIndexdoes. - Words opens readable in a small pane. In a narrow or short pane, Words opened on the whole field with the family names too small to read and no topic names at all. Now a pane too small for that opens on the middle of the field with every family name there readable and the biggest topics showing; zoom out to see the whole field, and 0 comes back to this view. A pane big enough for the whole field opens as before.
- Words zooms smoothly from the fit. Zooming in from the whole field had slowed below 50 frames a second at a full-size pane, because each step of the zoom redrew many words. Words now changes only what changed, and brings words in and steps their fades every 200 ms during a zoom (it was 120 ms), so the zoom keeps above 50 frames a second. What the field looks like is the same.
- A naming reply with no name is no longer silent. When a topic or family came back from the model with a description but no name, it was left called "unnamed cluster" and the run said nothing. Now the reply is asked for once more; if it still has no name, the run reports a failed naming ("the reply had no name"). A name kept from an earlier run that is empty or "unnamed cluster" is asked for again at the next Find topics run while every other kept name is reused, so topics left unnamed by earlier runs get named without paying for the rest.
- On a large collection, Find topics could lose its card vectors partway through: the helper that holds them stopped after five idle minutes while the run was busy elsewhere. It now waits while any job runs, and stops five minutes after the last one ends.
- Topic Map's tools no longer repeat what they were asked in a refusal, since refusals reach Model Hub's tool-call log, which keeps the arguments only as a hash.
topic-map.searchchecksbooklikek. No undo is registered with Model Hub while every tool only reads. - The Index dialog, opened from the palette while the collection has a run going, says so instead of running a dry run under it.
- The API's index estimate is $0 when there is nothing to read, so
startIndexisn't refused for a model with no listed price. - Topics: splitting a merge puts the family back in its place and keeps the cards a later merge brought; answering an overlap measures the closest pair and the largest families again;
topics.mdmarks only the pair that merged, and says when you chose it; the newest of two contradicting answers wins; a pinned family's topics follow the run's random seed;topics.jsonwrites the engine’s unset keys as null. - Keep up to date compares a shelf's members again after a minute, then with a growing wait, when Calibre couldn't answer at start; before, the first comparison waited for the half-hour check.
- Keep up to date says in a notice when an automatic run couldn't start (Model Hub off, a collection note that no longer reads as one), with the cause and the way out, once per cause. Before, only the developer console knew.
- A run in progress now shows on its collection's row and in the collection's dialog, with Cancel, after the job dialog is closed. Before, the only trace was Open jobs.
- Books that couldn't be split into passages are named at the top of the dry run and in the collection's dialog, each with its reason and where the fix is. Before, the only sign was a line in the end-of-run report.
- The dry run said "3 books to split, 2 passages to read" as if that were the whole run. It now says that the passages of books not split yet are counted once they are, so the number to read will grow.
- After Index, Find topics or Survey, a collection's row on the Collections tab kept its old state until settings were closed and opened again. The tab now draws again when a job ends.
- A collection's row on the Collections tab said when it last ran ("Indexed today") even when every passage had failed. It now says whether the index is Up to date (a green dot: an index run would do nothing), or what a run would still do ("2 books to split · 153 passages to read"), or Not indexed yet (red), from a dry run made when the tab opens.
- The Index dialog ended with a grayed-out action button and Close above the report, so there seemed to be nothing to click. When the job ends, the row is one Done button; the spend limit is disabled once the run starts. A run that fails or is canceled now clears the dry run's fold, its Preview button, the quality pick and the spend limit too, as a finished run does.
- Setup's Calibre row now says before a run when the Content Server is on but refuses changes (so AZW3 and MOBI books can't be converted and an index leaves them out), with where in Calibre to allow them, through Library Hub 0.2's
calibreChecks. Before, the only sign was a line in the run's report. - Indexing failed on every passage with "The model’s reply was not JSON twice in a row" when the
quicktier held a reasoning model: the model spent the reply cap thinking. The extract, split, name and survey roles now ask for reasoning off, as the engine's tasks did.
Changed
- Find topics is much faster. Its clustering now runs in the same compiled engine as search, in each of its helpers: about five times as fast on a large collection, on top of the change below. The results are the same on every computer. Because the arithmetic changed slightly, the next Find topics may move a few borderline cards to a neighboring topic, once; after that, runs on the same cards give the same topics again.
- Find topics is about twice as fast and leaves Obsidian's window lighter. Its clustering helpers now take the card vectors straight from the helper that holds them for search, so the vectors no longer pass through Obsidian's window. The topics come out exactly as before.
- Vectors can't mix. A collection's card vectors are kept in files named for the embedding model, its dimensions and the lens's search instruction, so changing any of them starts new files instead of adding vectors that can't be compared to the old ones. Search says when a collection's vectors were made with another model or instruction, and that indexing again fixes it. Cards are sent to Model Hub as passages and questions as queries, so Model Hub gives each embedding model the form it expects; for Qwen3 the vectors are the same as before. An index run says when one file's vectors came from more than one provider. Collections indexed before keep their files and their old way of sending cards and questions, so nothing has to be embedded again. Needs Model Hub's API 0.9.
- The Index dialog shows the counts, what the run would do and the cost first, with how it works under a fold; when the run ends, a short summary with the full report under a fold and one Done button.
- Documents are split into passages; nothing is "cut" any more in what you read. The command is Preview a collection's passages; a book without passages says so and why.
- Import an engine index… is gone: it moved the author's indexes over from the Python engine and has no use for anyone else.
- The Index dialog, the run summaries and the failure lines say passages ("Read 163 passages into cards"), as the guide does. Saved data keeps its
unitsfiles. - "Corpus" reads as "collection" and "reader" as "lens" wherever you see them. Saved data keeps its names, so a collection note's lens is still its
readerproperty.
Each released version is also a GitHub release with the same notes. What is planned next: the roadmap.