Skip to content
Connect an agent
Other diagram kinds

Tree diagrams

A tree diagram draws a hierarchy: the layout of a repository, the files a pull request changes, a company's teams, who owns which service, or a taxonomy. It replaces the ASCII tree that gets pasted into a README. It is for anyone, human or AI agent, who writes diagram source.

TL;DR

QuestionAnswer
What is it for?Anything with a parent and children: a repository layout, a diff, an org chart, an ownership map, a service dependency tree, or a list of topics.
How do I start one?Write tree "Title", then dir "Name" { blocks with file "name" lines inside, and } to close each block. Org charts and outlines use node "Name" instead.
Which styles are there?style=files (the default) draws a file tree in a frame. style=org draws cards joined by lines, growing down or right. style=outline draws a compact bulleted list.
How is a file's icon chosen?From its name. TypeScript, JavaScript, JSON, Markdown, CSS, HTML, YAML, TOML, lock files, images, shell, Python, Go, Rust, Java, SQL, Dockerfile, and .gitignore each get one. icon= overrides it.
How do I show a diff?change=added, change=modified, or change=removed washes the row green, amber, or red and adds a chip. size="4 KB" adds a pill.
How do I keep it short?omitted 14 "files" draws "and 14 more files". counts=on shows how many entries each folder holds.
What are the limits?300 entries and 8 levels. Past one, the source is refused with E140. More than 60 rows or 6 levels draws a warning.
Does Mermaid convert?Yes. treeView-beta and treeView become a Plotwork tree. See From Mermaid.

Ask your agent

text
Use Plotwork to draw the layout of this repository as a tree. Show the top two levels, put a short note beside each folder, and highlight the README.
text
Use Plotwork to draw the files this pull request changes as a tree. Mark each file added, modified, or removed, give the size of each, and say how many unchanged files are left out.
text
Use Plotwork to draw an org chart of the engineering team as a tree. The CTO has three teams, and each team owns a few services. Give each team its own tone.

Example

A repository layout: folders with a note on each, the icon of each file chosen from its name, a file that changed, a file that is emphasised, and a line that says how many more files there are.

storefront: file tree of 17 entries (10 folders, 7 files), 4 levels, 1 changed, 9 more not drawn. The layout of a small repository: services, libraries, and the file a change touches.

The title is the root of the tree, in the corner tab of the frame. Each folder is a row with its chip, its name in bold, and its note in a quiet column. The thin lines join a folder to its entries. The changed file is washed in amber with a chip, the README is emphasised in blue, and the three dots are the entries that are left out. Folders with no icon of their own get the folder icon, and files get the icon of their type.

The language

One statement to a line. Text is always in double quotes, options are key=value, and # starts a comment. Indentation is for the reader and means nothing to the parser: nesting comes from the braces, so a line written at the wrong depth cannot silently move an entry. A name with a dot or a slash needs its quotes, as every name does.

StatementMeaningExample
tree "Title" style=<style> direction=<direction> counts=<on|off> desc="<text>"The header. Every option is optional, and so is the title.tree "storefront" style=files
desc "<text>"The plain-language description, as a statement. The same as desc= on the header.desc "The layout of the repository."
dir "<Name>" <options> {A folder, a team, or a group. Write its entries inside it and close it with } on its own line. Leave the { off for a folder with nothing drawn in it.dir "src" note="source code" {
file "<name>" <options>A file. It holds nothing.file "main.ts" note="entry point"
node "<Name>" <options> {A person, a team, a service, or a topic. The braces are optional for a leaf.node "Platform" note="12 engineers" {
omitted <count> "<noun>"A quiet entry that says how many more exist and are not drawn.omitted 14 "files"
}Closes the nearest block that is still open, on a line of its own.}

An entry has no id, because a tree has no cross references. A service that two others depend on is written under each of them.

Plotwork
tree "Notes" style=outline
node "Plans" {  node "Free"  node "Pro" note="Hosted links"}omitted 3 "topics"

Header options

OptionValuesDefaultMeaning
style=files, org, outlinefilesHow the tree is drawn.
direction=down, rightdownWhich way an org chart grows. Only org reads it.
counts=on, offoffAdds a pill to each folder with the number of entries it holds. The entries an omitted line stands for are counted.
desc=quoted textnoneThe plain-language description.

Entry options

OptionValuesDefaultMeaning
note=quoted textnoneThe quiet text after the name in a file tree, or the second line of a card.
icon=any bundled icon, such as lucide:server, or nonea folder, or the icon of the file's typeThe icon on the chip.
tone=neutral, blue, violet, aqua, orange, green, amber, rednoneWashes the row, or tints the card, in the tone. It applies to that entry alone.
change=added, modified, removednoneWashes the row green, amber, or red and adds a chip with the word. It wins over tone=.
size=quoted text of at most 12 charactersnoneA pill at the right of the row. An org card does not draw it.
mark=on, offoffEmphasises the entry: a stronger blue wash and a bar at the left of a row, or a heavier outline on a card.

The second line of an entry is note= in every style. sub=, which flow nodes use, is answered with that sentence.

Choosing the icon of a file

A file's icon comes from its name, so a plain file "main.ts" already has the TypeScript mark. The table is small on purpose.

NameIcon
.ts, .tsxTypeScript
.js, .jsx, .mjs, .cjsJavaScript
.json, .jsoncBraces
.md, .mdxAn open book
.css, .scssCode
.html, .xmlMarkup
.yaml, .yml, .toml, .ini, .envSettings
A name with lock in it, such as pnpm-lock.yamlA padlock
.svg, .png, .jpg, .gif, .webpA frame
.sh, .bash, .zshA terminal
.py, .go, .rs, .javaThe language's mark
.sqlA database
Dockerfile, a compose fileDocker
.gitignore, .gitattributesGit
Any other nameA plain file

A pull request as a diff

change= turns a tree into a diff. A folder that holds changes can carry one too, and counts=on shows how many entries each folder holds. omitted says how many unchanged files are not drawn, so the picture stays about the change.

Pull request 128: file tree of 10 entries (4 folders, 6 files), 4 levels, 6 changed, 4 more not drawn. The files a pull request touches: two added, three modified, and one removed, with the size of each.

A row is washed in the tone of its change, then in its own tone, then in blue when it is emphasised. The pills line up down the page, so sizes and changes can be compared at a glance.

An org chart

style=org draws cards in a tidy tree: a parent is centred over its children, and every card of a level has the same height. Use node for people and teams, note= for a role, and tone= to colour a team. A chart that is wider than a Markdown column lists the leaves under their parent on its own, so a team of twelve does not spread across the page.

Engineering ownership: org chart of 11 entries, 3 levels. Who owns what in engineering: the CTO, three teams, and the services each team runs.

A service dependency tree

direction=right grows the chart to the right, a column for each level. It suits a dependency tree, where a service has a long name and a note, because the levels stack down the page and not across it. The cards of a column share a width.

What the checkout needs: org chart of 9 entries, 3 levels. The services the checkout depends on, each with what it needs in turn.

An outline

style=outline is the plainest: a bulleted list that steps in by level, with no frame. It reads as a table of contents, and it is the right choice for a taxonomy or a list of topics. Notes, changes, emphasis, and omitted all work the same way.

Support topics: outline of 14 entries, 3 levels, 1 changed, 6 more not drawn. How the support team sorts what customers ask about.

What a tree is made of

PartHow it looks
FrameA file tree sits in a rounded frame with the title in a corner tab, as a flow group does. An outline and an org chart have no frame.
RowThe same height for every entry. A note of one line never makes it taller, and a note of two lines adds a line. Names step in by level.
NotesOne column after the longest name. They wrap to two lines to keep the picture inside a Markdown column, and are cut with an ellipsis after that.
PillsThe count, the size, and the change, in columns at the right.
Guide linesFrom under a folder's chip a thin line runs down to its last entry and turns into it with a rounded corner.
CardA tinted flow node with an icon chip, a name of at most two lines, and a note of at most two lines.
ConnectorsSquare bends with rounded corners, through the gap between two levels.

Nobody writes a color value: the theme owns every color in light and dark.

Limits and warnings

LimitValueWhat happens past it
Entries300, the omitted lines includedE140 before any layout, with the advice to draw one tree for each top-level folder.
Levels8E140, once at the first folder whose block would start a ninth level. Its entries join the level around it, so nothing else is reported.
A size12 charactersE136.
Rows before the density warning60, in a file tree or an outlineW200.
Levels before the warning6W200.
A name400pxCut with an ellipsis and W203.
A noteTwo linesCut with an ellipsis and W203.

A file tree is as wide as its names, notes, and pills need, up to 880px, the width a Markdown column keeps text readable at. An org chart is as wide as its levels need, and when it is wider than a column it lists leaves under their parents first. The layout is plain arithmetic, so a tree of 300 entries is laid out in a few milliseconds.

Every mistake comes back as a result with a code, a line, a column, and a hint. Warnings never stop the drawing.

CodeWhen it firesFix
E100A name that is not in quotes, an empty name, a file with a block, omitted with no count, a tree with no entries, or text after a statement.Read the hint, which names the line to write. A bare word where a name belongs is answered with the form without an id.
E101, E110, E121, E122An unterminated string, an unknown statement, an unknown tone, or an unknown icon.Read the hint, which names the nearest choice.
E133, E134A block that is never closed, or a } with nothing to close.Add or remove the brace.
E135An unknown option, or sub=.Use note= for the second line.
E136An unknown style=, direction=, counts=, change=, or mark=, a size that is too long, or an omitted count that is not from 1 to 999,999.Read the hint, which says what to write.
E140More than 300 entries, or more than 8 levels.Split the tree by top-level folder, or flatten it.
W200More than 6 levels, more than 60 rows, or two entries of one name in one folder of a file tree.Lift the inner entries up, fold small folders into an omitted line, or rename the repeat.
W202The picture is wider than a Markdown column and its text would shrink.Set direction=right, shorten the names, or split the chart by branch.
W203A name, a note, or the title was cut with an ellipsis.Shorten it. The full text stays in the text description.

From Mermaid

Mermaid treeView-beta (and treeView, which Mermaid is likely to rename it to) converts to a file tree. An entry with entries under it is a folder, so is a name that ends with a slash, and any other entry is a file. An entry is a child of the nearest entry above it that is indented less, as Mermaid reads it. Ask your agent to convert it, or use the convert_mermaid tool. The migration guide covers the converter in full.

Mermaid
---title: Repository layout---treeView-beta    "src" ## where the code lives        "main.ts" :::error ## the entry point        "utils" icon(folder)    "docs"        "guide.md"    "README.md"

The converter reports the class it turned into a tone (M207) and the icon it dropped (M215):

Plotwork
tree "Repository layout" style=files
dir "src" note="where the code lives" {  file "main.ts" note="the entry point" tone=red  file "utils"}
dir "docs" {  file "guide.md"}
file "README.md"
MermaidPlotworkReport
An entry with entries under itdir "Name" {none
An entry with nonefile "Name"none
A name that ends in a slashdir, with the slash taken offnone
A name in double quotes, single quotes, or bare textthe namenone
## text after a namenote="text"none
A title line, front matter title:, and accTitle:The title. A title line wins.none
accDescr:desc=none
:::error and the liketone=red for a class that names a tone (error, warning, success, and the rest of the shared table)M207
Any other :::class, and classDefDropped.M200
icon(name)Dropped. Plotwork icons are a closed set, so the hint names the closest bundled icon.M215
Front matter config: such as rowIndent and lineThickness, and %%{init}%%Dropped.M200
<br/>, other HTML, and entities in a nameRemoved or decoded. A line break becomes a space.M205
An entry with no nameDropped, with everything under it.M216
A line that is not an entryNothing is converted, or the line is skipped when the conversion is lenient.M110, or M218
More than 300 entries, or more than 8 levelsNothing is converted.M102
No titleConverted.M214

See also

DocWhy
Writing diagramsThe flow, sequence and schema languages, and the rules every kind shares
Examples to copyFinished diagrams with the prompt that gets an agent to write each one
Migrating from MermaidConvert existing Mermaid diagrams, and what is dropped
TreemapsWhere size sits in a hierarchy, when the area matters more than the order
Mind mapsIdeas that branch from one root, when the grouping matters more than the layout
Editing existing diagramsRead a diagram back from a picture, change it, and draw it again
Language referenceEvery kind, node type, option and diagnostic
Diagram kindsThe kinds Plotwork draws and the header of each