ASCII disk usage visualizer with truecolor heat gradient — TreeSize / ncdu energy, but as a one-shot CLI snapshot.
Scan a directory and get:
- a tree view with gradient bars (cold → hot across each bar), percent, size, icons
- a file-type breakdown clustered by extension
- a squarified ASCII treemap of top-level children, color-coded by size
- volume context in the banner — see "scan is X% of a Y-GB disk that's Z% full" at a glance
- sparse-aware sizing — reports allocated bytes (like
du), not logical size; a 460 GB Docker.raw that actually uses 4 GB shows as 4 GB
Or run termtree --sys for a system overview: CPU, memory, disk, network bars with full context, plus top processes grouped by app — same visual language, no separate tool.
No dependencies — stdlib Python only. Single file. macOS for --sys (uses top, netstat, vm_stat); disk mode works anywhere POSIX.
████████╗███████╗██████╗ ███╗ ███╗████████╗██████╗ ███████╗███████╗
╚══██╔══╝██╔════╝██╔══██╗████╗ ████║╚══██╔══╝██╔══██╗██╔════╝██╔════╝
██║ █████╗ ██████╔╝██╔████╔██║ ██║ ██████╔╝█████╗ █████╗
██║ ██╔══╝ ██╔══██╗██║╚██╔╝██║ ██║ ██╔══██╗██╔══╝ ██╔══╝
██║ ███████╗██║ ██║██║ ╚═╝ ██║ ██║ ██║ ██║███████╗███████╗
╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚══════╝╚══════╝
termtree ▸ ~/Documents/Obsidian ▸ 2.8 MB · 364 files
curl -fsSL https://raw.githubusercontent.com/daniellauding/termtree/main/termtree.py \
-o ~/.local/bin/termtree && chmod +x ~/.local/bin/termtreepip install --user git+https://github.com/daniellauding/termtreegit clone https://github.com/daniellauding/termtree.git
cd termtree && ln -s "$PWD/termtree.py" ~/.local/bin/termtreeRequires Python 3.8+. For full truecolor: a terminal with COLORTERM=truecolor (iTerm2, Alacritty, Kitty, modern Terminal.app, WezTerm, etc.). Falls back to 256-color otherwise.
termtree # current dir, depth 2
termtree ~/Downloads -d 3 -n 15 # deeper, more children per level
termtree /Applications -d 1 # what apps weigh (treats .app bundles as opaque)
termtree ~ -d 1 --no-treemap # quick home overview
termtree . | less -R # paginate (colors preserved with -R)
termtree --sys # system overview: CPU + memory + disk + network
termtree --sys --watch 5 # live overview, refreshing every 5 secondstermtree ▸ system overview ▸ sampled 2s
CPU ██████▎ 28.4% 8 cores · load 4.60 5.97 7.25
Memory █████████████████████▎ 96.9% 31.0 GB used / 32.0 GB · 14.0 GB compressed
Disk ████████████████▌ 75.4% 347.2 GB used / 460.4 GB · 113.2 GB free
Net ↓ 2.6 KB/s ↑ 4.2 KB/s
I/O R 0 B/s W 0 B/s
Top CPU Top Memory
────────────────────────────────── ──────────────────────────────────
████ 40.8% Google Chrome ▊ 2.8 GB Google Chrome
██▋ 26.9% Warp ▋ 2.2 GB Notion
██▍ 24.5% WindowServer ▌ 1.9 GB com.apple.Virtu
... ...
CPU bars use 100% = one core saturated (top's per-process convention), so a process showing 200% means it's using two full cores. The system CPU bar at the top uses 0–100% wall.
Memory uses sysctl hw.memsize as authoritative total. Network uses exact byte deltas from netstat -ib (not top's MB-rounded counter, which loses small traffic). Top processes are aggregated by .app bundle name so all Chrome helpers roll up under "Google Chrome".
| flag | default | meaning |
|---|---|---|
path |
. |
directory to scan |
-d, --depth N |
2 |
tree depth |
-n, --top N |
10 |
top-N children shown per level (rest collapsed into … more) |
-w, --width N |
78 |
treemap width in cols |
--height N |
20 |
treemap height in rows |
--no-banner |
— | hide the ASCII banner |
--no-tree |
— | skip tree view |
--no-treemap |
— | skip treemap |
--no-types |
— | skip file-type breakdown |
--no-color |
— | disable ANSI colors |
-L, --follow-symlinks |
off | follow symlinks (off by default to avoid cycles) |
--apparent |
off | report logical size (st_size, like ls -l) instead of allocated on-disk blocks. Default is du-style allocated bytes — sparse files like Docker.raw will look ~100× bigger if you flip this on |
-S, --sys |
off | system overview mode: CPU + memory + disk + network on one screen. Skips disk scan |
--sample N |
2.0 |
sample window in seconds for --sys rate metrics |
--watch N |
— | refresh every N seconds (clears screen between). Works for both modes |
-V, --version |
— | print version |
Sorted by size (descending). Each row gets a gradient bar where filled cells go cold (blue) → hot (red) as the percentage approaches 100%. Small items stay cool, hot items light up.
├── ████▏ 67.4% 1.9 MB 📁 01-Projects
│ ├── ██▏ 12.2% 345.8 KB statement.pdf
│ ├── █▌ 8.8% 249.6 KB 📁 Budget-2026
│ └── █▉ 10.6% 300.9 KB … 15 more (74 files)
├── ██▏ 12.4% 350.9 KB 📁 02-Areas
└── ▎ 1.8% 49.7 KB … 18 more (30 files)
Folder icons:
- 📁 directory
- 📱
.appbundle (treated as opaque — internals not exposed) - ⚙️
.framework - 📦
.bundle - 🔒 dot-prefixed (hidden)
Clusters every file by extension across the whole scan — even nested deeply inside .app bundles. Useful for "what kind of files are eating my disk".
File types
──────────────────────────────────────────────────────────────────────
████████████▉ 59.0% 1.6 MB 324× .md
███▏ 14.3% 405.6 KB 3× .pdf
█▋ 7.5% 213.2 KB 5× .xlsx
Squarified treemap of top-level children, with cells sized proportionally to disk usage and color-coded by heat. Compensates for terminal character aspect ratio (~2:1 tall:wide) so rectangles look visually square.
┌───────────────────────────────────────────┐┌───────────┐┌──────────┐
│01-Projects ││02-Areas ││Projects │
│1.9 MB 67% ││12% ││11% │
│ ││ ││ │
└───────────────────────────────────────────┘└───────────┘└──────────┘
| termtree | du -sh * |
ncdu |
TreeSize | |
|---|---|---|---|---|
| One-shot snapshot | ✅ | ✅ | ❌ (interactive) | ❌ (GUI) |
| Treemap | ✅ | ❌ | ❌ | ✅ |
| File-type clustering | ✅ | ❌ | partial | ✅ |
| Gradient color | ✅ | ❌ | ❌ | ✅ |
| Zero dependencies | ✅ | ✅ | ❌ (C build) | ❌ |
| Works over SSH / pipes | ✅ | ✅ | ❌ |
termtree is intentionally not interactive. Use ncdu if you want navigation; use termtree when you want a screenshot-able snapshot you can paste into a doc, PR, or chat.
- Pure Python, single-pass
os.scandirrecursion. - Scans ~50k files/sec on warm cache (M-series Mac, APFS).
- Symlinks are not followed by default (avoids cycles on system paths). Use
-Lif you really want to. .app/.framework/.bundledirectories are summed but their internals don't appear in the tree — keeps macOS output readable. File-type stats still see inside them.
Issues, PRs, and "this would be cool" suggestions welcome.
Ideas on the table:
- interactive mode (curses / textual) with arrow-key drill-down
- output as JSON / SVG for tooling
- exclude patterns (
--exclude '*.cache') - nested treemap (recurse one level inside biggest box)
- gitignore-aware scanning
- comparison mode (diff two snapshots)
Keep PRs focused. Pure stdlib is a hard constraint — no extra deps unless they're optional and behind a feature flag.
MIT — see LICENSE.
Built by Daniel Lauding.