by laptapk
Generate linked Rust API documentation as Markdown from local Cargo projects.
Rustdocs for Obsidian
Rustdocs is a desktop-only Obsidian plugin that turns one or more local Cargo projects into linked, searchable Markdown API documentation. It reads Cargo workspace metadata and nightly rustdoc JSON, then creates package/module indexes and individual pages for Rust API items.
AI development disclaimer
This project was developed entirely using AI coding agents, with human direction. Its implementation, tests, and documentation were AI-generated. Passing tests do not guarantee correctness or security. Review the code, back up your vault, and try the plugin in a test vault before relying on it with important notes.
What it generates
- One workspace index and one index per crate/module.
- Separate pages for structs, enums, unions, traits, functions, type aliases, constants, statics, declarative/procedural macros, primitives, and trait aliases.
- Signatures, documentation comments, fields, variants, impls, methods, intra-doc relationships, and source locations when rustdoc exposes them.
- Stable block-targeted Markdown links, YAML frontmatter, and deterministic collision-safe filenames.
Filenames preserve Rust names: Client.md, State.md, default_client.md, and MAX_PEERS.md. Type suffixes appear only for naming collisions, such as parse (function).md and parse (macro).md. Modules keep their folder and index.md.
After updating from the old client--struct.md naming scheme, generate again to replace managed pages and refresh generated links. Old unedited generated pages go to the vault trash; edited pages remain protected. Links from your own notes to old filenames may need updating.
Every managed note contains a generated marker. A .rustdocs-manifest.json file records ownership and content hashes. Rustdocs checks all conflicts before changing files, preserves manually edited notes, and refuses to share an output folder between different profiles. Stale notes go to the vault trash. An interrupted generation can be retried using the ownership journal.
Requirements
- Obsidian Desktop 1.8 or newer. Mobile is intentionally unsupported because Cargo must run as a local process.
cargoavailable on thePATHinherited by Obsidian.- Nightly Rust, because rustdoc JSON remains experimental.
For rustup installations:
rustup toolchain install nightly-2026-09-12
Keep the profile’s Rustup toolchain value set to nightly-2026-09-12. If cargo itself is the pinned Nix nightly from this repository, leave the field blank so no rustup +toolchain selector is added.
New profiles automatically use direct Cargo when Obsidian inherits this repository's Nix shell environment.
Install
Until this plugin is published in the Obsidian community catalog:
- Download or build the release bundle.
- Copy
main.js,manifest.json,versions.json, andstyles.cssinto<vault>/.obsidian/plugins/rustdocs/. - Restart Obsidian and enable Rustdocs under Community plugins.
Build a local bundle with npm run package; files are written to dist/rustdocs/.
Use
- Open Settings → Rustdocs → Manage projects.
- Add a name, absolute Cargo project/workspace path, and vault-relative output folder.
- Optionally select packages, a target, features, private items, and a default profile.
- Click the book ribbon icon. With one/default profile it runs immediately; otherwise choose a project.
Commands are also available for choosing a project, managing profiles, and cancelling an active run. Generation progress appears in a modal. On success, Rustdocs can open the generated workspace index automatically.
Do not put hand-written notes inside a generated subtree under filenames that Rustdocs needs. Separate profiles must use separate output folders.
Source navigation
Every item with a rustdoc span has a visible Source reference, including fields, variants, impls, and associated items. References show src/lib.rs:42 or src/lib.rs:42-67; page frontmatter also records the original filename and start/end lines. Existing source files inside the vault become clickable vault links. Outside, missing, or compiler-remapped files remain textual locations; no source files are copied or modified.
Generated navigation targets deterministic Obsidian blocks (file.md#^item-…). Item and Source block IDs derive from the package, Rust path, and item kind, not rustdoc's transient numeric IDs or source line numbers. Associated items include their impl context. Rebuilding unchanged sources produces identical Markdown; moving an item to different source lines does not change its navigation IDs.
Source links open the file, while the adjacent range identifies the Rust lines; they do not pretend to jump to a Markdown line. For .rs files, Obsidian may use the system's default app; enable Files and links → Detect all file extensions if needed. Block IDs are added only to generated Markdown. See Obsidian's internal-link syntax.
Nix development
flake.nix and flake.lock define the canonical toolchain. No global Node or Rust installation is required:
nix develop
npm ci
npm run check
npm run package
nix flake check
nix build
The shell pins Node, npm, nightly Rust, Cargo, rustfmt, Clippy, rust-src, Git, jq, and cargo-deny. Integration tests run actual rustdoc JSON generation when RUSTDOCS_DIRECT_TOOLCHAIN=1, which the Nix shell sets.
For an Obsidian smoke test, run npm run package, install the resulting folder in a test vault, configure both tests/fixtures/basic and tests/fixtures/workspace, and generate each profile. Verify the indexes, item links, and stale-page cleanup after renaming an item.
To check source navigation, place a fixture project inside the test vault. Verify its Source links resolve to .rs files and its generated #^item-… / #^source-… targets appear in Obsidian's block picker. Generate twice and compare the Markdown byte-for-byte (only the ownership manifest timestamp may differ).
Troubleshooting
- Cargo not found: launch Obsidian from an environment where
cargois onPATH. - Toolchain/unstable option error: install
nightly-2026-09-12and select it in the profile, or enternix developand leave that field blank. - No targets: select a package with a library or binary target, and verify any configured target name.
- Refusing to change a note: move edited notes outside the generated subtree before retrying. Copying the generated marker alone does not establish ownership. Keep the ownership manifest so future runs can update the remaining pages.
- Dependency/build failure: run the matching
cargo rustdoccommand in the project to resolve native dependencies or feature errors, then retry.
Rustdoc JSON’s schema is unstable. This project pins nightly 2026-09-12 and accepts JSON format 61. Other formats fail with a toolchain hint before any vault writes. Output paths cannot traverse hidden folders or symbolic links.
Contributing and security
See CONTRIBUTING.md, SECURITY.md, and docs/architecture.md. Rustdocs is available under the MIT license.
For plugin developers
Search results and similarity scores are powered by semantic analysis of your plugin's README. If your plugin isn't appearing for searches you'd expect, try updating your README to clearly describe your plugin's purpose, features, and use cases.