#obsidian-vault #knowledge-graph #obsidian #parser

obsidian-parser

Blazingly fast Obsidian vault parser with graph analysis

24 releases (8 breaking)

Uses new Rust 2024

new 0.9.4 Mar 28, 2026
0.9.3 Dec 10, 2025
0.8.0 Nov 22, 2025
0.3.2 Jul 31, 2025

#578 in Parser implementations

MIT license

140KB
3K SLoC

obsidian-parser

License: MIT Crates.io Docs.rs Rust

Blazingly fast Rust library for parsing and analyzing Obsidian vaults.

Features

  • โšก High Performance: Parses 1000+ notes in under 3ms
  • ๐Ÿ›ก๏ธ 100% Safe Rust - Strictly forbids unsafe code (#![forbid(unsafe_code)])
  • ๐Ÿง  Knowledge Graphs: Built-in integration with petgraph for advanced analysis
  • ๐Ÿงฉ Flexible API: Supports both in-memory and on-disk note representations
  • ๐Ÿ” Frontmatter Parsing: Extract YAML properties with serde compatibility
  • ๐ŸŒ Link Analysis: Identify connections between notes
  • ๐Ÿ‘พ WebAssembly Support: Add obsidian-parser to your Obsidian plugins

Quick Start

Add to Cargo.toml:

[dependencies]
obsidian-parser = "0.9"

Basic Usage

  • Basic Parsing
use obsidian_parser::prelude::*;
use serde::Deserialize;

// Parse single file with `HashMap`
let note_hashmap = NoteInMemory::from_file_default("note.md").unwrap();
println!("Content: {}", note_hashmap.content().unwrap());
println!("Properties: {:#?}", note_hashmap.properties().unwrap().unwrap());
println!("Tags: {:?}", note_hashmap.tags().unwrap());

// Parse single file with custom struct
#[derive(Clone, Deserialize)]
struct NoteProperties {
    created: String,
    tags: Vec<String>,
    priority: u8,
}
let note_with_serde: NoteInMemory<NoteProperties> = NoteInMemory::from_file("note.md").unwrap();
  • Vault Analysis
use obsidian_parser::prelude::*;

// Load entire vault
let options = VaultOptions::new("/path/to/vault");
let vault: VaultInMemory = VaultBuilder::new(&options)
    .into_iter()
    .filter_map(Result::ok)
    .build_vault(&options)
    .unwrap();

// Check for duplicate note names
if !vault.have_duplicates_notes_by_name() {
    eprintln!("Duplicate note names detected!");
}

// Access parsed notes
for note in vault.notes() {
  println!("Note: {:?}", note);
}
  • Graph Analysis (requires petgraph feature)
#[cfg(feature = "petgraph")]
{
    use obsidian_parser::prelude::*;
    use petgraph::dot::{Dot, Config};
    let options = VaultOptions::new("/path/to/vault");
    let vault: VaultInMemory = VaultBuilder::new(&options)
        .into_iter()
        .filter_map(Result::ok)
        .build_vault(&options)
        .unwrap();
    let graph = vault.get_digraph().unwrap();
    
    // Export to Graphviz format
    println!("{:?}", Dot::with_config(&graph, &[Config::EdgeNoLabel]));
    
    // Find most connected note
    let most_connected = graph.node_indices()
        .max_by_key(|n| graph.edges(*n).count())
        .unwrap();
    println!("Knowledge hub: {:?}", graph[most_connected]);
}

Example: Analyze Knowledge Connectivity

Included example analyzer calculates connected components in your Obsidian vault's knowledge graph:

cargo run --example analyzer --release --features="petgraph rayon" -- --path="Path to Obsidian vault"

Performance

My PC AMD Ryzen 5 3600X with NVMe SSD

Operation Time
Vault initialization 739.35 ยตs
Graph construction 1.22 ms
Peak memory usage 900 KiB

License

MIT ยฉ CryptoGladi

Dependencies

~2.2โ€“7.5MB
~120K SLoC