* fix(app): record MCP and CLI structural edits as undo steps The automation bridge ran non-atomic tools, render, and eval without an undo entry, so Edit > Undo could not revert layers an MCP client or the CLI created, deleted, or rearranged. Snapshot the page around these edits as the AI chat does, and skip the entry when nothing changed so read-only scripts leave the history alone. * feat(app): activate documents, undo, redo, and change settings over automation Add activate_document, undo, redo, get_settings, and update_settings to the app's automation bridge. Settings cover appearance, snapping, canvas rendering, recovery, and chat preferences, validated with Valibot and applied through their owning stores; credentials, models, MCP connections, storage, and tool access stay out of reach. * feat(mcp): expose document activation, history, and settings tools * feat(cli): manage documents, history, settings, and tools in the running app Turn documents into a command group (list, open, new, save, close, activate), add undo, redo, and settings get/set, and add tool list/describe/call so every MCP tool runs from the shell, against the running app or headlessly on a file. * docs: document app control from the CLI and MCP * fix: never prompt in the app from automation closes and saves close_file opened the app's Save changes dialog, which an agent cannot answer: the call timed out and the dialog stayed open. It now fails on unsaved changes unless the caller passes unsaved "save" or "discard" (CLI --save or --discard). save_file and new_document no longer open a Save dialog for a document that was never saved, report a failed save as an error, and leave the document untouched when the path is refused. * docs: describe non-interactive close and save * fix: address review findings in app automation Keep a document's source when a save to a new path fails, report vector-edit undo and redo no-ops as unapplied, echo only the applied patch from update_settings so writing cannot read settings, reject tool call --write/--output without a file, and stop settings get from following inherited keys. * fix(app): record render undo on the page that receives the layers A render into a parent on another page was snapshotted against the target page, so undo left the new layers in place. Snapshot the page that contains the parent instead, and document that eval edits made after switching pages stay outside the undo step. * feat(app): limit automation undo to its own steps and expose design check settings The undo history is shared with the person in the editor, so an agent's undo could revert the user's last edit. Automation undo and redo now act only on steps made through the bridge, and only while they are newest; otherwise they fail and leave the history alone. Vector edit mode's session history is off limits entirely. Settings automation also covers the design check preferences that landed on master.
192 lines
5.4 KiB
Markdown
192 lines
5.4 KiB
Markdown
---
|
||
title: Inspecting Files
|
||
description: Browse node trees, search by name or type, and dig into properties from the terminal.
|
||
---
|
||
|
||
# Inspecting Files
|
||
|
||
The CLI lets you explore design documents without opening the editor. Every command also works on the live app — just omit the file argument.
|
||
|
||
::: tip Install
|
||
|
||
```sh
|
||
npm install -g @open-pencil/cli
|
||
# or
|
||
bun add -g @open-pencil/cli
|
||
```
|
||
|
||
:::
|
||
|
||
## Document Info
|
||
|
||
Get a quick overview — page count, total nodes, fonts used, file size:
|
||
|
||
```sh
|
||
openpencil info design.fig
|
||
```
|
||
|
||
## Font Diagnostics
|
||
|
||
Report requested font faces, available sources, substitutions, and affected layers:
|
||
|
||
```sh
|
||
openpencil fonts design.fig
|
||
openpencil fonts design.fig --json
|
||
openpencil fonts --document-id tab-123 --page-id 0:1
|
||
```
|
||
|
||
File mode checks all document pages using the CLI host's available fonts without downloading online fonts. Live mode reports the targeted app document/page, whose loaded fonts may differ from the CLI host. Faces are reported as `available`, `substituted`, or `unresolved`; JSON output includes `faithful`, `faces`, and `issues`.
|
||
|
||
Use [export font policies](./exporting#font-substitution-policy) to warn about or reject substitutions during file-backed raster and PDF exports.
|
||
|
||
## Node Tree
|
||
|
||
Print the full node hierarchy:
|
||
|
||
```sh
|
||
openpencil tree design.fig
|
||
```
|
||
|
||
```
|
||
[0] [page] "Getting started" (0:46566)
|
||
[0] [section] "" (0:46567)
|
||
[0] [frame] "Body" (0:46568)
|
||
[0] [frame] "Introduction" (0:46569)
|
||
[0] [frame] "Introduction Card" (0:46570)
|
||
[0] [frame] "Guidance" (0:46571)
|
||
```
|
||
|
||
## Find Nodes
|
||
|
||
Search by type:
|
||
|
||
```sh
|
||
openpencil find design.fig --type TEXT
|
||
```
|
||
|
||
Search by name:
|
||
|
||
```sh
|
||
openpencil find design.fig --name "Button"
|
||
```
|
||
|
||
Both flags can be combined to narrow results further.
|
||
|
||
## Query with XPath
|
||
|
||
Use XPath selectors to find nodes by type, attributes, and tree structure:
|
||
|
||
```sh
|
||
openpencil query design.fig "//FRAME"
|
||
```
|
||
|
||
### Useful patterns
|
||
|
||
**By type:**
|
||
|
||
```sh
|
||
openpencil query design.fig "//TEXT" # All text nodes
|
||
openpencil query design.fig "//COMPONENT" # All components
|
||
openpencil query design.fig "//INSTANCE" # All instances
|
||
```
|
||
|
||
**By attributes:**
|
||
|
||
```sh
|
||
openpencil query design.fig "//FRAME[@width < 300]" # Frames under 300px wide
|
||
openpencil query design.fig "//*[@cornerRadius > 0]" # Rounded corners
|
||
openpencil query design.fig "//*[@visible = false]" # Hidden nodes
|
||
openpencil query design.fig "//TEXT[@fontSize >= 24]" # Large text
|
||
openpencil query design.fig "//*[@opacity < 1]" # Semi-transparent nodes
|
||
```
|
||
|
||
**By name and text content:**
|
||
|
||
```sh
|
||
openpencil query design.fig "//TEXT[contains(@name, 'Button')]" # Name contains 'Button'
|
||
openpencil query design.fig "//TEXT[contains(@text, 'Hello')]" # Text content contains 'Hello'
|
||
```
|
||
|
||
**By hierarchy:**
|
||
|
||
```sh
|
||
openpencil query design.fig "//SECTION//TEXT" # Text inside sections
|
||
openpencil query design.fig "//FRAME/TEXT" # Direct text children of frames
|
||
openpencil query design.fig "//COMPONENT_SET//INSTANCE" # Instances inside component sets
|
||
```
|
||
|
||
### Queryable attributes
|
||
|
||
`name`, `width`, `height`, `x`, `y`, `visible`, `opacity`, `cornerRadius`, `fontSize`, `fontFamily`, `fontWeight`, `layoutMode`, `itemSpacing`, `paddingTop`, `paddingRight`, `paddingBottom`, `paddingLeft`, `strokeWeight`, `rotation`, `locked`, `blendMode`, `text`, `lineHeight`, `letterSpacing`
|
||
|
||
### Example output
|
||
|
||
```
|
||
Found 5 nodes
|
||
|
||
[0] [frame] "Logo 92×32" (0:9)
|
||
[1] [frame] "logo-short-6 31×32" (0:10)
|
||
[2] [frame] "wrapper 128×73" (0:20)
|
||
[3] [frame] "pen-drawing 148×52" (0:21)
|
||
[4] [frame] "surprised-emoji 32×32" (0:26)
|
||
```
|
||
|
||
## Node Details
|
||
|
||
Inspect all properties of a specific node by its ID:
|
||
|
||
```sh
|
||
openpencil node design.fig --id 1:23
|
||
```
|
||
|
||
## Pages
|
||
|
||
List all pages in the document:
|
||
|
||
```sh
|
||
openpencil pages design.fig
|
||
```
|
||
|
||
## Variables
|
||
|
||
List design variables and their collections:
|
||
|
||
```sh
|
||
openpencil variables design.fig
|
||
```
|
||
|
||
## Live App Mode
|
||
|
||
When the desktop app is running, omit the file argument — the CLI connects via RPC and operates on the live canvas:
|
||
|
||
```sh
|
||
openpencil documents list # list open document/page IDs
|
||
openpencil tree # inspect the active live document
|
||
openpencil tree --document-id tab-123 --page-id 0:1
|
||
openpencil eval --document-id tab-123 --page-id 0:1 -c "..."
|
||
```
|
||
|
||
Use `openpencil documents list --json` in agent workflows, then pass `--document-id` and `--page-id` explicitly instead of relying on the visible active tab/page. To open, save, switch, and close documents, undo, change settings, or call any editor tool, see [Controlling the App](/programmable/cli/app-control).
|
||
|
||
## Lint Designs
|
||
|
||
Check documents for naming, layout, structure, and accessibility issues:
|
||
|
||
```sh
|
||
openpencil lint design.fig
|
||
openpencil lint design.pen --preset strict
|
||
openpencil lint design.fig --rule color-contrast
|
||
openpencil lint design.fig --list-rules
|
||
openpencil lint design.fig --fix -o fixed.fig
|
||
```
|
||
|
||
Use `--json` for machine-readable output; each message carries its `fix` and `suggestions` as data. `--fix` applies the safe fixes — binding colors to the color variable they match and rounding geometry to whole pixels — and writes the result to the `.fig` file given with `-o`.
|
||
|
||
## JSON Output
|
||
|
||
All commands support `--json` for machine-readable output — pipe into `jq`, feed to CI scripts, or process with other tools:
|
||
|
||
```sh
|
||
openpencil tree design.fig --json | jq '.[] | .name'
|
||
```
|