PlantUML diagrams. No Java. Native speed.
puml is a fast, offline-first PlantUML-compatible diagram renderer written in Rust.
Give it a .puml file and get a pixel-perfect SVG, PNG, or PDF out — no Java, no Node,
no network. It ships as a single static binary, a WebAssembly module for in-browser
editing, and a Language Server (LSP) for editor integration across 25+ diagram families.
How it works — pipeline architecture
A request enters via one of three transports (CLI, LSP, WASM), passes through the preprocessor + language service, hits the pipeline core (parser → AST → normalizer → renderer), and exits as SVG / PNG / Text. The renderer is the only component that knows about each diagram family's visual conventions; everything upstream is family-agnostic AST.
|
Sequence |
Class |
MindMap |
|
Gantt |
C4 Container |
Component |
Browse all 25+ diagram families in the examples gallery →
# 1. Install (see all install options below)
cargo install puml --bin puml
# 2. Write a diagram
cat > hello.puml <<'EOF'
@startuml
Alice -> Bob: Hello
Bob --> Alice: Ack
@enduml
EOF
# 3. Render
puml hello.puml # writes hello.svg
puml --format png hello.puml # writes hello.png
puml --check hello.puml # lint without writingOpen hello.svg in any browser or SVG viewer. Done.
Install options (curl installer, Cargo, binary, Homebrew, npm, Docker)
curl -fsSL https://raw.githubusercontent.com/alliecatowo/puml/main/scripts/install.sh | shThe installer:
- Auto-detects your platform (Linux x86-64/arm64, macOS Apple Silicon/Intel)
- Downloads the signed release tarball over HTTPS
- Verifies the SHA-256 checksum against the release's
SHA256SUMSfile - Verifies the cosign keyless signature when
cosignis on yourPATH - Installs to
/usr/local/bin/puml(or~/.local/bin/pumlwhen/usr/local/binis not writable) - Runs
puml --versionas a self-test
The installer never executes the downloaded binary during the install step.
Options:
# Install a specific version
curl -fsSL .../install.sh | sh -s -- --version v0.2.1
# Install to a custom prefix
curl -fsSL .../install.sh | sh -s -- --prefix ~/.local
# Preview what would happen (no download, no install)
curl -fsSL .../install.sh | sh -s -- --dry-run
# Skip cosign (SHA-256 is always checked)
curl -fsSL .../install.sh | sh -s -- --no-verify-sigSee the install guide for manual download steps and checksum verification instructions.
Download the latest release for your platform from the Releases page:
| Platform | Archive | LSP Archive |
|---|---|---|
| Linux x86-64 | puml-x86_64-unknown-linux-musl.tar.gz |
puml-lsp-x86_64-unknown-linux-musl.tar.gz |
| Linux arm64 | puml-aarch64-unknown-linux-musl.tar.gz |
puml-lsp-aarch64-unknown-linux-musl.tar.gz |
| macOS (Apple Silicon) | puml-aarch64-apple-darwin.tar.gz |
puml-lsp-aarch64-apple-darwin.tar.gz |
| macOS (Intel) | puml-x86_64-apple-darwin.tar.gz |
puml-lsp-x86_64-apple-darwin.tar.gz |
| Windows x86-64 | puml-x86_64-pc-windows-msvc.zip |
puml-lsp-x86_64-pc-windows-msvc.zip |
Each release also includes a SHA256SUMS file and per-archive .cosign.bundle files
for supply-chain verification.
Extract and place the puml binary on your $PATH.
brew install alliecatowo/tap/pumlnpx puml-cli hello.puml # one-off, no install needed
npm install -g puml-cli # global installdocker run --rm -v "$PWD":/work ghcr.io/alliecatowo/puml:latest hello.pumlcargo install puml --bin pumlgit clone https://github.com/alliecatowo/puml.git
cd puml
cargo build --release
./target/release/puml hello.pumlSee the full install guide for proxy settings, checksum verification, and platform-specific notes.
Why puml — not PlantUML or Mermaid?
| PlantUML | Mermaid | puml | |
|---|---|---|---|
| Runtime | JVM required | Node + browser | Single static Rust binary |
| Offline | Yes (with Java installed) | No (needs browser) | Yes, always |
| Output | SVG, PNG, PDF | SVG (browser-rendered) | SVG, PNG, JPG, WebP, HTML |
| Determinism | Varies by JVM version | Varies by browser | Deterministic across platforms |
| CLI | Yes | Limited | Yes — designed as a compiler tool |
| LSP / editor | Third-party | Third-party | Built-in (puml-lsp) |
| WASM | No | Yes | Yes (crates/puml-wasm) |
PlantUML is the gold standard for feature breadth. Use it if you need full parity today and can accept the JVM dependency.
Mermaid is great for quick diagrams embedded in GitHub Markdown and wikis. It needs a browser runtime to render and does not produce diff-friendly offline artifacts.
puml is for teams that want diagrams in source control, reviewed as text, rendered offline, and wired into CI and editors without installing Java or Node.
What diagram families are supported?
Around 25 families:
- UML — sequence, class, object, use case, component, deployment, state, activity, timing
- Planning — Gantt, chronology, WBS, MindMap
- Structured data — JSON, YAML, EBNF, regex, math, Salt wireframes
- Architecture — C4-style, Archimate, nwdiag
- Other — SDL, ditaa, chart
PicoUML is the project's own ergonomic dialect — a smaller, cleaner superset of PlantUML syntax that is easier to write, diff, validate, and repair. Mermaid sequence and flowchart inputs are also accepted via an adapter into the same renderer.
Browse the examples gallery for rendered output from every family.
CLI, LSP, WASM, and VS Code details
# Render
puml hello.puml # → hello.svg
puml --format png --dpi 192 hello.puml # → hello.png at 2x
puml --format html hello.puml # → hello.html (self-contained)
# Live re-render on save (pure polling, no extra dependencies)
puml --watch hello.puml # re-renders hello.svg on every mtime change
puml --watch hello.puml -o out.svg # explicit output path
# Lint
puml --check hello.puml # exit 0 = valid
puml --from-markdown --check notes.md # lint all fenced puml blocks in a Markdown file
# Preprocessor dump
puml --preproc hello.puml # print source after !include / macro expansion
# Count nodes and edges
puml count hello.puml # → "4 nodes, 3 edges"
puml count --by-kind hello.puml # → summary + per-kind breakdown
# Structural stats
puml stats hello.puml # AST node/edge/kind summary
puml stats --format json hello.puml # machine-readable summary
# Raw content hash
puml hash hello.puml # deterministic FNV-1a raw-byte hash
puml hash --format base64 hello.puml # base64-encoded hash bytes
# Pipeline inspection (for debugging and tooling)
puml --dump ast hello.puml
puml --dump model hello.puml
puml --dump scene hello.puml
# Environment inspection — show PUML-related env vars and their resolved values
puml env # human-readable table
puml env --format json # machine-readable JSON (useful in CI scripts)Full flag reference, dialect options, and exit codes: CLI reference
puml-lsp ships in this repo. It provides diagnostics, hover, completions, and semantic
tokens for any editor that speaks the Language Server Protocol (Neovim, Emacs, Helix,
Zed, and others via generic LSP config).
cargo install --git https://github.com/alliecatowo/puml --bin puml-lspPoint your editor's LSP config at puml-lsp for .puml and .picouml files.
The renderer compiles to WebAssembly via crates/puml-wasm. The live browser editor at
alliecatowo.github.io/puml/editor runs the
full pipeline client-side with no server.
A VS Code extension lives under extensions/vscode/ in this repo. It wraps puml-lsp
and adds preview, syntax highlighting, and snippet support. (Screenshot pending —
tracked separately.)
PlantUML compatibility status
puml is PlantUML-compatible — not a claim of complete 1:1 parity. Many diagram
families render well today; some advanced features are partial and tracked openly.
Run puml --check on your files and compare output when pixel-perfect parity matters.
Current compatibility work is tracked through focused GitHub issues, executable
fixtures, and the roadmap in docs/parity-roadmap.md.
Project status and roadmap
puml is at v0.1.0 — young, ambitious, and developed with significant AI assistance.
Baseline rendering across all major diagram families landed in the parity blitz
(May 2025); advanced feature depth is an ongoing effort.
Active epics:
- #88 — Oracle conformance suite
- #89 — CI hardening
- #399 — Language service
- #590 — Renderer architecture and layout
See the GitHub milestone view for what is planned next.
How it works
puml is structured as a three-layer pipeline:
- Frontends — PlantUML, PicoUML, and a Mermaid adapter translate source text into a shared internal format.
- Pipeline core — the preprocessor resolves
!includedirectives and macros; the winnow-based parser produces a span-annotated AST; the normalizer detects the diagram family and builds a canonical model; the renderer emits deterministic SVG. - Transports — the CLI binary,
puml-lsp, andpuml-wasmall drive the same pipeline. Thelanguage_servicemodule provides hover, completion, semantic tokens, and diagnostics uniformly across all three surfaces.
Full breakdown with sequence, lifecycle, class, and parity diagrams: docs/architecture.md
Development setup
Prerequisites: Rust 1.78+ stable — rustup.rs
git clone https://github.com/alliecatowo/puml.git
cd puml
# Build
cargo build --release
# Lint + test (required before any commit to main)
cargo fmt
cargo clippy --all-targets --all-features -- -D warnings
cargo test --release
# Render a diagram
./target/release/puml docs/examples/sequence/01_basic.puml -o /tmp/out.svg
# Regenerate the full PNG audit corpus (for visual QA)
python3 scripts/render_corpus.py --force
# Quick harness check
./scripts/harness-check.sh --quickRead CONTRIBUTING.md for the full workflow, branch naming, commit format, and CI gate requirements.
- Install guide
- Quickstart
- CLI reference
- Comparison vs PlantUML / Mermaid
- FAQ
- CI integration
- Troubleshooting
- Examples gallery
- Architecture
Open a GitHub issue for bugs, compatibility gaps, or feature requests. Use Discussions for questions and ideas. Renderer fixes, fixture additions, and documentation improvements are especially welcome. Read CONTRIBUTING.md before larger changes.
Contributing · Code of Conduct · Security · MIT License