figura-cli 0.16.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +151 -128
- package/dist/mcp.js +23 -23
- package/package.json +1 -1
- package/skills/fig/SKILL.md +92 -19
package/package.json
CHANGED
package/skills/fig/SKILL.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: fig
|
|
3
3
|
description: "Mock up a screen as an on-brand, shareable HTML fig via your Figura team — render a UI state in seconds before writing the real code. Use when asked to visualize a screen, mock a UI, or 'make a fig'. iPhone-framed by default; browser frame for web/desktop."
|
|
4
4
|
argument-hint: '<what to visualize>'
|
|
5
|
-
allowed-tools: 'mcp__figura__figura_whoami, mcp__figura__figura_generate_fig, mcp__figura__figura_create_fig, mcp__figura__figura_revise_fig, mcp__figura__figura_publish_fig, mcp__figura__figura_commit_fig, Bash(figura *), Bash(bunx figura-cli *)'
|
|
5
|
+
allowed-tools: 'mcp__figura__figura_whoami, mcp__figura__figura_fig_scaffold, mcp__figura__figura_generate_fig, mcp__figura__figura_create_fig, mcp__figura__figura_revise_fig, mcp__figura__figura_publish_fig, mcp__figura__figura_commit_fig, Bash(figura *), Bash(bunx figura-cli *)'
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# /fig — figure it out before you build it
|
|
@@ -47,6 +47,44 @@ point. Only build a standalone `single` fig when the screen is genuinely net-new
|
|
|
47
47
|
Unsure whether a version already exists? **Ask the user** rather than assume
|
|
48
48
|
greenfield.
|
|
49
49
|
|
|
50
|
+
### Reconstruct the baseline from SOURCE — required, no screenshot
|
|
51
|
+
|
|
52
|
+
The existing/current/broken frame of a `compare` fig must be a **faithful
|
|
53
|
+
recreation of what actually ships**, not a hand-approximation — an approximated
|
|
54
|
+
"before" quietly rebuilds a strawman and the diptych argues against a screen that
|
|
55
|
+
doesn't exist. So when you build the baseline state and **no screenshot is
|
|
56
|
+
provided**, studying the source and rebuilding its layout is a **REQUIRED step**,
|
|
57
|
+
not optional reading:
|
|
58
|
+
|
|
59
|
+
1. **Locate the screen** — Grep/Glob for the route dir, the `page`/`route`
|
|
60
|
+
file, and the component(s) it renders (e.g. `apps/*/src/app/<route>/page.tsx`
|
|
61
|
+
plus imported views).
|
|
62
|
+
2. **Read the component file(s)** and extract the real structure:
|
|
63
|
+
- the **JSX/TSX element hierarchy and order** (containers → sections →
|
|
64
|
+
controls, top to bottom);
|
|
65
|
+
- the **class names / style modules / design tokens** on each element
|
|
66
|
+
(`flex`/`grid`, spacing, radii, colors) — these are the layout;
|
|
67
|
+
- the **imported UI primitives** (`Button`, `Input`, `Card`, …) and *their*
|
|
68
|
+
rendered shape (a `variant="cta"` white pill vs an `outline` button is a
|
|
69
|
+
visible difference — open the primitive if unsure);
|
|
70
|
+
- **conditional branches** — auth-provider variants, stages, empty/error/
|
|
71
|
+
loading states — and decide which branch the baseline depicts (state it);
|
|
72
|
+
- the **real copy and labels** (headings, placeholders, button text, error
|
|
73
|
+
banners) verbatim, not paraphrased.
|
|
74
|
+
3. **Rebuild that layout as the baseline** — real element hierarchy, real
|
|
75
|
+
controls, real copy, real spacing — so the "before" frame matches the shipped
|
|
76
|
+
screen line-for-line, then drift only the *proposed* frame.
|
|
77
|
+
4. **Fallback (only if the source genuinely can't be located/read):**
|
|
78
|
+
approximate, and **caption the baseline as an approximation** (a chip / note on
|
|
79
|
+
the frame: "approximated — source not found") so no one mistakes a guess for
|
|
80
|
+
the shipped UI.
|
|
81
|
+
|
|
82
|
+
This is what "grounded in the real current state" above means: the baseline is
|
|
83
|
+
**source-faithful by reconstruction**, or it is explicitly labelled a guess —
|
|
84
|
+
never a silent approximation. It applies to **both** the hand-build path and the
|
|
85
|
+
server render below — on a server render you can't read the repo *for* the engine,
|
|
86
|
+
so you hand it the studied structure in the brief (see step 3, "Server render").
|
|
87
|
+
|
|
50
88
|
## How to fig
|
|
51
89
|
|
|
52
90
|
1. **Verify the destination team** — call **`figura_whoami`** (or
|
|
@@ -64,16 +102,26 @@ greenfield.
|
|
|
64
102
|
re-verify. If the response has no `binding` field (older CLI/MCP), confirm
|
|
65
103
|
the team slug matches this project with the user before proceeding.
|
|
66
104
|
|
|
67
|
-
2. **Default — build it yourself, with YOUR Claude.** Fetch the
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
105
|
+
2. **Default — build it yourself, with YOUR Claude.** Fetch the **canonical
|
|
106
|
+
authoring scaffold** — **`figura_fig_scaffold`** (CLI:
|
|
107
|
+
`bunx figura-cli fig scaffold --platform <mobile|web> [--device <id>] [--area <str>]`)
|
|
108
|
+
— and hand-build the fig's HTML against it, then land it with
|
|
109
|
+
**`figura_create_fig`**, setting `area`, `orientation` (`portrait` /
|
|
110
|
+
`landscape` / `both`), `mode` (`single` / `compare` / `variations` — default
|
|
111
|
+
to `compare` when Existing-first turned up a baseline), `title`, and a real
|
|
112
|
+
description. This uses the caller's own Claude (the model running this skill)
|
|
113
|
+
— no extra cost, full control for precise broken-vs-proposed diptychs.
|
|
114
|
+
|
|
115
|
+
The scaffold IS the source of truth: it's the **exact system prompt Figura
|
|
116
|
+
injects when it renders a fig server-side** — the design rules, exemplars,
|
|
117
|
+
accent hints, your team's composed brand, and the component/device kit
|
|
118
|
+
context, all in one. Follow it verbatim; never invent brand values or restate
|
|
119
|
+
design rules from memory. Match `--platform` to the target (a web fig's
|
|
120
|
+
scaffold composes the team's *web* brand surface, a mobile fig's the *mobile*
|
|
121
|
+
one). **Fallback if the scaffold fetch fails** (older engine/CLI, or the
|
|
122
|
+
`figura_fig_scaffold` tool is unavailable): fetch just the brand with
|
|
123
|
+
`bunx figura-cli brand --json` and author against that — the scaffold is the
|
|
124
|
+
preferred path, the raw brand is the degraded one.
|
|
77
125
|
|
|
78
126
|
**Landing IS hosting — leave `publish` and `commit` unset.** Creating a fig
|
|
79
127
|
always persists it to Figura (there is no separate "save it for real" step);
|
|
@@ -110,6 +158,19 @@ greenfield.
|
|
|
110
158
|
on brand). Never pick this path on your own to save effort: it costs credits
|
|
111
159
|
and hand-built figs track the brand better.
|
|
112
160
|
|
|
161
|
+
**The engine CANNOT read your repo — carry the studied baseline in the brief.**
|
|
162
|
+
`figura_generate_fig` runs server-side against the team brand; it has no access
|
|
163
|
+
to the caller's filesystem, so for a `compare`/existing state it would otherwise
|
|
164
|
+
*guess* the "before" too. Close the seam yourself: do the source study from
|
|
165
|
+
"Reconstruct the baseline from SOURCE" above **first**, then pass the
|
|
166
|
+
reconstructed structure into the `prompt` brief as an explicit "before" spec —
|
|
167
|
+
the file you grounded it in, the element order top-to-bottom, the real controls
|
|
168
|
+
and primitive shapes, the branch depicted, and the verbatim copy/labels. The
|
|
169
|
+
`prompt` is free NL text, so this needs no extra parameter — the studied layout
|
|
170
|
+
just becomes the baseline half of the brief (the proposed half describes the
|
|
171
|
+
change). If you truly couldn't locate the source, say so in the brief and label
|
|
172
|
+
the baseline an approximation, same as the hand-build fallback.
|
|
173
|
+
|
|
113
174
|
4. **Open the HOSTED fig for approval — never a local file.** Run
|
|
114
175
|
`figura fig open <id>` (the id `figura_create_fig`/`figura_generate_fig` just
|
|
115
176
|
returned). It opens **`viewUrl`** in the reviewer's browser — the actual
|
|
@@ -173,7 +234,9 @@ truncation, and doesn't need a library):
|
|
|
173
234
|
as annotation chips: what's broken today, what each variation improves,
|
|
174
235
|
what it trades away.
|
|
175
236
|
- **In both views:** render the current state honestly from the shipped
|
|
176
|
-
implementation
|
|
237
|
+
implementation — **reconstructed from source** per "Reconstruct the baseline
|
|
238
|
+
from SOURCE" (no screenshot ⇒ study the component file(s) and rebuild the real
|
|
239
|
+
layout, don't approximate); color-code chips by function (broken / improved /
|
|
177
240
|
trade-off / detail) using the team's status colors from the fetched design
|
|
178
241
|
system; mark the recommended variation and close with a short "my read"
|
|
179
242
|
arguing the pick against the others. Keep the chrome around the frames
|
|
@@ -255,11 +318,20 @@ with two things you do **not** hand-write:
|
|
|
255
318
|
|
|
256
319
|
So when you **hand-build** a fig (the default path), do your part of the contract:
|
|
257
320
|
|
|
258
|
-
- **
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
321
|
+
- **Bare mobile screen — and ONLY then:** when the fig's HTML *is* one raw app
|
|
322
|
+
screen (no masthead, no state pills, no hand-drawn `.fig-device` frames — the
|
|
323
|
+
Figura viewer draws the iPhone shell around it), size the body to the exact
|
|
324
|
+
logical screen and emit `<meta name="figura:artboard" content="WxH">` matching
|
|
325
|
+
it (iPhone portrait `393x852` / landscape `852x393`). For OS-chrome insets
|
|
326
|
+
prefer `var(--fig-safe-top, 59px)` / `.fig-safe-top` over hardcoded pixels —
|
|
327
|
+
the stamp fills the value, the fallback keeps you correct if the kit is absent.
|
|
328
|
+
- **A document-style fig NEVER gets an artboard.** The artboard meta is the
|
|
329
|
+
viewer's opt-in signal for "size me to exactly WxH and wrap me in a device
|
|
330
|
+
shell" — stamped on an overview ⇄ focus redesign page (or any compare /
|
|
331
|
+
variations document with its own masthead, pills, or hand-drawn device
|
|
332
|
+
frames), it crams the whole document into a phone frame. A document fig
|
|
333
|
+
renders full-page precisely because it carries NO artboard meta, even when
|
|
334
|
+
every screen it depicts is a mobile app.
|
|
263
335
|
- **Always:** emit `<meta name="figura:context" content="...">` (design intent).
|
|
264
336
|
- **Optional but valued:** if the fig grounds a specific feature or flag, emit
|
|
265
337
|
`<meta name="figura:feature" content="<flag-or-slug>">` so it links back to the
|
|
@@ -270,8 +342,9 @@ So when you **hand-build** a fig (the default path), do your part of the contrac
|
|
|
270
342
|
- **MCP unavailable** (headless / cron, or no interactive auth): fall back to the
|
|
271
343
|
CLI — `bunx figura-cli fig create` / `fig publish`, with `fig revise` /
|
|
272
344
|
`fig revisions` for versions, `fig commit` / `fig uncommit` (or `--commit` on
|
|
273
|
-
the final create/revise) for the team library,
|
|
274
|
-
`bunx figura-cli brand --json` for the
|
|
345
|
+
the final create/revise) for the team library, `bunx figura-cli fig scaffold`
|
|
346
|
+
for the authoring scaffold, and `bunx figura-cli brand --json` for the raw
|
|
347
|
+
brand (the scaffold's fallback).
|
|
275
348
|
- **`figura_create_fig`/`figura_revise_fig` itself fails** (no network, API down,
|
|
276
349
|
auth expired): the fig never entered Figura, so there is no `id`/`viewUrl` to
|
|
277
350
|
open. Only THEN write the HTML to a local scratch file (project-scoped —
|