Breadcrumbs is an Obsidian plugin that lets you add typed links to your notes, then view/traverse them in various ways. Internally, Breadcrumbs uses a graph to represent this structure (much like the regular Obsidian graph, except now, links have types to them). You tell Breadcrumbs about the structure of your notes, then it lets you visualise and navigate the graph.
As of May 2026, Breadcrumbs is maintained by michaelpporter. The plugin was originally created by SkepticMystic, whose foundational work made this all possible. Development continues at github.com/michaelpporter/breadcrumbs.
Breadcrumbs 4.13.0 is fully compatible with Obsidian 1.13. The settings tab uses the new declarative settings API — all sections appear in global settings search and support page-based navigation. The existing display() fallback remains for older Obsidian versions (minAppVersion stays 1.12.3).
Want to see Breadcrumbs in action before configuring your own vault? The Breadcrumbs Demo Vault is a ready-to-open vault with pre-configured edge fields, example notes, and working graph structure.
Breadcrumbs has its own docs site!✨ All detailed documentation lives there: https://breadcrumbs-docs.michaelpporter.com
See CONTRIBUTING.md for development setup, build commands, and how to submit a pull request.
If you find Breadcrumbs useful, consider sponsoring continued development:
Original creator SkepticMystic also accepts donations via Ko-fi — their foundational work is what made this plugin possible.
Breadcrumbs is fully open source. This section discloses every network request, binary module, and non-obvious code pattern in the compiled plugin.
Mermaid diagrams — when you open a breadcrumbs codeblock rendered as Mermaid and click the "View Image on mermaid.ink" button, your browser opens https://mermaid.ink/img/<encoded-diagram> in a new tab. This is the only outbound network request the plugin can make. It is user-initiated (button click), not automatic. The diagram text is base64-encoded with btoa() and appended to the URL; no data is sent to any Breadcrumbs server.
No other network requests are made by this plugin. A static scan of the compiled main.js will report fetch( matches inside bundled dependencies; none are reachable network calls:
- KaTeX (math rendering, pulled in transitively) defines a lexer method
Parser.fetch()that returns the next parse token. The name collides with the WebfetchAPI but performs no networking — this accounts for the large majority of the matches. - markmap-view / markmap-lib (used to render
breadcrumbscodeblocks withtype: markmap) bundle a CDN asset loader that canfetchKaTeX/plugin files fromcdn.jsdelivr.net(fallbackunpkg.com). Breadcrumbs does not use that path: it injects markmap's stylesheet inline vialoadCSS([{ type: "style", data: globalCSS }])and never requests remote assets, so the fetch branch is never reached.
The compiled bundle includes one inline WebAssembly binary, wasm/pkg/breadcrumbs_graph_wasm_bg.wasm. This is the Breadcrumbs graph engine, written in Rust and compiled with wasm-pack. The full Rust source is in wasm/src/ and can be audited directly.
The binary is not native machine code — it is portable WebAssembly that runs in the same sandbox as the plugin's JavaScript, with no filesystem, network, or system-call access beyond what JS explicitly passes across the boundary. It is never fetched from a remote URL: esbuild's binary loader embeds the bytes into main.js at build time, and src/main.ts initializes the engine with the inline bytes via init({ module_or_path: wasmbin }).
To verify the binary matches the source, rebuild it from the Rust sources with bun run wasm:build and compare — the .wasm is reproducible from wasm/src/.
wasm-pack generates JavaScript glue code in wasm/pkg/breadcrumbs_graph_wasm.js. Static scanners may flag three patterns in this generated file:
| Pattern | Origin | Purpose |
|---|---|---|
fetch() |
wasm-bindgen shim | Fallback for loading WASM by URL. Never called — the plugin passes the inline binary directly to init({ module_or_path: wasmbin }). |
new Function(...) |
wasm-bindgen shim (__wbg_newnoargs) |
Part of wasm-bindgen's standard generated runtime. It is invoked only with a fixed string compiled into the WASM binary, never with user input, and the plugin's own Rust code never calls it. The plugin does use the js_sys::Function type (update_callback, node_label_fn, iterate_nodes), but only to receive and call back JavaScript functions passed in from the plugin — it never constructs functions from strings. The bundle contains no eval(). |
exported memory / wasm.memory access |
wasm-bindgen shim | The module exports its linear memory and the JS glue reads/writes it to pass strings and arrays between Rust and JavaScript. Required by wasm-bindgen for any non-scalar data transfer across the boundary. |
All of the above are generated automatically by wasm-bindgen and are not written by the plugin authors.
On the exported linear memory specifically: static scanners flag that the WASM module exports its memory. This is unavoidable and standard for every wasm-bindgen module — JavaScript cannot pass a string, Vec, or array to Rust (or read one back) without direct access to the module's linear memory, so wasm-bindgen exports it and the generated glue (getUint8ArrayMemory0, getDataViewMemory0, etc.) copies bytes in and out. It is not a privilege escalation: the JavaScript host instantiates the module and already fully controls it, and the WASM sandbox has no filesystem, network, or system-call access of its own. Exporting memory only lets the two halves of the same plugin exchange data.
- SkepticMystic: Original creator of Breadcrumbs. The plugin concept, architecture, and community were built by them.
- mProjectsCode: For their PRs, insightful suggestions, and efficiency improvements.
- HEmile: For their PRs, and helpful discussions on graph-theory.
- michaelpporter: Current maintainer.
- Push all previous changes to the actual project
- Bump version in
package.json bun run version:betato updatemanifest-beta.jsonandversions.jsonaccordinglygit tag -a x.x.x-beta -m 'x.x.x-beta'to tag the buildgit push origin x.x.x-betato push the release and trigger the action
Or, do steps 3-5 in one go with bun run release:beta
Older media kept for posterity. Many predate v4 and may not match current behavior, but the effort of the authors is appreciated.
- @Rhoadey: How a Hierarchy Note sharpened my thinking in 20 minutes
- Obsidian Hub - Breadcrumbs Quickstart Guide
- Obsidian Hub - Breadcrumbs for Comparative Law
- Obsidian Hub - How to get the most out of Breadcrumbs
- @SkepticMystic: Breadcrumbs - Everything you need to know (Outdated)
- @SkepticMystic: Breadcrumbs - Obsidian Community Showcase (Outdated)
- @Zen Productivist: Threading Mode with the Breadcrumbs Plugin in Obsidian (2022-01-01)