Skip to content

Commit f5e9268

Browse files
committed
feat: add dirplot demo command
Adds a new `demo` subcommand that runs a curated set of example commands (map, git, read-meta, termsize) and saves outputs to a configurable folder. Supports --output/-o (default: demo), --github-url (default: https://github.com/deeplook/dirplot), and --interactive/-i to confirm each command before running. Updates docs/CLI.md with a full reference section and README.md Quick start with a one-liner. Adds test_demo_help and test_demo_runs.
1 parent 19409f0 commit f5e9268

4 files changed

Lines changed: 468 additions & 0 deletions

File tree

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ dirplot git github://owner/repo -o h.mp4 --animate --last 7d # GitHub, last w
5252

5353
dirplot watch . --output treemap.png # live watch
5454
dirplot watch . --output treemap.mp4 --animate # record as MP4
55+
56+
dirplot demo # run examples, save to ./demo/
5557
```
5658

5759
## Documentation

docs/CLI.md

Lines changed: 310 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,310 @@
1+
# CLI Reference
2+
3+
## `dirplot map` — treemap for any directory tree
4+
5+
```bash
6+
# Use without installing
7+
uvx dirplot --help
8+
9+
# Current directory in system viewer
10+
dirplot map .
11+
12+
# Display inline in terminal (iTerm2 / Kitty / WezTerm, auto-detected)
13+
dirplot map . --inline
14+
15+
# Save to file without displaying
16+
dirplot map . --output treemap.png --no-show
17+
18+
# Exclude paths
19+
dirplot map . --exclude .venv --exclude .git
20+
21+
# Focus on named subtrees
22+
dirplot map . --subtree src --subtree tests
23+
dirplot map . --subtree src/dirplot/fonts
24+
25+
# Multiple roots shown under their common parent
26+
dirplot map src tests
27+
dirplot map src/main.py src/util.py
28+
29+
# Pipe tree or find output (format auto-detected)
30+
tree src/ | dirplot map
31+
tree -s src/ | dirplot map
32+
find . -name "*.py" | dirplot map
33+
find . -type d | dirplot map
34+
35+
# Read a saved path list from a file
36+
tree src/ > paths.txt && dirplot map --paths-from paths.txt
37+
38+
# Custom size, colormap, font
39+
dirplot map . --size 1920x1080 --output treemap.png --no-show
40+
dirplot map . --colormap Set2 --font-size 18
41+
42+
# Log scale — use when one large file dominates and squashes everything else
43+
dirplot map . --log
44+
45+
# Disable cushion shading
46+
dirplot map . --no-cushion
47+
48+
# Show a file-count legend
49+
dirplot map . --legend # up to 20 entries
50+
dirplot map . --legend 10 # cap at 10
51+
52+
# Disable breadcrumb collapsing
53+
dirplot map . -B
54+
55+
# Interactive SVG output (hover highlight + floating tooltip)
56+
dirplot map . --output treemap.svg --no-show
57+
dirplot map . --format svg --output treemap.svg --no-show
58+
59+
# Pipe PNG bytes to stdout
60+
dirplot map . --output - --no-show | convert - -resize 50% small.png
61+
dirplot map . --output - --format svg --no-show > treemap.svg
62+
63+
# Archive files — no unpacking needed
64+
dirplot map project.zip
65+
dirplot map release.tar.gz --depth 2
66+
dirplot map app.jar
67+
68+
# Remote sources
69+
dirplot map ssh://alice@prod.example.com/var/www
70+
dirplot map s3://noaa-ghcn-pds --no-sign
71+
dirplot map github://pallets/flask
72+
dirplot map github://torvalds/linux@v6.12/Documentation
73+
dirplot map docker://my-container:/app
74+
dirplot map pod://my-pod:/app
75+
```
76+
77+
### Options
78+
79+
| Flag | Short | Default | Description |
80+
|---|---|---|---|
81+
| `--paths-from` | || File with path list (`tree`/`find` output); `-` for stdin |
82+
| `--output` | `-o` || Save to this path (PNG or SVG); `-` for stdout |
83+
| `--format` | `-f` | auto | Output format: `png` or `svg` |
84+
| `--show/--no-show` | | `--show` | Display the image after rendering |
85+
| `--inline` | | off | Display in terminal (auto-detected protocol; PNG only) |
86+
| `--legend [N]` | | off | File-count legend; `N` = max entries (default: 20) |
87+
| `--font-size` | | `12` | Directory label font size in pixels |
88+
| `--colormap` | `-c` | `tab20` | Matplotlib colormap for unknown extensions |
89+
| `--exclude` | `-e` || Path to exclude (repeatable) |
90+
| `--subtree` | `-s` || Show only this named subtree (repeatable); supports nested paths |
91+
| `--depth` | | unlimited | Maximum recursion depth |
92+
| `--size` | | terminal size | Output dimensions as `WIDTHxHEIGHT` (e.g. `1920x1080`) |
93+
| `--header/--no-header` | | `--header` | Print info lines before rendering |
94+
| `--cushion/--no-cushion` | | `--cushion` | Van Wijk cushion shading for a raised 3-D look |
95+
| `--log/--no-log` | | `--no-log` | Log scale for file sizes; useful when one large file dominates the layout |
96+
| `--breadcrumbs/--no-breadcrumbs` | `-b`/`-B` | `--breadcrumbs` | Collapse single-child chains into `foo / bar / baz` labels |
97+
| `--password` | || Archive password; prompted interactively if not supplied |
98+
| `--github-token` | | `$GITHUB_TOKEN` | GitHub personal access token |
99+
| `--ssh-key` | | `~/.ssh/id_rsa` | SSH private key path |
100+
| `--aws-profile` | | `$AWS_PROFILE` | Named AWS profile |
101+
| `--no-sign` | | off | Anonymous access for public S3 buckets |
102+
103+
---
104+
105+
## `dirplot watch` — live watch mode
106+
107+
Monitors directories and regenerates the treemap on every change. With `--animate`, each debounced render becomes one frame; the complete APNG or MP4 is written on Ctrl-C.
108+
109+
```bash
110+
# Watch and regenerate on every change
111+
dirplot watch . --output treemap.png
112+
113+
# Watch multiple directories
114+
dirplot watch src tests --output treemap.png
115+
116+
# Adjust debounce (default 0.5 s)
117+
dirplot watch . --output treemap.png --debounce 1.0
118+
dirplot watch . --output treemap.png --debounce 0 # immediate
119+
120+
# Log all events to a JSONL file
121+
dirplot watch src --output treemap.png --event-log events.jsonl
122+
123+
# Animated APNG or MP4 — one frame per debounced render, written on Ctrl-C
124+
dirplot watch . --output treemap.png --animate
125+
dirplot watch . --output treemap.mp4 --animate
126+
dirplot watch . --output treemap.mp4 --animate --crf 18 # higher quality
127+
dirplot watch . --output treemap.mp4 --animate --codec libx265 # smaller file
128+
```
129+
130+
### Options
131+
132+
| Flag | Default | Description |
133+
|---|---|---|
134+
| `--output` / `-o` | required | Output file (`.png`, `.apng`, `.mp4`) |
135+
| `--debounce` | `0.5` | Seconds of quiet before regenerating; `0` disables |
136+
| `--event-log` || Write raw events as JSONL on Ctrl-C exit |
137+
| `--animate` / `--no-animate` | off | Capture frames and write APNG or MP4 on Ctrl-C |
138+
| `--crf` | `23` | MP4 quality: 0 = lossless, 51 = worst. Ignored for APNG |
139+
| `--codec` | `libx264` | MP4 codec: `libx264` (H.264) or `libx265` (H.265) |
140+
| `--log` / `--no-log` | off | Log scale for file sizes |
141+
| `--size` | terminal size | Output dimensions as `WIDTHxHEIGHT` |
142+
| `--depth` || Maximum recursion depth |
143+
| `--exclude` / `-e` || Path to exclude (repeatable) |
144+
| `--colormap` / `-c` | `tab20` | Matplotlib colormap |
145+
| `--font-size` | `12` | Directory label font size in pixels |
146+
| `--cushion` / `--no-cushion` | on | Van Wijk cushion shading |
147+
148+
---
149+
150+
## `dirplot replay` — event log replay
151+
152+
Replays a JSONL event log produced by `dirplot watch --event-log` as an animated treemap. Events are grouped into time buckets (one frame per bucket).
153+
154+
```bash
155+
# Replay as APNG (60-second buckets, 30-second total)
156+
dirplot replay events.jsonl --output replay.apng --total-duration 30
157+
158+
# Replay as MP4
159+
dirplot replay events.jsonl --output replay.mp4 --total-duration 30
160+
dirplot replay events.jsonl --output replay.mp4 --crf 18 # higher quality
161+
dirplot replay events.jsonl --output replay.mp4 --codec libx265 # smaller file
162+
163+
# Fine-grained buckets with fixed frame duration
164+
dirplot replay events.jsonl --output replay.apng --bucket 10 --frame-duration 200
165+
```
166+
167+
### Options
168+
169+
| Flag | Default | Description |
170+
|---|---|---|
171+
| `--output` / `-o` | required | Output `.apng` or `.mp4` |
172+
| `--bucket` | `60.0` | Time bucket size in seconds; one frame per bucket |
173+
| `--frame-duration` | `500` | Frame display time in ms (when `--total-duration` is not set) |
174+
| `--total-duration` || Target total animation length in seconds; frames scale proportionally to real time gaps |
175+
| `--crf` | `23` | MP4 quality: 0 = lossless, 51 = worst. Ignored for APNG |
176+
| `--codec` | `libx264` | MP4 codec: `libx264` (H.264) or `libx265` (H.265) |
177+
| `--workers` / `-w` | all CPU cores | Parallel render workers |
178+
| `--log` / `--no-log` | off | Log scale for file sizes |
179+
| `--size` | terminal size | Output dimensions as `WIDTHxHEIGHT` |
180+
| `--depth` || Maximum directory depth |
181+
| `--exclude` / `-e` || Path to exclude (repeatable) |
182+
| `--colormap` / `-c` | `tab20` | Matplotlib colormap |
183+
| `--font-size` | `12` | Directory label font size in pixels |
184+
| `--cushion` / `--no-cushion` | on | Van Wijk cushion shading |
185+
186+
---
187+
188+
## `dirplot git` — git history animation
189+
190+
Renders a git repository's commit history as an animated treemap. Each commit becomes one frame; changed tiles are highlighted.
191+
192+
The `repo` argument accepts:
193+
- Local path: `.`, `/path/to/repo`
194+
- Local path with ref: `.@my-branch`, `.@v1.0`, `.@abc1234`
195+
- GitHub URL: `github://owner/repo[@branch]` or `https://github.com/owner/repo[/tree/branch]`
196+
197+
For GitHub URLs, dirplot clones into a temporary directory (shallow when `--max-commits` or `--last` is set) and removes it on exit.
198+
199+
```bash
200+
# Full git history as APNG or MP4
201+
dirplot git . --output history.apng --animate --exclude .git
202+
dirplot git . --output history.mp4 --animate
203+
dirplot git . --output history.mp4 --animate --crf 18 # higher quality
204+
dirplot git . --output history.mp4 --animate --codec libx265 # smaller file
205+
206+
# Specific local branch
207+
dirplot git .@my-branch --output history.mp4 --animate
208+
209+
# Revision range with time-proportional frame durations
210+
dirplot git . --output history.apng --animate \
211+
--range main~50..main --total-duration 30
212+
213+
# Specific revision range at fixed resolution
214+
dirplot git /path/to/repo --output history.apng --animate \
215+
--range v1.0..HEAD --size 1920x1080 --exclude node_modules
216+
217+
# GitHub repo — no local clone needed
218+
dirplot git github://owner/repo --output history.apng --animate --max-commits 100
219+
dirplot git github://owner/repo@main --output history.apng --animate --max-commits 50
220+
221+
# Filter by time period
222+
dirplot git . --output history.mp4 --animate --last 30d
223+
dirplot git . --output history.mp4 --animate --last 24h
224+
dirplot git github://owner/repo --output history.mp4 --animate --last 2w --max-commits 10
225+
```
226+
227+
### Options
228+
229+
| Flag | Default | Description |
230+
|---|---|---|
231+
| `--output` / `-o` | required | Output PNG, APNG, or MP4 |
232+
| `--animate` / `--no-animate` | off | Build APNG or MP4; without this, each commit overwrites the output PNG |
233+
| `--range` / `-r` | all commits | Git revision range (e.g. `main~50..main`, `v1.0..HEAD`) |
234+
| `--max-commits` / `-n` || Cap the number of commits processed |
235+
| `--last` || Time-period filter: `30d`, `24h`, `2w`, `1mo`, `30m`. Uses `--shallow-since` for GitHub URLs |
236+
| `--frame-duration` | `1000` | Frame display time in ms (when `--total-duration` is not set) |
237+
| `--total-duration` || Target total animation length in seconds; frames scale proportionally to real time gaps between commits |
238+
| `--crf` | `23` | MP4 quality: 0 = lossless, 51 = worst. Ignored for APNG |
239+
| `--codec` | `libx264` | MP4 codec: `libx264` (H.264) or `libx265` (~40% smaller at same quality) |
240+
| `--workers` / `-w` | all CPU cores | Parallel render workers; 4–8 is typically optimal |
241+
| `--log` / `--no-log` | off | Log scale for file sizes |
242+
| `--size` | terminal size | Output dimensions as `WIDTHxHEIGHT` |
243+
| `--depth` || Maximum directory depth |
244+
| `--exclude` / `-e` || Path to exclude (repeatable) |
245+
| `--colormap` / `-c` | `tab20` | Matplotlib colormap |
246+
| `--font-size` | `12` | Directory label font size in pixels |
247+
| `--cushion` / `--no-cushion` | on | Van Wijk cushion shading |
248+
| `--github-token` | `$GITHUB_TOKEN` | GitHub personal access token |
249+
250+
---
251+
252+
## `dirplot demo` — run example commands
253+
254+
Runs a curated set of example commands covering each subcommand and saves outputs to a folder. Useful for a first-time walkthrough or to verify that everything works in your environment.
255+
256+
```bash
257+
# Run all examples with defaults (saves to ./demo/)
258+
dirplot demo
259+
260+
# Custom output folder and repo
261+
dirplot demo --output ~/dirplot-demo --github-url https://github.com/pallets/flask
262+
263+
# Step through commands one by one
264+
dirplot demo --interactive
265+
```
266+
267+
Examples produced:
268+
269+
| Output file | Command |
270+
|---|---|
271+
| *(stdout)* | `dirplot termsize` |
272+
| `map-local.png` | `dirplot map .` (dark mode, PNG) |
273+
| `map-github.png` | `dirplot map github://owner/repo` (dark mode, PNG) |
274+
| `map-local.svg` | `dirplot map .` (light mode, SVG) |
275+
| `git.png` | `dirplot git github://owner/repo --max-commits 5` (static PNG) |
276+
| `git.mp4` | `dirplot git github://owner/repo --max-commits 10 --animate --total-duration 20` |
277+
| *(stdout)* | `dirplot read-meta map-local.png` |
278+
279+
`dirplot watch` and `dirplot replay` are listed but skipped with an explanatory note — both require interactive or pre-recorded input.
280+
281+
### Options
282+
283+
| Flag | Short | Default | Description |
284+
|---|---|---|---|
285+
| `--output` | `-o` | `demo` | Folder for generated output files |
286+
| `--github-url` | | `https://github.com/deeplook/dirplot` | GitHub repository URL for remote examples |
287+
| `--interactive` | `-i` | off | Ask for confirmation before each command is run |
288+
289+
---
290+
291+
## Inline terminal display
292+
293+
The `--inline` flag renders the image directly in the terminal. The protocol is auto-detected at runtime.
294+
295+
| Terminal | Platform | Protocol |
296+
|---|---|---|
297+
| [iTerm2](https://iterm2.com/) | macOS | iTerm2 |
298+
| [WezTerm](https://wezfurlong.org/wezterm/) | macOS, Linux, Windows | Kitty & iTerm2 |
299+
| [Warp](https://www.warp.dev/) | macOS, Linux | iTerm2 |
300+
| [Hyper](https://hyper.is/) | macOS, Linux, Windows | iTerm2 |
301+
| [Kitty](https://sw.kovidgoyal.net/kitty/) | macOS, Linux | Kitty |
302+
| [Ghostty](https://ghostty.org/) | macOS, Linux | Kitty |
303+
304+
The default `--show` mode opens the image in the system viewer (`open` on macOS, `xdg-open` on Linux) and works in any terminal.
305+
306+
> **Windows:** Common shells and terminal emulators (PowerShell, cmd, Windows Terminal) do not support inline image protocols. [WezTerm](https://wezfurlong.org/wezterm/) is currently the only mainstream Windows terminal with support (Kitty protocol). WSL2 is treated as Linux and has full support.
307+
308+
> **AI coding assistants:** `--inline` does not work in Claude Code, Cursor, or GitHub Copilot Chat — these tools intercept terminal output as plain text. Use `--show` or `--output` instead.
309+
310+
> **Tip:** In supported terminals, the rendered image can often be dragged directly out of the terminal window into another application.

0 commit comments

Comments
 (0)