Skip to content

Arbol

Draw tree structures in the terminal, in the style of the Linux tree command — on Windows, macOS and Linux, with the same commands everywhere.

$ arbol tests/data/sample_tree -I 'datasets|assets|suite|scripts' -L 3
tests/data/sample_tree
├── docs
│   ├── images
│   │   ├── diagram.svg
│   │   └── logo.png
│   ├── api.md
│   ├── changelog.md
│   └── guide.md
├── src
│   ├── core
│   │   ├── utils
│   │   ├── engine.py
│   │   └── parser.py
│   ├── plugins
│   │   ├── export.py
│   │   └── importer.py
│   └── __init__.py
├── vendor
│   ├── bundle.min.css
│   └── legacy.js
├── config.yaml
└── README.md

Hidden entries are skipped by default — no .git/, no .venv/, no __pycache__/. Pass -a to see them. Directories sort before files, then case-insensitively.

What it's for

Four uses, one renderer behind all of them.

1. tree, the same on every platform

tree is a Linux tool. Getting it on Windows means Chocolatey, WSL, or Git Bash, and the flags differ once you do. Arbol is a Python package, so it installs the same way everywhere and takes the same commands everywhere:

arbol .
arbol . -a -L 2

Output matches GNU tree — with -a, byte-identical to tree -a --dirsfirst apart from the summary footer. Flag names follow tree's, so -L, -I and -a mean what you already expect. See the CLI page.

2. Save the structure, edit it, draw it again

-o writes the walk to JSON. Edit that file however you like, then point arbol back at it:

arbol . -o tree.json
arbol tree.json

Useful for proposing a layout before building it — add the directories you plan to add, delete what you plan to remove, and render the result. The edited file goes through exactly the same renderer as a real walk, so what you see is what a finished tree would look like.

Save what you can see

The JSON holds what was walked, so hidden entries are not in it unless you save with -a:

arbol . -a -o tree.json

3. Draw a tree you wrote yourself

The JSON needs no filesystem behind it. Any nesting of objects, arrays and strings draws, so you can describe an org, a schema, a taxonomy — anything tree-shaped:

{
  "ROOT": "Acme Corp",
  "Engineering": {"Backend": ["api", "workers"], "Frontend": ["web", "mobile"]},
  "Operations": {"Support": "tier-1"}
}
$ arbol acme.json
Acme Corp
├── Engineering
│   ├── Backend
│   │   ├── api
│   │   └── workers
│   └── Frontend
│       ├── web
│       └── mobile
└── Operations
    └── Support
        └── tier-1

4. Draw a Python dict directly

No file, no CLI — import it and pass the dict:

import arbol

arbol.print_tree(
    {
        "ROOT": "Acme Corp",
        "Engineering": {"Backend": ["api", "workers"], "Frontend": ["web", "mobile"]},
        "Operations": {"Support": "tier-1"},
    }
)

Same output as above. Use arbol.render(...) instead to get it back as a string — useful for logs, tests, or writing into a report. See the Python API.

Install

The distribution is named arbol-tree, since arbol on PyPI is an unrelated package. The import name and the command are both arbol.

pip install arbol-tree

As a uv tool

To get an arbol command on your PATH without putting it in any project's environment:

uv tool install arbol-tree
arbol .

Upgrade or remove it later with uv tool upgrade arbol-tree and uv tool uninstall arbol-tree.

Without installing anything

uvx fetches, runs, and discards in one step — handy for a one-off, or for trying it before committing to an install:

uvx --from arbol-tree arbol .

The --from is required

A bare uvx arbol resolves the unrelated arbol package on PyPI and fails with Package 'arbol' does not provide any executables. uvx assumes the package name matches the command name; here it does not, which is the whole reason --from exists.

Pin a version the same way:

uvx --from arbol-tree==0.1.0 arbol .

Where to go next

  • Command line — every option, and how directory and JSON input differ
  • Ignore patterns — the -I glob syntax, which mirrors tree
  • Python API — using JsonBuilder and ArbolTerminalView directly