mirror of
https://github.com/storytold/figcraft.git
synced 2026-10-25 02:47:02 -06:00
- New `figcraft_format::rest`: imports the public REST API file JSON (`GET /v1/files/:key`, and the nodes endpoint's response) using the published reference only. Pages (name, background, flow starting points), the layer tree, names, visibility, lock, opacity, blend mode, masks. - Geometry from `relativeTransform` (children of groups/booleans checked against `absoluteBoundingBox` to settle their space), else absolute bounds + rotation; sizes, corner radii (uniform and per corner), smoothing, clip content, constraints, export settings, layout grids. - Paints: solid, linear/radial/angular/diamond gradients (handles map 1:1), image fills (fill, fit, tile, stretch, rotation, filters) with bytes from a resolver or a grey placeholder keyed by the imageRef; paint opacity, visibility and blend. Strokes: weight, per-side weights, align, caps, join, dashes, miter angle. Effects: drop/inner shadow (offset, radius, spread, show behind), layer and background blur. - Vectors from `fillGeometry` (stroke-only vectors use the `strokeGeometry` outline), ellipse arc data, stars/polygons, boolean operations. Text: characters, type style (family, style or weight + italic, size, line height px/%/auto, letter spacing, case, decoration, alignment, auto resize, truncation, paragraph spacing/indent, OpenType flags, links), per-character overrides → styled runs (UTF-16 aware), list type. - Auto layout: direction incl. grid, alignment, padding, gaps, wrap, hug/fixed/fill sizing (legacy and per-axis fields), absolute positioning, min/max, grid cells. - Components and sets with descriptions and property definitions (names lose their `#id` suffix); instances of components in the file become instances with their property values and listed overrides; outside components and component cycles stay frames. Shared styles are created from the layers that use them, named from the metadata. - Unknown types and fields are skipped with a counted warning list; sizes, depth (256), layer count (200,000), path length and list lengths are capped; nothing panics on junk. - Engine: `file.open` / `file.import` / CLI detect the JSON by content, link imported instances to their mains (sources and overrides), read image fills from an `images` folder next to the file, never save over the JSON, and return `warnings`. `file.import` now remaps ids across all imported pages at once (instances keep their main and layer sources) and brings styles and page backgrounds along. `figcraft-cli info` prints load notes. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
96 lines
4.0 KiB
Markdown
96 lines
4.0 KiB
Markdown
# figcraft-cli
|
||
|
||
FigCraft without a window: inspect, export, convert and render documents, run command scripts, list
|
||
commands, serve MCP and measure performance. Build it with
|
||
`cargo build --release -p figcraft-cli` (binary `target/release/figcraft-cli`).
|
||
|
||
Bad arguments print usage and exit with code 2; failures exit with 1. The CLI never panics on input.
|
||
|
||
## Subcommands
|
||
|
||
### `info <file> [--json]`
|
||
|
||
Pages, node counts, top-level frames (id, type, name, size), style/variable/image counts. Repairs
|
||
of a damaged file and import warnings go to stderr as `note:` lines (`notes` with `--json`).
|
||
|
||
Every subcommand that reads a file also takes the public REST API file JSON (the response of
|
||
`GET /v1/files/:key` or of its nodes endpoint, written to a `.json` file): it is imported on the fly.
|
||
Image fills come from `images/<imageRef>.png` (or `.jpg`, …) next to the JSON when present, else a
|
||
grey placeholder.
|
||
|
||
```text
|
||
$ figcraft-cli info app.figcraft
|
||
app.figcraft — App (412 nodes, 6 styles, 12 variables, 3 images)
|
||
page 1 "Screens": 380 nodes, 4 top-level
|
||
2 FRAME "Home" 393.0×852.0
|
||
…
|
||
```
|
||
|
||
### `export <file> -o <out> [--format png|jpg|svg|webp|pdf] [--scale N] [--page NAME] [--node ID|NAME]`
|
||
|
||
- `<out>` is a directory: one file per top-level frame of the page (default the first page), named
|
||
after the frame (`Home.png`, `Settings.png`…); with no frames, one file per top-level layer.
|
||
- `<out>` has an image extension: one file with the given `--node`, or the whole page composited.
|
||
- `--node` takes a layer id (`12` or `0:12`) or a layer name.
|
||
- The format comes from `--format`, else `<out>`'s extension, else png. `--scale` (default 1, max 64)
|
||
applies to raster formats.
|
||
|
||
```sh
|
||
figcraft-cli export app.figcraft -o exports/ --scale 2
|
||
figcraft-cli export app.figcraft -o hero.svg --node "Hero"
|
||
```
|
||
|
||
### `convert <in> <out>`
|
||
|
||
By extension. Inputs: `.figcraft`, `.json` (FigCraft or REST API file JSON), `.svg` (becomes vectors), `.png/.jpg/.webp/.gif/.bmp`
|
||
(an image layer). Outputs: `.figcraft`, `.json` (FigCraft JSON, pretty-printed), `.svg`,
|
||
`.png/.jpg/.webp` (the current page rendered at 1x with its background), `.pdf` (when PDF export is
|
||
available).
|
||
|
||
### `render <file> -o <out.png> [--scale N] [--page NAME]`
|
||
|
||
The whole page (default the first) with its background, as png, jpg or webp. Large pages are scaled
|
||
down to fit 16384 px.
|
||
|
||
### `run <script.json|script.jsonl> [--in <file>] [--out <file>]`
|
||
|
||
Runs commands in a headless session (a new document, or `--in`), printing one JSON line per step:
|
||
|
||
```text
|
||
{"command":"frame.create","ok":true,"result":{"id":2},"step":0}
|
||
```
|
||
|
||
A failing step prints `"ok": false` with the error and exits with code 1 (nothing is saved).
|
||
`--out` saves the result by extension like `convert`.
|
||
|
||
Script formats: a JSON array of `{"command": id, "params": {...}}`, an object
|
||
`{"commands": [...]}`, or JSON lines (one step per line; blank lines and `//` lines are skipped).
|
||
|
||
```json
|
||
[
|
||
{"command": "frame.create", "params": {"preset": "iPhone 16", "x": 0, "y": 0, "name": "Home"}},
|
||
{"command": "node.create", "params": {"type": "text", "parent": 2, "x": 24, "y": 64, "text": "Welcome", "props": {"fontSize": 32}}},
|
||
{"command": "layout.add", "params": {"ids": [2], "direction": "vertical"}}
|
||
]
|
||
```
|
||
|
||
Ids are assigned in order (a new document's first page is 1, so the first layer is 2), which lets a
|
||
script refer to layers it created.
|
||
|
||
### `commands [--json] [--filter TEXT]`
|
||
|
||
Every command with its label, shortcut, undoable flag (`*`) and parameter docs; `--json` for
|
||
machines.
|
||
|
||
### `mcp [--attach PORT]`
|
||
|
||
Serve MCP on stdio: headless by default, or attached to a running app started with
|
||
`figcraft --control PORT`. See [mcp.md](mcp.md).
|
||
|
||
### `perf [--shapes N] [--frames N]`
|
||
|
||
Builds a synthetic document (default 20 000 shapes in 200 frames: rectangles, ellipses and text) and
|
||
times building, a full-page render at 1x, 1920×1080 renders (zoomed in and zoom-to-fit), 10 000 hit
|
||
tests, save/load, SVG export, `node.create` through the engine and select-all + move + undo. Use a
|
||
release build for meaningful numbers.
|