Map Rust source into a module tree

Paste a lib.rs, main.rs, module file, or a multi-file Rust snippet and get the module/item hierarchy back as an indented tree, Mermaid flowchart, JSON tree, or flat crate::path list. It uses syn's Rust parser, so visibility, impl methods, traits, types, cfg(test) modules and external mod declarations are recognized without uploading code.

Try:
Module map

About this tool

Rust crates grow a hierarchy quickly: mod declarations, nested modules, public and private types, traits, impl blocks, methods, tests, and constants all compete for attention. This tool turns pasted Rust source into a compact map of that hierarchy so you can understand a module before editing it, paste a quick graph into an issue, or export a machine-readable outline.

The parser is syn, not a brace-counting regex. That means inline modules, external mod foo; declarations, visibility such as pub(crate), impl methods, trait declarations, #[cfg(test)], and #[test] attributes are read from Rust syntax. For multi-file snippets, separate files with headers:

=== src/lib.rs ===
pub mod util;

=== src/util.rs ===
pub fn slug() {}

Worked example

Input:

pub mod config {
    pub struct Config;
    impl Config { pub fn load() -> Self { Config } }
}

pub trait Service { fn run(&self); }
fn main() {}

Default tree output:

crate
├── mod config: pub
│   ├── struct Config: pub
│   └── impl Config
│       └── fn load: pub
├── trait Service: pub
└── fn main: pub(self)

Switch to Mermaid when you want a pasteable graph, JSON when another script needs counts and children, or paths when you want a grep-friendly list like crate::config::Config::load (fn, pub).

Practical uses

Limits and edge cases

FAQ

Does this inspect my local crate on disk?

No. It only parses the Rust text you paste into the form or pass to the CLI. That keeps the tool browser-only and deterministic, but it also means it cannot discover sibling files unless you include them in the paste with === path === headers.

How do I resolve `mod foo;` declarations?

Paste multiple files in one input. Start each file with a separator such as === src/lib.rs === or === src/foo.rs ===. When the root declares mod foo;, the mapper connects the matching file under that module. If the file is missing, the node is shown as (external).

Why are test modules hidden?

Most module maps are used to understand production structure, so #[cfg(test)], #[test], and #[bench] items are excluded by default. Enable include_tests when you want test helpers and test-only modules included in the tree.

Can it show dependency edges between modules?

No. This tool maps declarations and nesting. Dependency edges require name/import analysis across files and are already covered by graph-oriented code tools. Use Mermaid output here for the declaration hierarchy, not for use dependency cycles.

Why does a macro-generated item not appear?

Macros are not expanded. A visible macro_rules! name definition appears as a macro node, but items generated by invoking that macro are not available to syn without running a compiler expansion pipeline.

Developer & Automation Access

Run it from the terminal

Same engine as this page, headless — via the gizza CLI:

gizza tool rust-module-map "pub mod config {
    pub struct Config;
    impl Config { pub fn load() -> Self { Config } }
}

fn main() {}"

New to the CLI? Get gizza →

Open it by URL

Pre-fill and auto-run this tool with query parameters — the names match the API/CLI:

https://gizza.ai/tools/rust-module-map/?source=pub%20mod%20config%20%7B%0A%20%20%20%20pub%20struct%20Config%3B%0A%20%20%20%20impl%20Config%20%7B%20pub%20fn%20load%28%29%20-%3E%20Self%20%7B%20Config%20%7D%20%7D%0A%7D%0A%0Afn%20main%28%29%20%7B%7D&format=tree&max_depth=0&focus_on=crate%3A%3Aconfig&sort_by=source&show_types=true&show_traits=true&show_fns=true&show_impls=true&show_consts=true&include_tests=true&show_visibility=true&crate_name=my_crate

Machine-readable descriptor: tool.json — title + parameters JSON Schema for agents.