Skip to main content

vizzle

UML visualization for git: parse a codebase (or a git diff) and render UML diagrams — as Mermaid text or as an interactive d3-powered HTML page — with changes highlighted so a reader immediately sees what a change did to the shape of the code. Two diagram types so far: class (the shape of the code) and component (the shape of the application). Each type has a spec in docs/diagram-types/ — what an element is, how it is detected, what its diff means, and the modelling decisions behind it (e.g. why aggregation and composition diamonds are a convention rather than an inference: docs/diagram-types/class.md §5.4).

  • Rust core (crates/vizzle-core): tree-sitter parsing (Python, TypeScript + Rust), a language-neutral class graph + import graph, a component detector (manifest-driven), graph diff engines, and Mermaid renderers. Parses ~200 classes in well under a second.
  • PyO3 bindings (crates/vizzle-py): built with maturin into the private extension module vizzle_cli._core.
  • Click CLI (packages/vizzle-cli): the vizzle command. Python owns the git orchestration; Rust owns everything hot.

Three source layers ship as one wheel — pip install vizzle gets the CLI and the compiled core together, so their versions cannot drift apart.

Install

Nothing to install — run it straight from PyPI, with nothing added to the repo you are looking at:

uvx vizzle component ~/code/some-repo

Or keep it around: uv tool install vizzle (or pipx install vizzle). Needs Python ≥ 3.10 and git on PATH; on Linux, glibc ≥ 2.28. Why it is distributed this way is in docs/distribution.md.

For coding agents

vizzle ships a Claude Code plugin, so an agent knows to reach for a diagram instead of reading the repo file by file — a component diagram of a 358-file codebase costs about 1.5k tokens:

claude plugin marketplace add stiproot/vizzle
claude plugin install vizzle@vizzle-marketplace

From a clone

For development — requires uv and a Rust toolchain:

uv sync   # builds the Rust extension via maturin and installs the CLI

Working from a clone, read uv run vizzle … wherever the examples below say uvx vizzle …, so you exercise your build rather than the published one.

Usage

Full class diagram of a codebase:

uvx vizzle class ~/code/repo/h -o h-classes.mmd

Grouped into namespace blocks — --group-by component for one block per package, --group-by module for one per file:

uvx vizzle class ~/code/repo/h --group-by component --no-members

Component diagram — one box per build-level module (workspace package, app, service; any directory with a package.json/pyproject.toml/Cargo.toml/ go.mod), one dashed arrow per dependency derived from imports (spec: docs/diagram-types/component.md):

uvx vizzle component ~/code/repo/h -o h-components.mmd --weights
uvx vizzle component ~/code/repo/h -o h-components.html   # interactive

In the HTML view each app/package gets a labelled box you can drag as a unit, and every component carries a + toggle that explodes it into a full UML class diagram — boxes with stereotypes, fields and methods, data types on every member, and the association, dependency and inheritance edges between them (or use Show classes to open them all at once). Each explosion is laid out once at load and then only shown or hidden, so toggling stays instant. --no-classes omits that detail for a leaner file.

What changed, as a diagram (added = green ✚, removed = red ✖, modified = yellow ✱; unchanged classes in touched files render as context):

# working tree vs HEAD
uvx vizzle diff ~/code/repo/h

# between two revisions
uvx vizzle diff ~/code/repo/h --base HEAD~20 --head HEAD -o changes.mmd

# did the change rewire the application? (parses both full revisions;
# added/removed dependency edges render loudest)
uvx vizzle diff ~/code/repo/h --type component

# for a script: the verdict as JSON (changed, counts, rendered size), so it
# never has to read the diagram text
uvx vizzle diff ~/code/repo/h --type component -o changes.mmd --stats verdict.json

# make a point: light the classes an explanation is about and dim the rest,
# or keep only a class and its neighbours
uvx vizzle class src --no-members --highlight LaunchRunRequest,TaskAgent
uvx vizzle class src --around TaskAgent --depth 1

# one manifest but many subsystems: split the package into its subpackages,
# focus the diff on the changed ones and their neighbours, and zoom into the
# classes that changed inside them
uvx vizzle diff . --type component --split src/mypkg --focus -o shape.mmd --zoom inside.mmd

Interactive HTML (d3)

Write to a .html file (or pass --format html) and vizzle emits a fully self-contained page — d3 v7 is inlined, no network needed — that renders the class graph as SVG with zoom (scroll), pan (drag the background), draggable class boxes, a fit-to-view button, and a live filter box. Diff pages color whole classes and individual member rows (removed members are struck through). In a component diff, opening a changed component shows only the classes and members that changed, banded in their change colour, with the rest folded behind a count and a link to show them:

uvx vizzle class ~/code/repo/h -o h-classes.html
uvx vizzle diff ~/code/repo/h --base HEAD~20 --head HEAD -o changes.html
open changes.html

Layout is a d3 force simulation (link + charge + rectangle collision) with a weak per-module gravity, ticked synchronously before first paint so the page opens settled. The component view adds a two-level relaxation pass — components separate within their group, then groups separate as blocks — so group boxes never overlap, including after a component is expanded.

Both views are built from one shared core (assets/viz-core.{css,js}, inlined into every page): the palette, geometry, viewport, filter, and header. A template only describes what its own nodes look like.

Comprehension first. Nothing here needs a git diff: vizzle class and vizzle component are for reading unfamiliar code. The diff is a lens laid over the same diagram — under it, unchanged elements fade to neutral context and only what changed keeps saturated color, so the change reads instantly without losing its surroundings.

On a pull request

.github/workflows/pr-diagram.yml posts a component diff as a PR comment, so reviewers see what a change did to the shape of the application without installing anything. GitHub renders ```mermaid blocks natively, so there is no image hosting involved. Copy the file into any repo with Python or TypeScript in it — the only requirement is uvx on the runner.

It edits one comment rather than appending, says so in a single line when nothing structural moved, and skips fork PRs (which get a read-only token) rather than failing them. It deliberately does not use pull_request_target; the reasoning is in docs/distribution.md §2.3.

Live server with hot reload

vizzle serve hosts the diagram and watches the source tree; every save re-parses and pushes a reload to connected browsers (stdlib http.server + server-sent events + watchfiles — no web framework). Your zoom/pan position survives reloads.

uvx vizzle serve ~/code/repo/h                  # live class diagram
uvx vizzle serve ~/code/repo/h --diff --open    # watch your working-tree
                                                # changes vs HEAD reshape
                                                # the UML as you edit
uvx vizzle serve ~/code/repo/h --type component --diff   # live rewiring view

Defaults to http://127.0.0.1:8499/; see --port, --host, --base. The server answers only requests addressed to this machine; --host 0.0.0.0 publishes the repository's structure to the network, and says so.

Useful flags (class and diff): --no-members, --modules (add a «module» box per module holding its public module-level functions), --group-by module|component (mermaid namespace blocks per module or per component), --externals (edges to types outside the parsed set), --direction LR (mermaid), -I/-E include/exclude globs and -l language (every command; on diff they apply to both revisions, so a filtered file never reads as added or removed), --title, -f/--format mermaid|html. serve takes the same selection flags plus --no-members, --modules, --externals and --title.

Render the .mmd output with mermaid-cli:

npx -y @mermaid-js/mermaid-cli -i changes.mmd -o changes.svg

Or let vizzle drive it, which is usually what you want:

uvx vizzle render changes.mmd out/            # one source
uvx vizzle render docs/diagrams out/ -f svg   # a directory, README excluded

vizzle render finds mmdc on PATH or runs it through bunx/npx, points puppeteer at a browser you already have rather than letting it download a redundant one, and raises Mermaid's default 50,000-character maxTextSize — past which a whole-repo diagram renders a small error graphic instead of failing loudly. The HTML output has no such limit.

Committed diagrams that stay true

A Markdown file can carry a gen:c4-code manifest naming the classes its diagram covers, or a source path to cover in full. vizzle doc regenerates the fence from the code, and --check fails when the committed diagram has drifted, which is the shape a lint step wants:

uvx vizzle doc docs/architecture.md      # regenerate one document
uvx vizzle doc --dir docs --check        # verify every managed doc, write nothing

The manifest format and what --check guarantees are in docs/curated-diagrams.md.

How the diff works

vizzle diff asks git for the changed files (git diff --name-status -M -z), pulls the base-revision contents via git show, and hands both revisions to the Rust core. The core parses each side into a class graph, diffs the graphs (classes keyed by qualified name, members fingerprinted by signature), and renders a single diagram where every class and member carries its change status.

Mermaid 11 quirk, learned the hard way: in classDiagram, classDef statements only take effect when they appear after the cssClass attachments. The renderer emits them last.

Development

uv sync                                  # also installs dev tools (ruff, pre-commit)
uv run pre-commit install                # one-time: enable the git hook

cargo test -p vizzle-core                 # core unit tests
uv run pytest packages/vizzle-cli/tests   # CLI end-to-end tests
uv sync --reinstall-package vizzle       # rebuild after Rust changes

Formatting and linting run on every commit via pre-commit: ruff format + ruff check --fix (Python), cargo fmt + cargo clippy -D warnings (Rust), plus whitespace/YAML/TOML hygiene checks. Run everything manually with uv run pre-commit run --all-files. Vendored (assets/d3.*) and generated (examples/) files are excluded.

JS dependencies (bun)

The d3 bundle inlined into HTML output is a real dependency managed with bun in web/, then vendored into the Python package so wheels stay self-contained:

cd web
bun install            # or: bun update d3
bun run sync-assets    # copies node_modules/d3/dist/d3.min.js into assets/

The vendored copy is committed; re-run sync-assets after bumping d3.

Example outputs generated from the h codebase live in examples/.

Metadata

Release files for vizzle 0.12.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for vizzle 0.12.0
File Size Uploaded Provenance Actions
vizzle-0.12.0.tar.gz 217.2 kB With provenance Details for vizzle-0.12.0.tar.gz

Built distributions (wheels)

Table of built distributions (wheels) for vizzle 0.12.0
File Actions
vizzle-0.12.0-cp310-abi3-manylinux_2_28_x86_64.whl CPython 3.10 abi3 Linux glibc 2.28+ x86-64 Details for vizzle-0.12.0-cp310-abi3-manylinux_2_28_x86_64.whl
vizzle-0.12.0-cp310-abi3-manylinux_2_28_aarch64.whl CPython 3.10 abi3 Linux glibc 2.28+ ARM64 Details for vizzle-0.12.0-cp310-abi3-manylinux_2_28_aarch64.whl
vizzle-0.12.0-cp310-abi3-macosx_11_0_arm64.whl CPython 3.10 abi3 macOS 11.0+ ARM64 Details for vizzle-0.12.0-cp310-abi3-macosx_11_0_arm64.whl
vizzle-0.12.0-cp310-abi3-macosx_10_12_x86_64.whl CPython 3.10 abi3 macOS 10.12+ x86-64 Details for vizzle-0.12.0-cp310-abi3-macosx_10_12_x86_64.whl

Total release size: 7.8 MB

Release files / vizzle-0.12.0.tar.gz

Download URL vizzle-0.12.0.tar.gz
Size 217.2 kB
Tags Source
SHA-256 checksum
How to use checksums
51cabb62b88da39637e926ead915f9518b40eb0f871f6a1b66003e6241e3e768
BLAKE2b-256 checksum
How to use checksums
390db9a17de5ed65c2c96ff3b58add81804fc9b217fd314eb12354183429fc5c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 3, 2026.

Transparency log

Release files / vizzle-0.12.0-cp310-abi3-manylinux_2_28_x86_64.whl

Download URL vizzle-0.12.0-cp310-abi3-manylinux_2_28_x86_64.whl
Size 2.0 MB
Tags CPython 3.10 Linux glibc 2.28+ x86-64 abi3
SHA-256 checksum
How to use checksums
a57a914a5aac88a6662ae0c40e547513e0a3069df61bf953cf91801ce215473a
BLAKE2b-256 checksum
How to use checksums
ffd9f0c2e4a14188bde7524af9c3c7ec8407c78542e3131de4e01a54d8a77b08
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 3, 2026.

Transparency log

Release files / vizzle-0.12.0-cp310-abi3-manylinux_2_28_aarch64.whl

Download URL vizzle-0.12.0-cp310-abi3-manylinux_2_28_aarch64.whl
Size 1.9 MB
Tags CPython 3.10 Linux glibc 2.28+ ARM64 abi3
SHA-256 checksum
How to use checksums
eebcb632c28469659c7940aefa78b76b67a8ad22947a3f27746c25d072e19151
BLAKE2b-256 checksum
How to use checksums
cc15ef367fb68c1519e91929cde6db81dd973611a50017cfd51e0dfd19aaf6b7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 3, 2026.

Transparency log

Release files / vizzle-0.12.0-cp310-abi3-macosx_11_0_arm64.whl

Download URL vizzle-0.12.0-cp310-abi3-macosx_11_0_arm64.whl
Size 1.8 MB
Tags CPython 3.10 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
d6622ab4d3dafae0e565bd520831b57c12d1cb64ac5748f61110dd7f775a4ce1
BLAKE2b-256 checksum
How to use checksums
9520ab08d6bf8906ac824fe5a5973c0bddb86cd024463aa49bcbf43980f8f801
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 3, 2026.

Transparency log

Release files / vizzle-0.12.0-cp310-abi3-macosx_10_12_x86_64.whl

Download URL vizzle-0.12.0-cp310-abi3-macosx_10_12_x86_64.whl
Size 1.9 MB
Tags CPython 3.10 abi3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
141f21134ca9ccf7a1269904e8bcfed425aba67d4070abfac74f57f2a456f227
BLAKE2b-256 checksum
How to use checksums
042a78a361cb0407abff0eb05be345d68c5edd1c12712794765276e1a3919ce7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 3, 2026.

Transparency log

Security for vizzle 0.12.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 5 files in this release have been uploaded with provenance metadata.

Select from 5 files

Attestation for vizzle-0.12.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 3, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page