How to Build a Clean ASCII Directory Tree for Your README
Build an ASCII directory tree for your README or docs from an indented file list. Compare the unix tree command, learn the box-drawing connectors, and generate one fast.
How to Build a Clean ASCII Directory Tree for Your README
Open almost any well-maintained repository and the README starts the same way: a short paragraph, then a folder tree drawn with little branch and pipe characters that shows where everything lives. That tree is the fastest way to tell a new contributor "your code goes here, your tests go there" without a wall of prose. This guide covers what those characters mean, how the output compares to the unix tree command, and how to produce one without nudging box characters around by hand.
Why an ASCII tree beats a paragraph
A folder layout written as prose forces the reader to hold structure in their head: "the config file sits next to the source directory, which contains an index and a utils folder, which holds a helper." A tree shows the same thing as a picture you scan in a second.
The most common places people reach for one:
- READMEs, opened with the project layout so a first-time contributor knows where to put a new file.
- Tutorials and blog posts, where the reader has to recreate a specific set of files and a tree makes the target obvious.
- Tickets and code reviews, to show exactly which files a change touches.
- Design docs, to agree on a folder structure before a single directory exists.
Because the tree is plain text, it drops into a fenced code block and renders in monospace on GitHub, GitLab, and most static-site generators with zero extra tooling.
The unix tree command, and where it falls short
If you have the tree command installed, running it in a project root prints exactly the shape we are after — the GNU tree utility has shipped this box-drawing output since the late 1990s and it became the de facto convention for README layouts (source: the GNU/Linux tree man page, which documents the -L, --charset, and -I flags still used today). It is the reason your generated tree should match its glyphs precisely.
But the command assumes the files already exist on the machine you are sitting at. That assumption breaks more often than you would think:
- You are planning a structure that has not been created yet.
- You are in a sandbox, a CI shell, or a locked-down corporate box with no
treebinary. - You only have a screenshot of someone else's file explorer.
- You want to document a layout for part of a repo without
-Iexclude gymnastics.
In all of those cases you need to type the structure by hand. The Directory Tree Generator takes a plain indented list and emits the same connectors tree would, so the output is indistinguishable from the real command — it just does not require the files to be on disk.
Reading the connectors: branch, last-branch, and pipe
Four glyphs do all the work, and once you see the pattern the diagram stops looking like noise:
├──(tee branch) — used for any entry that still has a sibling below it.└──(corner) — the last child of a group; it closes off that branch.│(pipe) — drawn down the left edge of a group while more siblings follow, then replaced by blank space once the corner has been printed.(indent) — three trailing spaces that keep deeper levels aligned.
That tee-versus-corner pairing is the whole trick. The pipe keeps drawing vertically as long as a group has more members, and the moment the corner appears the vertical line stops. Get that right and the tree reads as one connected figure instead of a stack of disconnected rows.
If your target chokes on the Unicode box characters — an old terminal, a plain-text email pipeline, some log viewers, or a font that renders boxes as question marks — switch to ASCII connectors. The branch becomes a pipe plus dashes and the last branch becomes a backtick plus dashes, so the shape survives anywhere.
A real input and its output
Here is the part that trips people up: the input is just an indented list, one entry per line, with a trailing slash on folders. Indentation decides depth — each step inward is one level deeper. Say you type this with a two-space indent unit:
my-app/
src/
index.ts
utils/
format.ts
tests/
index.test.ts
README.md
The generator walks that list and draws the connectors for you, producing:
my-app/
├── src/
│ ├── index.ts
│ └── utils/
│ └── format.ts
├── tests/
│ └── index.test.ts
└── README.md
Notice the geometry: src/ and tests/ get a tee because README.md still follows them, but README.md gets the corner because it is last at the root. Inside src/, the pipe keeps running down the left because tests/ is still coming, which is exactly what makes format.ts line up under utils/ two levels in. A line with children is treated as a folder automatically even if you forget the slash, so the structure stays correct either way.
My take after a year of READMEs
I used to draw these trees by hand, and every single edit was a small disaster. Add one folder and you have to retype every pipe character below it, count spaces, and inevitably ship a README where one branch is a character off and the whole thing looks broken on GitHub. The switch that actually stuck for me was treating the tree as generated output, not a hand-drawn asset. I keep the indented list in the doc's draft, regenerate when the layout changes, and never touch a box character directly. The reverse mode earns its keep too — paste a finished tree someone else drew, get the indented list back, edit it, regenerate. Editing structure as a list and rendering it as a tree is far less error-prone than editing the rendered art.
A few habits that save grief:
- Pick one indent unit and stick to it. Mixing two spaces and a Tab in the same list while the tool is set to spaces is the number-one cause of a child landing at the wrong depth.
- Add the trailing slash to empty folders. A leaf folder like
assets/with nothing inside looks like a file without it. - Keep the names generic if the layout is confidential — or use copy-and-paste instead of the share link, since the URL encodes your list in the query string.
For the surrounding files, the same indented-list discipline pairs well with a .gitignore generator so the structure you document and the structure you commit actually match.
Wrapping up
An ASCII directory tree is one of the highest-leverage things you can put in a README: a second to read, trivial to keep current, and universally rendered in monospace. Type the structure as an indented list, let the connectors get drawn for you, switch to ASCII glyphs when the target is fussy, and regenerate instead of hand-editing. The result reads like tree ran it — because it draws the exact same shape.
Made by Toolora · Updated 2026-06-13