ezu-cli 0.13.1

Command-line renderer for the Ezu Style Spec
# ezu-cli

Command-line renderer for the Ezu Style Spec — the `ezu` binary of the
[`ezu`](../../README.md) workspace.

```sh
cargo install ezu-cli
```

Or without a Rust toolchain: `brew install reearth/tap/ezu`, or take one
of the prebuilt binaries for Linux, macOS and Windows attached to every
[release](https://github.com/reearth/ezu/releases/latest).

Point it at any style (URL or local path) and it renders PNGs. A style
declares its own tile sources in a `sources` block (MVT, PMTiles, raster
DEM, RGBA raster, GeoJSON), so most commands need nothing but a
`--style` and a tile address; CLI flags override anything declared there
for one-off swaps.

## Commands

| Command | What it does |
|---|---|
| `ezu tile` | Render a single `z/x/y` tile to PNG, lossless WebP or raw straight RGBA (by `--out`'s extension or `--format`) |
| `ezu bbox` | Stitch the tiles covering a lon/lat box at one zoom into a single image, `--concurrency` tiles at a time |
| `ezu frame` | Render a map at a print scale and paper size (`--scale 1000 --dpi 200 --size-mm 245x174`), cropped exactly to that frame; `--pages` renders a list of pages in one run |
| `ezu tiles` | Bulk-render an XYZ pyramid into `<out>/<z>/<x>/<y>.png` over a zoom range, `--concurrency` tiles at a time |
| `ezu check` | Validate a style — parse + build graph + resolve assets. Exits non-zero on error, so it drops into a pre-commit hook or CI step. `--no-fetch` stays offline (parse + graph only) |
| `ezu translate` | Lower a MapLibre GL style into an ezu recipe via [`ezu-translate`]../ezu-translate. `--font "NAME=SOURCE"` maps a fontstack entry to a real font; skipped or approximated layers are reported on stderr |
| `ezu graph` | Emit a Mermaid `graph LR` diagram of the style's node dependencies — or, with `--tile`, an HTML page of the same graph with each node's own intermediate tile drawn on it |
| `ezu legend` | Emit the style's declared legend as JSON, with `--swatch-dir` writing each entry's swatch image, for a host to lay out beside the map |
| `ezu schema` | Print the Ezu Style JSON Schema, assembled from the registered ops (`--out FILE` to write it). Feed it to an editor's JSON language server, an `ajv` CI check, or a docs generator — [custom ops]../ezu-graph#custom-ops are included |
| `ezu serve` | Live editor + tile server (below) |

Global flags: `--verbose` / `-v` turns on per-node debug logs from the
evaluator (op name, cache hit/miss, output shape, eval duration).
Render commands share `--style`, `--assets-dir`, `--pmtiles` / `--mvt`,
`--overzoom-levels`, `--pad`, `--strict` (refuse a style that raises build
warnings), `--png-compression`, and repeatable `--param NAME=VALUE` overrides
validated against the style's `params` declarations. `tile`, `bbox`,
`tiles` and `serve` also take `--tile-size`, to render at another size than
the style's `tile-size`, and `--pixel-ratio`, to render the same map at a
higher density for hi-DPI screens; `serve` answers `{y}@2x.png` with the tile
at pixel ratio 2. `tile`, `bbox` and `frame` take repeatable
`--features NODE=PATH` to write a features node's contents as GeoJSON, in
tile units, lon/lat or pixels (`--features-coords`). Source tiles a run
fetches are kept within `EZU_TILE_CACHE_MB` (default 256 MB).

```sh
# Single tile — the reference styles bundle their own `sources` block,
# so no `--pmtiles` / `--mvt` is needed.
ezu tile --style crates/ezu/examples/styles/watercolor.json \
  --tile 13/7276/3225 --out tile.png

ezu bbox --style URL_OR_PATH \
  --bbox 139.74,35.65,139.78,35.69 --zoom 13 --out tokyo.png

# A 1:1000 page, 245 × 174 mm at 200 dpi.
ezu frame --style URL_OR_PATH \
  --center 139.70,35.66 --scale 1000 --dpi 200 --size-mm 245x174 --out page.png

ezu tiles --style URL_OR_PATH \
  --bbox 139.74,35.65,139.78,35.69 --min-zoom 10 --max-zoom 14 --out pyramid

ezu check style.json --no-fetch
ezu translate maplibre-style.json --out recipe.json

# Parameter overrides, validated against the style's `params` block.
ezu tile --style watercolor.json --tile 13/7276/3225 \
  --param 'paper=#ffe0f0' --param softness=2 --out tile.png
```

## `ezu serve` — live editor + tile server

```sh
ezu serve                                                # default example style
ezu serve crates/ezu/examples/styles/pencil-sketch.json  # a specific style
ezu serve https://example.com/style.json                 # or fetch one over http(s)
# Open http://127.0.0.1:8080
```

The server hosts the browser editor at `/`, rendered tiles at
`/tiles/{z}/{x}/{y}.{png,webp}`, raw MVT bytes at `/mvt/{z}/{x}/{y}`,
and a registry-derived JSON Schema at `/schemas/ezu-style.json` — the
same schema the editor validates against as you type, so
[custom ops](../ezu-graph#custom-ops) get autocomplete for free.
`/style/params` serves the current style's parameter schema and
`/style/attribution` the merged source attributions.

The editor (MapLibre GL based) supports:

- **Open / URL / Save** — load a style from a local file or http(s) URL,
  save the current buffer as `<name>.json`. Open on Chromium browsers
  uses the File System Access API so Save writes back in place.
- **Apply** with `⌘↵` / `Ctrl+↵` (works anywhere on the page).
- **Live preview** — when enabled, auto-applies on every keystroke that
  parses + schema-validates + server-validates clean.
- **External-edit reload** — when launched with a local path
  (`ezu serve foo.json`), the server polls the file and pushes
  Server-Sent Events on every change. The editor swaps the buffer
  silently when clean, or surfaces a Reload banner when the user has
  unsaved edits. The `↻ HH:MM:SS` indicator in the toolbar shows the
  last auto-reload. On Chromium, the same watch also runs against
  files opened via the in-browser file picker. Opening a different
  file via `Open…` / `URL…` detaches the server watch for that
  session.
- **Params panel** — controls generated from the style's `params`
  declarations (sliders for bounded numbers, color pickers, toggles,
  and for a `string` param a menu of its `enum` or a text field).
  Adjustments ride the tile requests as query-string overrides and
  re-render live without touching the style text; `reset` returns to
  the declared defaults. See
  [parametric styles]../ezu-style#params.
- **Source MVT inspector** — toggle a vector overlay of the underlying
  MVT, with per-layer ON/OFF and click-to-inspect feature properties.
  Layers are discovered from the tile at the map center; pan/zoom
  rescans automatically.
- **Tile grid + zoom indicator** — toggle a `z/x/y` boundary overlay
  (drawn per tile via `maplibregl.addProtocol`), and read the live
  zoom value (click to copy `z @ lat,lng`).

A self-contained [`ezu-wasm`](../ezu-wasm) demo page and the routes it
needs (including the COOP/COEP headers the threads build requires) ship
with `ezu serve` too.

## License

MIT or Apache-2.0, at your option.