A 100% Rust implementation of the Mermaid diagram parser and renderer.
Try it in your browser: btucker.github.io/selkie
Selkie aims to provide a fast, native alternative to Mermaid.js for parsing and rendering diagrams. The entire implementation is written in Rust, with no JavaScript dependencies at runtime.
This project has been built entirely with coding agents, mostly Claude Code. Development is guided by an evaluation system that compares Selkie's output against the reference Mermaid.js implementation, providing automated feedback on structural and visual parity. The eval system serves as the primary guidance mechanism—agents run selkie eval to see prioritized issues, investigate differences by comparing generated SVGs against reference implementations, and verify that changes improve scores without introducing regressions. This creates a tight feedback loop where the agent can autonomously identify what needs work and measure its progress.
Selkie provides significant performance improvements over mermaid-js in both CLI and browser environments.
Compared to mermaid-cli (mmdc):
| Diagram | mmdc | Selkie |
|---|---|---|
| Simple flowchart (5 nodes) | 1.53s | 6ms |
| Medium flowchart (15 nodes) | 1.54s | 7ms |
| Sequence diagram (4 actors) | 1.52s | 5ms |
| Class diagram (5 classes) | 1.55s | 5ms |
| Large flowchart (100 nodes) | 1.82s | 27ms |
CLI-to-CLI comparison. Median of 5 runs after 2 warmup runs.
The dramatic speedup comes from avoiding the browser entirely—mermaid-cli spawns Puppeteer + Chromium for each render.
For client-side rendering, Selkie compiles to WebAssembly. Both run in the same Chromium browser for a fair comparison. Run it yourself →
| Diagram | Mermaid.js | Selkie WASM |
|---|---|---|
| Simple flowchart (5 nodes) | 10ms | 1ms |
| Medium flowchart (15 nodes) | 21ms | 1.6ms |
| Sequence diagram (4 actors) | 4.5ms | 0.3ms |
| Class diagram (5 classes) | 16ms | 0.5ms |
| State diagram (8 states) | 22ms | 0.75ms |
| Pie chart (5 slices) | 1.6ms | 0.1ms |
Median of 10 runs after 2 warmup runs. Chromium via Playwright.
Bundle Size:
| Uncompressed | Gzipped | |
|---|---|---|
| Selkie (WASM + JS) | ~3.0 MB | ~725 KB |
| Mermaid.js | ~2.6 MB | ~770 KB |
Selkie could not exist without all the human effort that has gone into these excellent projects:
- Mermaid - The original JavaScript diagramming library that defines the syntax and rendering we aim to match
- Dagre - Graph layout algorithms that inspire our layout engine
- ELK - Eclipse Layout Kernel, providing additional layout strategies
Selkie supports parsing and rendering for all major Mermaid diagram types.
| Type | Example |
|---|---|
| Flowchart | |
| Sequence | |
| Class | |
| State | |
| ER | |
| Gantt | |
| Pie | |
| Architecture | |
| Git Graph | |
| Requirement | |
| Quadrant | |
| Mindmap | |
| Timeline | |
| Sankey | |
| XY Chart | |
| C4 | |
| Journey | |
| Radar | |
| Block | |
| Packet | |
| Treemap | |
| Kanban |
cargo install selkie-rsOr build from source:
git clone https://github.com/btucker/selkie
cd selkie
cargo build --release# Render a diagram to SVG
selkie render -i diagram.mmd -o output.svg
# Shorthand (implicit render command)
selkie -i diagram.mmd -o output.svg
# Read from stdin, write to stdout
cat diagram.mmd | selkie -i - -o -
# Use a specific theme
selkie -i diagram.mmd -o output.svg --theme dark
# Output to PNG (requires 'png' feature)
selkie -i diagram.mmd -o output.pngSelkie includes a built-in evaluation system that compares output against Mermaid.js. See EVAL.md for detailed documentation.
# Run evaluation with built-in samples
selkie eval
# Evaluate specific diagram types
selkie eval --type flowchart
# Output to custom directory
selkie eval -o ./reports
# Show detailed per-diagram diffs
selkie eval --verboseThe eval system generates an HTML report with:
- Structural comparison - Node/edge counts, labels, connections
- Visual similarity - SSIM-based image comparison
- Side-by-side PNGs - Selkie output next to Mermaid.js reference
Requires Mermaid CLI for reference rendering (npm install -g @mermaid-js/mermaid-cli).
use selkie::{parse, render};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let diagram_source = r#"
flowchart LR
A[Start] --> B{Decision}
B -->|Yes| C[OK]
B -->|No| D[Cancel]
"#;
let diagram = parse(diagram_source)?;
let svg = render(&diagram)?;
println!("{}", svg);
Ok(())
}Selkie can be compiled to WebAssembly for client-side rendering in the browser. The WASM entrypoint mirrors the mermaid-js API (initialize, parse, and render) and also exposes render_text for a minimal wrapper.
# Build the WASM package (requires wasm-bindgen / wasm-pack)
wasm-pack build --target web --features wasmimport init, { initialize, parse, render } from "./pkg/selkie.js";
await init();
initialize({ startOnLoad: false });
parse(`flowchart TD; A-->B;`);
const { svg } = render("diagram1", `flowchart TD; A-->B;`);
document.body.innerHTML = svg;Selkie uses Cargo feature flags to enable optional functionality. This keeps the core library lightweight while allowing additional capabilities when needed.
| Feature | Description | Dependencies |
|---|---|---|
cli |
Command line interface | clap |
The CLI is enabled by default. To build only the library without CLI:
cargo build --release --no-default-featuresSVG output is always available with no additional dependencies:
selkie -i diagram.mmd -o output.svgAdditional output formats require feature flags:
| Feature | Format | Dependencies |
|---|---|---|
| (none) | SVG | (built-in) |
png |
PNG | resvg |
pdf |
svg2pdf, resvg | |
kitty |
Terminal inline | resvg, image, base64, libc, atty |
wasm |
WebAssembly bindings | wasm-bindgen |
all-formats |
All of the above | All of the above |
# Build with PNG support
cargo build --release --features png
# Build with all output formats
cargo build --release --features all-formats
# Install with PDF support
cargo install selkie-rs --features pdf
# Library only (no CLI, minimal dependencies)
cargo build --release --no-default-featuresProvides the selkie command-line binary with subcommands for rendering and evaluation. Without this feature, only the library is built.
Enables PNG output via the resvg crate, a high-quality SVG rendering library. Use with:
selkie -i diagram.mmd -o output.pngEnables PDF output via svg2pdf. Useful for generating print-ready documents:
selkie -i diagram.mmd -o output.pdfEnables inline image display in terminals that support the Kitty graphics protocol (Kitty, Ghostty, WezTerm). When enabled, diagrams can be rendered directly in the terminal:
selkie -i diagram.mmd # Displays inline if terminal supports itEnables WebAssembly bindings for browser usage. Build with:
wasm-pack build --target web --features wasmConvenience feature that enables png, pdf, and kitty together. Best for development or when you need maximum flexibility:
cargo install selkie-rs --features all-formatsThis project uses Microbeads for issue tracking - an AI-native issue tracker that lives directly in the repository. Issues are stored in .beads/ and sync with git, making them accessible to both humans and AI coding agents.
# View available work
mb ready
# View issue details
mb show <issue-id>
# Update issue status
mb update <issue-id> --status in_progress
mb close <issue-id>
# Sync with remote
mb syncThis project follows test-driven development. Run the test suite:
cargo testRun the evaluation to check parity with Mermaid.js:
cargo run -- evalMIT License - see LICENSE for details.
