@nnao45/figma-use 0.1.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/SKILL.md ADDED
@@ -0,0 +1,683 @@
1
+ ---
2
+ name: figma-use
3
+ description: Control Figma via CLI — create shapes, frames, text, components, set styles, layout, variables, export images. Use when asked to create/modify Figma designs or automate design tasks.
4
+ ---
5
+
6
+ # figma-use
7
+
8
+ CLI for Figma. Two modes: commands and JSX.
9
+
10
+ ```bash
11
+ # Commands
12
+ bun run dist/cli/index.js create frame --width 400 --height 300 --fill "#FFF" --layout VERTICAL --gap 16
13
+ bun run dist/cli/index.js create icon mdi:home --size 32 --color "#3B82F6"
14
+ bun run dist/cli/index.js set fill 1:23 "$Colors/Primary"
15
+
16
+ # JSX (props directly on elements, NOT style={{}})
17
+ echo '<Frame p={24} bg="#3B82F6" rounded={12}>
18
+ <Text size={18} color="#FFF">Hello</Text>
19
+ </Frame>' | bun run dist/cli/index.js render --stdin --x 100 --y 100
20
+ ```
21
+
22
+ ## Before You Start
23
+
24
+ ```bash
25
+ bun run dist/cli/index.js status # Check connection
26
+ ```
27
+
28
+ If not connected — start Figma with remote debugging:
29
+
30
+ ```bash
31
+ # macOS
32
+ open -a Figma --args --remote-debugging-port=9222
33
+
34
+ # Windows
35
+ "C:\Users\%USERNAME%\AppData\Local\Figma\Figma.exe" --remote-debugging-port=9222
36
+
37
+ # Linux
38
+ figma --remote-debugging-port=9222
39
+ ```
40
+
41
+ Start Figma with `--remote-debugging-port=9222` and you're ready.
42
+
43
+ ## Two Modes
44
+
45
+ **Imperative** — single operations:
46
+
47
+ ```bash
48
+ bun run dist/cli/index.js create frame --width 400 --height 300 --fill "#FFF" --radius 12
49
+ bun run dist/cli/index.js set fill <id> "#FF0000"
50
+ bun run dist/cli/index.js node move <id> --x 100 --y 200
51
+ ```
52
+
53
+ **Declarative** — render JSX trees:
54
+
55
+ ```bash
56
+ echo '<Frame p={24} gap={16} flex="col" bg="#FFF" rounded={12}>
57
+ <Text size={24} weight="bold" color="#000">Title</Text>
58
+ <Text size={14} color="#666">Description</Text>
59
+ </Frame>' | bun run dist/cli/index.js render --stdin --x 100 --y 200
60
+ ```
61
+
62
+ stdin supports both pure JSX and full module syntax with imports:
63
+
64
+ ```tsx
65
+ import { Frame, Text, defineComponent } from 'figma-use/render'
66
+
67
+ const Button = defineComponent(
68
+ 'Button',
69
+ <Frame bg="#3B82F6" p={12} rounded={6}>
70
+ <Text color="#FFF">Click</Text>
71
+ </Frame>
72
+ )
73
+
74
+ export default () => (
75
+ <Frame flex="row" gap={8}>
76
+ <Button />
77
+ <Button />
78
+ </Frame>
79
+ )
80
+ ```
81
+
82
+ **Elements:** `Frame`, `Rectangle`, `Ellipse`, `Text`, `Line`, `Star`, `Polygon`, `Vector`, `Group`, `Icon`, `Image`, `Instance`
83
+
84
+ Use `<Instance>` to create component instances:
85
+
86
+ ```tsx
87
+ <Frame flex="row" gap={8}>
88
+ <Instance component="59763:10626" />
89
+ <Instance component="59763:10629" />
90
+ </Frame>
91
+ ```
92
+
93
+ ⚠️ **Always use `--x` and `--y`** to position renders. Don't stack everything at (0, 0).
94
+
95
+ ## Icons
96
+
97
+ 150k+ icons from Iconify by name:
98
+
99
+ ```bash
100
+ bun run dist/cli/index.js create icon mdi:home
101
+ bun run dist/cli/index.js create icon lucide:star --size 48 --color "#F59E0B"
102
+ bun run dist/cli/index.js create icon heroicons:bell-solid --component # as Figma component
103
+ ```
104
+
105
+ In JSX:
106
+
107
+ ```tsx
108
+ <Icon name="mdi:home" size={24} color="#3B82F6" />
109
+ ```
110
+
111
+ ## Images
112
+
113
+ Create image nodes from URL, local file, or data URI:
114
+
115
+ ```bash
116
+ bun run dist/cli/index.js create image https://example.com/photo.jpg --x 100 --y 200
117
+ bun run dist/cli/index.js create image ./screenshot.png --name "Reference"
118
+ bun run dist/cli/index.js create image ./photo.jpg --width 400 --height 300 --scale fit --radius 12
119
+ ```
120
+
121
+ Auto-detects native image dimensions. Supports `--scale` modes: `fill`, `fit`, `crop`, `tile`.
122
+
123
+ In JSX:
124
+
125
+ ```tsx
126
+ <Image src="https://example.com/photo.jpg" w={200} h={150} />
127
+ ```
128
+
129
+ ## Export JSX
130
+
131
+ Convert Figma nodes back to JSX code:
132
+
133
+ ```bash
134
+ bun run dist/cli/index.js export jsx <id> # Minified
135
+ bun run dist/cli/index.js export jsx <id> --pretty # Formatted
136
+
137
+ # Format options
138
+ bun run dist/cli/index.js export jsx <id> --pretty --semi --tabs
139
+
140
+ # Match vector shapes to Iconify icons (requires: npm i whaticon)
141
+ bun run dist/cli/index.js export jsx <id> --match-icons
142
+ bun run dist/cli/index.js export jsx <id> --match-icons --icon-threshold 0.85 --prefer-icons lucide,tabler
143
+ ```
144
+
145
+ Round-trip workflow:
146
+
147
+ ```bash
148
+ # Export → edit → re-render
149
+ bun run dist/cli/index.js export jsx <id> --pretty > component.tsx
150
+ # ... edit the file ...
151
+ bun run dist/cli/index.js render component.tsx --x 500 --y 0
152
+ ```
153
+
154
+ Compare two nodes as JSX:
155
+
156
+ ```bash
157
+ bun run dist/cli/index.js diff jsx <from-id> <to-id>
158
+ ```
159
+
160
+ ## Export Storybook (Experimental)
161
+
162
+ Export all components on current page as Storybook stories:
163
+
164
+ ```bash
165
+ fbun run dist/cli/index.js export storybook # Output to ./stories/
166
+ fbun run dist/cli/index.js export storybook --out ./src/stories # Custom output dir
167
+ fbun run dist/cli/index.js export storybook --match-icons # Match vectors to Iconify icons
168
+ fbun run dist/cli/index.js export storybook --no-semantic-html # Disable semantic HTML conversion
169
+ ```
170
+
171
+ **Semantic HTML:** By default, components are converted to semantic HTML elements based on their names:
172
+
173
+ - `Input/*`, `TextField/*` → `<input type="text">`
174
+ - `Textarea/*` → `<textarea>`
175
+ - `Checkbox/*` → `<input type="checkbox">`
176
+ - `Radio/*` → `<input type="radio">`
177
+ - `Button/*` → `<button>`
178
+ - `Select/*`, `Dropdown/*` → `<select>`
179
+
180
+ Use `--no-semantic-html` to disable this and keep `<Frame>` elements.
181
+
182
+ Generates `.stories.tsx` files:
183
+
184
+ - **ComponentSets** → React component with props + stories with args
185
+ - **VARIANT properties** → Union type props (`variant?: 'Primary' | 'Secondary'`)
186
+ - **TEXT properties** → Editable string props (`label?: string`)
187
+ - Components grouped by `/` prefix → `Button/Primary`, `Button/Secondary` → `Button.stories.tsx`
188
+
189
+ Example output for Button with variant and label:
190
+
191
+ ```tsx
192
+ // Button.tsx
193
+ export interface ButtonProps {
194
+ label?: string
195
+ variant?: 'Primary' | 'Secondary'
196
+ }
197
+ export function Button({ label, variant }: ButtonProps) {
198
+ if (variant === 'Primary')
199
+ return (
200
+ <Frame>
201
+ <Text>{label}</Text>
202
+ </Frame>
203
+ )
204
+ // ...
205
+ }
206
+
207
+ // Button.stories.tsx
208
+ export const Primary: StoryObj<typeof Button> = {
209
+ args: { label: 'Click', variant: 'Primary' }
210
+ }
211
+ ```
212
+
213
+ ## Variables as Tokens
214
+
215
+ Reference Figma variables in any color option with `var:Name` or `$Name`:
216
+
217
+ ```bash
218
+ bun run dist/cli/index.js create rect --width 100 --height 100 --fill 'var:Colors/Primary'
219
+ bun run dist/cli/index.js set fill <id> '$Brand/Accent'
220
+ ```
221
+
222
+ In JSX:
223
+
224
+ ```tsx
225
+ <Frame bg="$Colors/Primary" />
226
+ <Text color="var:Text/Primary">Hello</Text>
227
+ ```
228
+
229
+ ## Style Shorthands
230
+
231
+ **Size & Position:**
232
+ | Short | Full | Values |
233
+ |-------|------|--------|
234
+ | `w`, `h` | width, height | number or `"fill"` |
235
+ | `minW`, `maxW` | minWidth, maxWidth | number |
236
+ | `minH`, `maxH` | minHeight, maxHeight | number |
237
+ | `x`, `y` | position | number |
238
+
239
+ **Layout:**
240
+ | Short | Full | Values |
241
+ |-------|------|--------|
242
+ | `flex` | flexDirection | `"row"`, `"col"` |
243
+ | `gap` | spacing | number |
244
+ | `wrap` | layoutWrap | `true` |
245
+ | `justify` | justifyContent | `"start"`, `"center"`, `"end"`, `"between"` |
246
+ | `items` | alignItems | `"start"`, `"center"`, `"end"` |
247
+ | `p`, `px`, `py` | padding | number |
248
+ | `pt`, `pr`, `pb`, `pl` | padding sides | number |
249
+ | `position` | layoutPositioning | `"absolute"` |
250
+ | `grow` | layoutGrow | number |
251
+ | `stretch` | layoutAlign | `true` → STRETCH |
252
+
253
+ **Appearance:**
254
+ | Short | Full | Values |
255
+ |-------|------|--------|
256
+ | `bg` | fill | hex or `$Variable` |
257
+ | `stroke` | strokeColor | hex |
258
+ | `strokeWidth` | strokeWeight | number |
259
+ | `strokeAlign` | strokeAlign | `"inside"`, `"outside"` |
260
+ | `opacity` | opacity | 0..1 |
261
+ | `blendMode` | blendMode | `"multiply"`, etc. |
262
+
263
+ **Corners:**
264
+ | Short | Full | Values |
265
+ |-------|------|--------|
266
+ | `rounded` | cornerRadius | number |
267
+ | `roundedTL/TR/BL/BR` | individual corners | number |
268
+ | `cornerSmoothing` | squircle smoothing | 0..1 (iOS style) |
269
+
270
+ **Effects:**
271
+ | Short | Full | Values |
272
+ |-------|------|--------|
273
+ | `shadow` | dropShadow | `"0px 4px 8px rgba(0,0,0,0.25)"` |
274
+ | `blur` | layerBlur | number |
275
+ | `overflow` | clipsContent | `"hidden"` |
276
+ | `rotate` | rotation | degrees |
277
+
278
+ **Text:**
279
+ | Short | Full | Values |
280
+ |-------|------|--------|
281
+ | `size` | fontSize | number |
282
+ | `weight` | fontWeight | `"bold"`, number |
283
+ | `font` | fontFamily | string |
284
+ | `color` | textColor | hex |
285
+
286
+ **Grid (CSS Grid layout):**
287
+ | Short | Full | Values |
288
+ |-------|------|--------|
289
+ | `display` | layoutMode | `"grid"` |
290
+ | `cols` | gridTemplateColumns | `"100px 1fr auto"` |
291
+ | `rows` | gridTemplateRows | `"auto auto"` |
292
+ | `colGap` | columnGap | number |
293
+ | `rowGap` | rowGap | number |
294
+
295
+ ## Components (via .figma.tsx)
296
+
297
+ First call creates master, rest create instances:
298
+
299
+ ```tsx
300
+ import { defineComponent, Frame, Text } from 'figma-use/render'
301
+
302
+ const Card = defineComponent(
303
+ 'Card',
304
+ <Frame p={24} bg="#FFF" rounded={12}>
305
+ <Text size={18} color="#000">
306
+ Card
307
+ </Text>
308
+ </Frame>
309
+ )
310
+
311
+ export default () => (
312
+ <Frame gap={16} flex="row">
313
+ <Card />
314
+ <Card />
315
+ </Frame>
316
+ )
317
+ ```
318
+
319
+ ```bash
320
+ bun run dist/cli/index.js render ./Card.figma.tsx --x 100 --y 200
321
+ bun run dist/cli/index.js render --examples # Full API reference
322
+ ```
323
+
324
+ ## Variants (ComponentSet)
325
+
326
+ ```tsx
327
+ import { defineComponentSet, Frame, Text } from 'figma-use/render'
328
+
329
+ const Button = defineComponentSet(
330
+ 'Button',
331
+ {
332
+ variant: ['Primary', 'Secondary'] as const,
333
+ size: ['Small', 'Large'] as const
334
+ },
335
+ ({ variant, size }) => (
336
+ <Frame
337
+ p={size === 'Large' ? 16 : 8}
338
+ bg={variant === 'Primary' ? '#3B82F6' : '#E5E7EB'}
339
+ rounded={8}
340
+ >
341
+ <Text color={variant === 'Primary' ? '#FFF' : '#111'}>
342
+ {variant} {size}
343
+ </Text>
344
+ </Frame>
345
+ )
346
+ )
347
+ ```
348
+
349
+ Creates real ComponentSet with all combinations.
350
+
351
+ ## Diffs
352
+
353
+ Compare frames and generate patch:
354
+
355
+ ```bash
356
+ bun run dist/cli/index.js diff create --from <id1> --to <id2>
357
+ ```
358
+
359
+ ```diff
360
+ --- /Card/Header #123:457
361
+ +++ /Card/Header #789:013
362
+ type: FRAME
363
+ size: 200 50
364
+ -fill: #FFFFFF
365
+ +fill: #F0F0F0
366
+ ```
367
+
368
+ ⚠️ Context lines need space prefix: ` size: 200 50` not `size: 200 50`
369
+
370
+ Apply with validation (supports modify, create, and delete operations):
371
+
372
+ ```bash
373
+ bun run dist/cli/index.js diff apply patch.diff # Fails if old values don't match
374
+ bun run dist/cli/index.js diff apply patch.diff --dry-run # Preview
375
+ bun run dist/cli/index.js diff apply patch.diff --force # Skip validation
376
+ ```
377
+
378
+ Visual diff (red = changed pixels):
379
+
380
+ ```bash
381
+ bun run dist/cli/index.js diff visual --from <id1> --to <id2> --output diff.png
382
+ ```
383
+
384
+ ⚠️ **After initial render, use diffs or direct commands.** Don't re-render full JSX trees.
385
+
386
+ ## Reconstruct (Image → Figma)
387
+
388
+ Convert a screenshot or mockup image into a Figma design:
389
+
390
+ ```bash
391
+ # Place reference image and create working frame
392
+ bun run dist/cli/index.js reconstruct ./screenshot.png --name "Login Page"
393
+
394
+ # With custom position and reference opacity
395
+ bun run dist/cli/index.js reconstruct https://example.com/mockup.png --x 500 --y 0 --ref-opacity 0.2
396
+
397
+ # Include base64 image data in output (for AI vision analysis)
398
+ bun run dist/cli/index.js reconstruct ./design.png --include-data --json
399
+ ```
400
+
401
+ **AI agent workflow:**
402
+
403
+ 1. `reconstruct ./screenshot.png --json` — places reference image (locked, semi-transparent) and creates empty working frame
404
+ 2. AI analyzes the image (via vision) to understand the layout
405
+ 3. AI uses `render --parent <workingFrameId>` or `create` commands to build Figma nodes on top
406
+ 4. Delete or hide the reference image when done
407
+
408
+ The command returns `workingFrameId`, dimensions, and position — everything the AI needs to start building.
409
+
410
+ ## Query (XPath)
411
+
412
+ Find nodes using XPath selectors:
413
+
414
+ ```bash
415
+ bun run dist/cli/index.js query "//FRAME" # All frames
416
+ bun run dist/cli/index.js query "//FRAME[@width < 300]" # Frames narrower than 300px
417
+ bun run dist/cli/index.js query "//COMPONENT[starts-with(@name, 'Button')]" # Name starts with
418
+ bun run dist/cli/index.js query "//FRAME[contains(@name, 'Card')]" # Name contains
419
+ bun run dist/cli/index.js query "//SECTION/FRAME" # Direct children
420
+ bun run dist/cli/index.js query "//SECTION//TEXT" # All descendants
421
+ bun run dist/cli/index.js query "//*[@cornerRadius > 0]" # Any node with radius
422
+ bun run dist/cli/index.js query "//FRAME[@width > 100 and @width < 500]" # Range
423
+ ```
424
+
425
+ Attributes: `name`, `width`, `height`, `x`, `y`, `cornerRadius`, `opacity`, `visible`, `characters`, `fontSize`, `layoutMode`, `itemSpacing`
426
+
427
+ XPath functions: `contains()`, `starts-with()`, `string-length()`, `not()`, `and`, `or`
428
+
429
+ ## Common Commands
430
+
431
+ ```bash
432
+ # Create
433
+ bun run dist/cli/index.js create frame --width 400 --height 300 --fill "#FFF" --layout VERTICAL --gap 16
434
+ bun run dist/cli/index.js create text --text "Hello" --font-size 24 --fill "#000"
435
+ bun run dist/cli/index.js create rect --width 100 --height 50 --fill "#F00" --radius 8
436
+ bun run dist/cli/index.js create image ./photo.png --x 100 --y 200
437
+
438
+ # Find
439
+ bun run dist/cli/index.js query "//FRAME[@name = 'Header']"
440
+ bun run dist/cli/index.js find --name "Button"
441
+ bun run dist/cli/index.js find --type FRAME
442
+ bun run dist/cli/index.js selection get
443
+
444
+ # Explore
445
+ bun run dist/cli/index.js node ancestors <id> # Get parent chain (useful for navigation)
446
+ bun run dist/cli/index.js node bindings <id> # Get variable bindings for fills/strokes
447
+ bun run dist/cli/index.js page bounds # Find free space for new objects
448
+ bun run dist/cli/index.js variable find "Text/Neutral" # Search variables by name
449
+
450
+ # Modify
451
+ bun run dist/cli/index.js set fill <id> "#FF0000"
452
+ bun run dist/cli/index.js set radius <id> 12
453
+ bun run dist/cli/index.js set text <id> "New text"
454
+ bun run dist/cli/index.js set text-resize <id> height # Wrap text (height auto, fixed width)
455
+ bun run dist/cli/index.js set layout <id> --mode VERTICAL --gap 12 --padding 16
456
+ bun run dist/cli/index.js set layout <id> --mode GRID --cols "1fr 1fr 1fr" --rows "auto" --gap 16
457
+ bun run dist/cli/index.js node move <id> --x 100 --y 200
458
+ bun run dist/cli/index.js node resize <id> --width 300 --height 200
459
+ bun run dist/cli/index.js node delete <id> [id2...]
460
+ bun run dist/cli/index.js node to-component <id>
461
+
462
+ # Export
463
+ bun run dist/cli/index.js export node <id> --output design.png
464
+ bun run dist/cli/index.js export screenshot --output viewport.png
465
+
466
+ # Navigate
467
+ bun run dist/cli/index.js page list
468
+ bun run dist/cli/index.js page set "Page Name"
469
+ bun run dist/cli/index.js viewport zoom-to-fit <id>
470
+ ```
471
+
472
+ Full reference: [REFERENCE.md](https://github.com/dannote/figma-use/blob/master/REFERENCE.md)
473
+
474
+ ## Analyze
475
+
476
+ Discovery tools for understanding design systems:
477
+
478
+ ```bash
479
+ # Repeated patterns — potential components
480
+ bun run dist/cli/index.js analyze clusters
481
+ bun run dist/cli/index.js analyze clusters --min-count 5
482
+
483
+ # Color palette
484
+ bun run dist/cli/index.js analyze colors # Usage frequency
485
+ bun run dist/cli/index.js analyze colors --show-similar # Find similar colors to merge
486
+
487
+ # Typography
488
+ bun run dist/cli/index.js analyze typography # All font combinations
489
+ bun run dist/cli/index.js analyze typography --group-by size
490
+
491
+ # Spacing
492
+ bun run dist/cli/index.js analyze spacing --grid 8 # Check 8px grid compliance
493
+
494
+ # Accessibility snapshot — extract interactive elements
495
+ bun run dist/cli/index.js analyze snapshot # Full page
496
+ bun run dist/cli/index.js analyze snapshot <id> -i # Interactive only (buttons, inputs, etc.)
497
+ bun run dist/cli/index.js analyze snapshot --depth 6 # Limit depth
498
+ ```
499
+
500
+ **Use cases:**
501
+
502
+ - **Component extraction** — find copy-pasted elements that should be components
503
+ - **Design audit** — identify inconsistencies, similar-but-different elements
504
+ - **Design system creation** — discover existing colors, typography, spacing patterns
505
+ - **Onboarding** — understand structure of unfamiliar design files
506
+
507
+ Output shows counts, examples, and warnings (e.g., off-grid spacing, hardcoded colors).
508
+
509
+ ## Lint (Experimental)
510
+
511
+ Check designs for consistency and accessibility issues:
512
+
513
+ ```bash
514
+ bun run dist/cli/index.js lint # Recommended preset
515
+ bun run dist/cli/index.js lint --page "Components" # Lint specific page
516
+ bun run dist/cli/index.js lint --preset strict # Stricter rules
517
+ bun run dist/cli/index.js lint --preset accessibility # A11y only (contrast, touch targets)
518
+ bun run dist/cli/index.js lint --rule color-contrast # Single rule
519
+ bun run dist/cli/index.js lint -v # With fix suggestions
520
+ bun run dist/cli/index.js lint --json # For CI/CD
521
+ bun run dist/cli/index.js lint --list-rules # Show all rules
522
+ ```
523
+
524
+ **Presets:** `recommended`, `strict`, `accessibility`, `design-system`
525
+
526
+ **17 rules:**
527
+
528
+ - Design tokens: `no-hardcoded-colors`, `consistent-spacing`, `consistent-radius`, `effect-style-required`
529
+ - Layout: `prefer-auto-layout`, `pixel-perfect`
530
+ - Typography: `text-style-required`, `min-text-size`, `no-mixed-styles`
531
+ - Accessibility: `color-contrast`, `touch-target-size`
532
+ - Structure: `no-default-names`, `no-hidden-layers`, `no-deeply-nested`, `no-empty-frames`, `no-groups`
533
+ - Components: `no-detached-instances`
534
+
535
+ Exit code 1 if errors found — use in CI pipelines.
536
+
537
+ ## Output
538
+
539
+ Human-readable by default — **prefer this to save tokens**. Use `--json` only when you need to parse specific fields programmatically.
540
+
541
+ ## Node IDs
542
+
543
+ Format: `session:local` (e.g., `1:23`). Inside instances: `I<instance-id>;<internal-id>`.
544
+
545
+ Get IDs from `figma-use selection get` or `figma-use node tree`.
546
+
547
+ ## Colors
548
+
549
+ Hex: `#RGB`, `#RRGGBB`, `#RRGGBBAA`
550
+ Variables: `var:Colors/Primary` or `$Colors/Primary`
551
+
552
+ ---
553
+
554
+ ## Best Practices
555
+
556
+ ### Always verify visually
557
+
558
+ ```bash
559
+ bun run dist/cli/index.js export node <id> --output /tmp/check.png
560
+ ```
561
+
562
+ ### Always zoom after creating
563
+
564
+ ```bash
565
+ bun run dist/cli/index.js viewport zoom-to-fit <id>
566
+ ```
567
+
568
+ ### Position multiple renders separately
569
+
570
+ ```bash
571
+ echo '...' | bun run dist/cli/index.js render --stdin --x 0 --y 0
572
+ echo '...' | bun run dist/cli/index.js render --stdin --x 500 --y 0 # Not at same position!
573
+ ```
574
+
575
+ ### Copy between pages
576
+
577
+ ```bash
578
+ bun run dist/cli/index.js node clone <id> [id2...] --json | jq -r '.[].id'
579
+ bun run dist/cli/index.js node set-parent <new-id> --parent <target-page-id>
580
+ bun run dist/cli/index.js node move <new-id> --x 50 --y 50
581
+ ```
582
+
583
+ ### Replace node
584
+
585
+ ```bash
586
+ # Replace with component (creates instance)
587
+ bun run dist/cli/index.js node replace-with <id> --target <component-id>
588
+
589
+ # Replace with JSX from stdin
590
+ echo '<Icon name="lucide:x" size={16} />' | bun run dist/cli/index.js node replace-with <id> --stdin
591
+ ```
592
+
593
+ ### Convert to component
594
+
595
+ ```bash
596
+ bun run dist/cli/index.js node to-component <id>
597
+ bun run dist/cli/index.js node to-component "1:2 1:3 1:4" # Multiple
598
+ ```
599
+
600
+ ### Instance internal IDs
601
+
602
+ ```bash
603
+ bun run dist/cli/index.js set text "I123:456;789:10" "New text" # I<instance>;<internal>
604
+ ```
605
+
606
+ ### Row layout needs width
607
+
608
+ ```bash
609
+ # ❌ Collapses to 1×1
610
+ <Frame flex="row" gap={8}>
611
+
612
+ # ✅ Explicit width
613
+ <Frame w={300} flex="row" gap={8}>
614
+ ```
615
+
616
+ ### Sections
617
+
618
+ ```bash
619
+ bun run dist/cli/index.js create section --name "Buttons" --x 0 --y 0 --width 600 --height 200
620
+ bun run dist/cli/index.js node set-parent <id> --parent <section-id>
621
+ ```
622
+
623
+ ⚠️ Deleting section deletes all children!
624
+
625
+ ### Comment-driven workflow
626
+
627
+ Wait for designer feedback and react:
628
+
629
+ ```bash
630
+ bun run dist/cli/index.js comment watch --json
631
+ ```
632
+
633
+ Output when comment arrives:
634
+ ```json
635
+ {
636
+ "id": "123456",
637
+ "message": "Make this button bigger",
638
+ "user": { "handle": "designer" },
639
+ "client_meta": { "node_id": "1:23" }
640
+ }
641
+ ```
642
+
643
+ Agent workflow — run once per comment, then restart:
644
+
645
+ 1. `figma-use comment watch --json` — blocks until new comment
646
+ 2. Parse the JSON, get `message` and `target_node` (exact element under comment)
647
+ 3. Process the request (modify design, etc.)
648
+ 4. Reply: `figma-use comment add "Done!" --reply <comment-id>`
649
+ 5. Resolve: `figma-use comment resolve <comment-id>`
650
+ 6. Exit. External runner restarts for next comment.
651
+
652
+ Options:
653
+ - `--timeout 60` — exit after 60s if no comment (returns `{"timeout":true}`)
654
+ - `--interval 5` — poll every 5s (default: 3s)
655
+
656
+ ### Vector paths — iterative workflow
657
+
658
+ Draw, screenshot, adjust, repeat — like a designer tweaking Bezier curves:
659
+
660
+ ```bash
661
+ # 1. Draw initial shape
662
+ bun run dist/cli/index.js create vector --path "M 50 0 L 100 100 L 0 100 Z" --fill "#F00"
663
+
664
+ # 2. Check result
665
+ bun run dist/cli/index.js export node <id> --output /tmp/shape.png
666
+
667
+ # 3. Adjust: scale, move, flip
668
+ bun run dist/cli/index.js path scale <id> --factor 0.8
669
+ bun run dist/cli/index.js path move <id> --dx 20 --dy -10
670
+ bun run dist/cli/index.js path flip <id> --axis x
671
+
672
+ # 4. Or replace path entirely
673
+ bun run dist/cli/index.js path set <id> "M 50 0 C 80 30 80 70 50 100 C 20 70 20 30 50 0 Z"
674
+
675
+ # 5. Screenshot again, repeat until good
676
+ bun run dist/cli/index.js export node <id> --output /tmp/shape.png
677
+ ```
678
+
679
+ For complex illustrations, import SVG:
680
+
681
+ ```bash
682
+ bun run dist/cli/index.js import --svg "$(cat icon.svg)"
683
+ ```
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+
3
+ // Enable V8 compile cache for faster subsequent runs
4
+ import { enableCompileCache } from 'node:module'
5
+ try {
6
+ enableCompileCache()
7
+ } catch {}
8
+
9
+ import('../dist/cli/index.js')