@dannote/figma-use 0.3.0 → 0.5.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/CHANGELOG.md +100 -0
- package/README.md +217 -334
- package/SKILL.md +78 -1
- package/bin/figma-use.js +4 -1
- package/dist/cli/index.js +563 -83
- package/dist/proxy/index.js +180 -2
- package/package.json +1 -1
- package/packages/plugin/dist/main.js +93 -1
package/README.md
CHANGED
|
@@ -1,444 +1,327 @@
|
|
|
1
1
|
# figma-use
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**CLI for Figma.** LLMs already know React and work great with CLIs — this combines both.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
```bash
|
|
6
|
+
echo '<Frame style={{padding: 24, backgroundColor: "#3B82F6", borderRadius: 12}}>
|
|
7
|
+
<Text style={{fontSize: 18, color: "#FFF"}}>Hello Figma</Text>
|
|
8
|
+
</Frame>' | figma-use render --stdin
|
|
9
|
+
```
|
|
8
10
|
|
|
9
|
-
|
|
11
|
+
No JSON schemas, no MCP protocol overhead — just JSX that any LLM can write.
|
|
10
12
|
|
|
11
|
-
|
|
12
|
-
|---------|-------------|-----------|
|
|
13
|
-
| Read node properties | ✓ | ✓ |
|
|
14
|
-
| Take screenshots | ✓ | ✓ |
|
|
15
|
-
| Extract variables | ✓ | ✓ |
|
|
16
|
-
| **Create shapes** | ✗ | ✓ |
|
|
17
|
-
| **Create text** | ✗ | ✓ |
|
|
18
|
-
| **Create frames & components** | ✗ | ✓ |
|
|
19
|
-
| **Modify properties** | ✗ | ✓ |
|
|
20
|
-
| **Set fills, strokes, effects** | ✗ | ✓ |
|
|
21
|
-
| **Auto-layout** | ✗ | ✓ |
|
|
22
|
-
| **Create/modify variables** | ✗ | ✓ |
|
|
23
|
-
| **Execute arbitrary code** | ✗ | ✓ |
|
|
13
|
+
📄 **Includes [SKILL.md](./SKILL.md)** — drop-in reference for Claude Code and other AI agents.
|
|
24
14
|
|
|
25
|
-
|
|
15
|
+
## Why CLI over MCP?
|
|
26
16
|
|
|
27
|
-
|
|
17
|
+
MCP servers exchange verbose JSON. CLIs are **token-efficient**:
|
|
28
18
|
|
|
19
|
+
```bash
|
|
20
|
+
# 47 tokens
|
|
21
|
+
figma-use create frame --width 400 --height 300 --fill "#FFF" --radius 12 --layout VERTICAL --gap 16
|
|
29
22
|
```
|
|
30
|
-
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
|
31
|
-
│ │ │ │ │ │
|
|
32
|
-
│ AI Agent / │─────▶│ figma-use │─────▶│ Figma │
|
|
33
|
-
│ CLI │ HTTP │ proxy │ WS │ Plugin │
|
|
34
|
-
│ │◀─────│ :38451 │◀─────│ │
|
|
35
|
-
│ │ │ │ │ │
|
|
36
|
-
└─────────────────┘ └────────┬────────┘ └─────────────────┘
|
|
37
|
-
│
|
|
38
|
-
│ WebSocket (persistent)
|
|
39
|
-
▼
|
|
40
|
-
┌─────────────────┐
|
|
41
|
-
│ Figma │
|
|
42
|
-
│ Multiplayer │
|
|
43
|
-
│ Server │
|
|
44
|
-
└─────────────────┘
|
|
45
|
-
```
|
|
46
23
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
24
|
+
vs MCP JSON request + response: **~200 tokens** for the same operation.
|
|
25
|
+
|
|
26
|
+
For AI agents doing dozens of Figma operations, this adds up fast.
|
|
50
27
|
|
|
51
|
-
|
|
28
|
+
## Why JSX?
|
|
29
|
+
|
|
30
|
+
Every LLM has been trained on millions of React components. They can write this without examples:
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
<Frame style={{ flexDirection: 'column', gap: 16, padding: 24 }}>
|
|
34
|
+
<Text style={{ fontSize: 24, fontWeight: 'bold' }}>Title</Text>
|
|
35
|
+
<Text style={{ fontSize: 14, color: '#666' }}>Description</Text>
|
|
36
|
+
</Frame>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The `render` command takes this JSX and creates real Figma nodes — frames, text, components, auto-layout, the works.
|
|
52
40
|
|
|
53
41
|
## Installation
|
|
54
42
|
|
|
55
43
|
```bash
|
|
56
44
|
bun install -g @dannote/figma-use
|
|
45
|
+
|
|
46
|
+
figma-use plugin # Install Figma plugin (quit Figma first)
|
|
47
|
+
figma-use proxy # Start proxy server
|
|
57
48
|
```
|
|
58
49
|
|
|
59
|
-
|
|
50
|
+
Open Figma → Plugins → Development → **Figma Use**
|
|
51
|
+
|
|
52
|
+
## Render: JSX → Figma (Experimental)
|
|
60
53
|
|
|
61
|
-
|
|
54
|
+
> ⚠️ Uses Figma's internal multiplayer protocol — ~100x faster than plugin API, but may break if Figma changes it.
|
|
55
|
+
|
|
56
|
+
### Setup
|
|
62
57
|
|
|
63
58
|
```bash
|
|
59
|
+
# Terminal 1: Start Figma with debug port
|
|
60
|
+
figma --remote-debugging-port=9222
|
|
61
|
+
|
|
62
|
+
# Terminal 2: Start proxy
|
|
64
63
|
figma-use proxy
|
|
65
64
|
```
|
|
66
65
|
|
|
67
|
-
###
|
|
66
|
+
### Basic Usage
|
|
68
67
|
|
|
69
68
|
```bash
|
|
70
|
-
#
|
|
71
|
-
figma-use
|
|
69
|
+
# From stdin
|
|
70
|
+
echo '<Frame style={{width: 200, height: 100, backgroundColor: "#FF0000"}} />' | figma-use render --stdin
|
|
72
71
|
|
|
73
|
-
#
|
|
74
|
-
figma-use
|
|
75
|
-
|
|
76
|
-
|
|
72
|
+
# From file
|
|
73
|
+
figma-use render ./Card.figma.tsx
|
|
74
|
+
|
|
75
|
+
# With props
|
|
76
|
+
figma-use render ./Card.figma.tsx --props '{"title": "Hello"}'
|
|
77
77
|
```
|
|
78
78
|
|
|
79
|
-
|
|
79
|
+
### Supported Elements
|
|
80
80
|
|
|
81
|
-
|
|
81
|
+
`Frame`, `Rectangle`, `Ellipse`, `Text`, `Line`, `Star`, `Polygon`, `Vector`, `Group`
|
|
82
82
|
|
|
83
|
-
|
|
84
|
-
# Create a styled button
|
|
85
|
-
figma-use create frame --x 0 --y 0 --width 200 --height 48 \
|
|
86
|
-
--fill "#3B82F6" --radius 8 \
|
|
87
|
-
--layout HORIZONTAL --gap 8 --padding "12,24,12,24" \
|
|
88
|
-
--name "Button"
|
|
89
|
-
|
|
90
|
-
# Add text
|
|
91
|
-
figma-use create text --x 0 --y 0 --text "Click me" \
|
|
92
|
-
--fontSize 16 --fontFamily "Inter" --fontStyle "Medium" --fill "#FFFFFF" \
|
|
93
|
-
--parent "1:23"
|
|
94
|
-
|
|
95
|
-
# Export to PNG
|
|
96
|
-
figma-use export node "1:23" --format PNG --scale 2 --output button.png
|
|
97
|
-
```
|
|
83
|
+
### Style Properties
|
|
98
84
|
|
|
99
|
-
|
|
85
|
+
```tsx
|
|
86
|
+
// Layout
|
|
87
|
+
flexDirection: 'row' | 'column'
|
|
88
|
+
justifyContent: 'flex-start' | 'center' | 'flex-end' | 'space-evenly'
|
|
89
|
+
alignItems: 'flex-start' | 'center' | 'flex-end' | 'stretch'
|
|
90
|
+
gap: number
|
|
91
|
+
padding: number
|
|
92
|
+
paddingTop / paddingRight / paddingBottom / paddingLeft: number
|
|
93
|
+
|
|
94
|
+
// Size & Position
|
|
95
|
+
width: number
|
|
96
|
+
height: number
|
|
97
|
+
x: number
|
|
98
|
+
y: number
|
|
99
|
+
|
|
100
|
+
// Appearance
|
|
101
|
+
backgroundColor: string // hex color
|
|
102
|
+
borderColor: string
|
|
103
|
+
borderWidth: number
|
|
104
|
+
borderRadius: number
|
|
105
|
+
opacity: number
|
|
106
|
+
|
|
107
|
+
// Text
|
|
108
|
+
fontSize: number
|
|
109
|
+
fontFamily: string
|
|
110
|
+
fontWeight: 'normal' | 'bold' | '100'-'900'
|
|
111
|
+
color: string
|
|
112
|
+
textAlign: 'left' | 'center' | 'right'
|
|
113
|
+
```
|
|
100
114
|
|
|
101
|
-
|
|
115
|
+
### Reusable Components
|
|
102
116
|
|
|
103
|
-
|
|
117
|
+
`defineComponent` creates a Figma Component. First usage renders the master, subsequent usages create Instances:
|
|
104
118
|
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
119
|
+
```tsx
|
|
120
|
+
import { defineComponent, Frame, Text } from '@dannote/figma-use/render'
|
|
121
|
+
|
|
122
|
+
const Card = defineComponent('Card',
|
|
123
|
+
<Frame style={{ padding: 24, backgroundColor: '#FFF', borderRadius: 12 }}>
|
|
124
|
+
<Text style={{ fontSize: 18, color: '#000' }}>Card</Text>
|
|
125
|
+
</Frame>
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
export default () => (
|
|
129
|
+
<Frame style={{ gap: 16, flexDirection: 'row' }}>
|
|
130
|
+
<Card /> {/* Creates Component */}
|
|
131
|
+
<Card /> {/* Creates Instance */}
|
|
132
|
+
<Card /> {/* Creates Instance */}
|
|
133
|
+
</Frame>
|
|
134
|
+
)
|
|
117
135
|
```
|
|
118
136
|
|
|
119
|
-
|
|
137
|
+
### Component Variants
|
|
120
138
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
139
|
+
`defineComponentSet` creates a Figma ComponentSet with all variant combinations:
|
|
140
|
+
|
|
141
|
+
```tsx
|
|
142
|
+
import { defineComponentSet, Frame, Text } from '@dannote/figma-use/render'
|
|
143
|
+
|
|
144
|
+
const Button = defineComponentSet('Button', {
|
|
145
|
+
variant: ['Primary', 'Secondary'] as const,
|
|
146
|
+
size: ['Small', 'Large'] as const,
|
|
147
|
+
}, ({ variant, size }) => (
|
|
148
|
+
<Frame style={{
|
|
149
|
+
padding: size === 'Large' ? 16 : 8,
|
|
150
|
+
backgroundColor: variant === 'Primary' ? '#3B82F6' : '#E5E7EB',
|
|
151
|
+
borderRadius: 8,
|
|
152
|
+
}}>
|
|
153
|
+
<Text style={{ color: variant === 'Primary' ? '#FFF' : '#111' }}>
|
|
154
|
+
{variant} {size}
|
|
155
|
+
</Text>
|
|
156
|
+
</Frame>
|
|
157
|
+
))
|
|
158
|
+
|
|
159
|
+
export default () => (
|
|
160
|
+
<Frame style={{ gap: 16, flexDirection: 'column' }}>
|
|
161
|
+
<Button variant="Primary" size="Large" />
|
|
162
|
+
<Button variant="Secondary" size="Small" />
|
|
163
|
+
</Frame>
|
|
164
|
+
)
|
|
128
165
|
```
|
|
129
166
|
|
|
130
|
-
|
|
167
|
+
This creates 4 variant components (Primary/Small, Primary/Large, Secondary/Small, Secondary/Large) inside a ComponentSet, plus instances with the requested variants.
|
|
131
168
|
|
|
132
|
-
|
|
133
|
-
figma-use create rect --x 0 --y 0 --width 100 --height 50 [--fill --stroke --radius]
|
|
134
|
-
figma-use create ellipse --x 0 --y 0 --width 100 --height 100 [--fill]
|
|
135
|
-
figma-use create line --x 0 --y 0 --length 100 [--stroke]
|
|
136
|
-
figma-use create polygon --x 0 --y 0 --size 60 --sides 6 [--fill]
|
|
137
|
-
figma-use create star --x 0 --y 0 --size 60 --points 5 [--fill]
|
|
138
|
-
figma-use create vector --x 0 --y 0 --path "M0,0 L100,100"
|
|
139
|
-
```
|
|
169
|
+
### Variable Bindings
|
|
140
170
|
|
|
141
|
-
|
|
171
|
+
Bind colors to Figma variables by name:
|
|
142
172
|
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
173
|
+
```tsx
|
|
174
|
+
import { defineVars, Frame, Text } from '@dannote/figma-use/render'
|
|
175
|
+
|
|
176
|
+
const colors = defineVars({
|
|
177
|
+
bg: { name: 'Colors/Gray/50', value: '#F8FAFC' },
|
|
178
|
+
text: { name: 'Colors/Gray/900', value: '#0F172A' },
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
export default () => (
|
|
182
|
+
<Frame style={{ backgroundColor: colors.bg }}>
|
|
183
|
+
<Text style={{ color: colors.text }}>Bound to variables</Text>
|
|
184
|
+
</Frame>
|
|
185
|
+
)
|
|
150
186
|
```
|
|
151
187
|
|
|
152
|
-
|
|
188
|
+
The `value` is a fallback. At render time, colors get bound to actual Figma variables by name.
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## CLI Commands
|
|
193
|
+
|
|
194
|
+
The `render` command is the fastest way to create complex layouts. For simpler operations or modifications, use direct commands:
|
|
195
|
+
|
|
196
|
+
### Create
|
|
153
197
|
|
|
154
198
|
```bash
|
|
155
|
-
figma-use create
|
|
156
|
-
|
|
199
|
+
figma-use create frame --width 400 --height 300 --fill "#FFF" --radius 12 --layout VERTICAL --gap 16
|
|
200
|
+
figma-use create rect --width 100 --height 50 --fill "#FF0000" --radius 8
|
|
201
|
+
figma-use create ellipse --width 80 --height 80 --fill "#00FF00"
|
|
202
|
+
figma-use create text --text "Hello" --fontSize 24 --fill "#000"
|
|
203
|
+
figma-use create line --length 100 --stroke "#000"
|
|
204
|
+
figma-use create component --width 200 --height 100
|
|
205
|
+
figma-use create instance --component <id>
|
|
157
206
|
```
|
|
158
207
|
|
|
159
|
-
###
|
|
208
|
+
### Modify
|
|
160
209
|
|
|
161
210
|
```bash
|
|
162
211
|
figma-use set fill <id> "#FF0000"
|
|
163
|
-
figma-use set stroke <id> "#000"
|
|
164
|
-
figma-use set radius <id>
|
|
165
|
-
figma-use set radius <id> --topLeft 16 --bottomRight 16
|
|
212
|
+
figma-use set stroke <id> "#000" --weight 2
|
|
213
|
+
figma-use set radius <id> 12
|
|
166
214
|
figma-use set opacity <id> 0.5
|
|
167
|
-
figma-use set rotation <id> 45
|
|
168
|
-
figma-use set visible <id> false
|
|
169
215
|
figma-use set text <id> "New text"
|
|
170
216
|
figma-use set font <id> --family "Inter" --style "Bold" --size 20
|
|
171
|
-
figma-use set effect <id> --type DROP_SHADOW --radius 10 --offsetY 4 --color "#00000040"
|
|
172
217
|
figma-use set layout <id> --mode VERTICAL --gap 12 --padding 16
|
|
173
|
-
figma-use set
|
|
174
|
-
figma-use set constraints <id> --horizontal CENTER --vertical MAX
|
|
175
|
-
figma-use set image <id> image.png [--mode FILL]
|
|
218
|
+
figma-use set effect <id> --type DROP_SHADOW --radius 10 --color "#00000040"
|
|
176
219
|
```
|
|
177
220
|
|
|
178
|
-
###
|
|
221
|
+
### Query
|
|
179
222
|
|
|
180
223
|
```bash
|
|
181
|
-
figma-use
|
|
182
|
-
figma-use
|
|
183
|
-
figma-use
|
|
184
|
-
figma-use
|
|
185
|
-
figma-use
|
|
186
|
-
figma-use
|
|
187
|
-
|
|
188
|
-
figma-use collection list
|
|
189
|
-
figma-use collection get <id>
|
|
190
|
-
figma-use collection create "Colors"
|
|
191
|
-
figma-use collection delete <id>
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
### Styles
|
|
195
|
-
|
|
196
|
-
```bash
|
|
197
|
-
figma-use style list
|
|
198
|
-
figma-use style create-paint "Brand/Primary" --color "#E11D48"
|
|
199
|
-
figma-use style create-text "Heading/H1" --family "Inter" --style "Bold" --size 32
|
|
200
|
-
figma-use style create-effect "Shadow/Medium" --type DROP_SHADOW --radius 8 --offsetY 4
|
|
224
|
+
figma-use node get <id> # Get node properties
|
|
225
|
+
figma-use node tree # Page structure as readable tree
|
|
226
|
+
figma-use node children <id> # List children
|
|
227
|
+
figma-use find --name "Button" # Find by name
|
|
228
|
+
figma-use find --type FRAME # Find by type
|
|
229
|
+
figma-use selection get # Current selection
|
|
201
230
|
```
|
|
202
231
|
|
|
203
232
|
### Export
|
|
204
233
|
|
|
205
234
|
```bash
|
|
206
|
-
figma-use export node <id>
|
|
207
|
-
figma-use export
|
|
208
|
-
figma-use export
|
|
235
|
+
figma-use export node <id> --output design.png
|
|
236
|
+
figma-use export screenshot --output viewport.png
|
|
237
|
+
figma-use export selection --output selection.png
|
|
209
238
|
```
|
|
210
239
|
|
|
211
|
-
|
|
240
|
+
### Navigate
|
|
212
241
|
|
|
213
242
|
```bash
|
|
214
|
-
figma-use export node <id> --scale 10 --force
|
|
215
|
-
```
|
|
216
|
-
|
|
217
|
-
Heavy operations support `--timeout` (seconds):
|
|
218
|
-
```bash
|
|
219
|
-
figma-use export node <id> --scale 2 --output large.png --timeout 300
|
|
220
|
-
```
|
|
221
|
-
|
|
222
|
-
### Selection & Navigation
|
|
223
|
-
|
|
224
|
-
```bash
|
|
225
|
-
figma-use selection get
|
|
226
|
-
figma-use selection set "1:2,1:3,1:4"
|
|
227
|
-
|
|
228
243
|
figma-use page list
|
|
229
|
-
figma-use page set
|
|
230
|
-
|
|
231
|
-
figma-use viewport get
|
|
232
|
-
figma-use viewport set --x 100 --y 200 --zoom 0.5
|
|
244
|
+
figma-use page set "Page Name"
|
|
233
245
|
figma-use viewport zoom-to-fit <ids...>
|
|
234
246
|
```
|
|
235
247
|
|
|
236
|
-
###
|
|
237
|
-
|
|
238
|
-
```bash
|
|
239
|
-
figma-use find --name "Button"
|
|
240
|
-
figma-use find --name "Icon" --type FRAME
|
|
241
|
-
figma-use find --type INSTANCE --limit 50 # Limit results (default: 100)
|
|
242
|
-
figma-use get pages
|
|
243
|
-
figma-use get components --name "Button" # Filter by name
|
|
244
|
-
figma-use get components --limit 50 # Limit results (default: 50)
|
|
245
|
-
figma-use get styles
|
|
246
|
-
```
|
|
247
|
-
|
|
248
|
-
### Boolean & Group
|
|
249
|
-
|
|
250
|
-
```bash
|
|
251
|
-
figma-use boolean union "1:2,1:3"
|
|
252
|
-
figma-use boolean subtract "1:2,1:3"
|
|
253
|
-
figma-use boolean intersect "1:2,1:3"
|
|
254
|
-
figma-use boolean exclude "1:2,1:3"
|
|
255
|
-
|
|
256
|
-
figma-use group create "1:2,1:3"
|
|
257
|
-
figma-use group ungroup <id>
|
|
258
|
-
figma-use group flatten "1:2,1:3"
|
|
259
|
-
```
|
|
260
|
-
|
|
261
|
-
### Render React Components
|
|
262
|
-
|
|
263
|
-
Render TSX/JSX components directly to Figma via WebSocket (bypasses plugin API for ~100x speed):
|
|
248
|
+
### Variables & Styles
|
|
264
249
|
|
|
265
250
|
```bash
|
|
266
|
-
|
|
267
|
-
figma-use
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
figma-use render ./Card.figma.tsx --props '{"title": "Hello", "items": ["A", "B"]}'
|
|
271
|
-
|
|
272
|
-
# JSX snippet from stdin
|
|
273
|
-
echo '<Frame style={{width: 200, height: 100, backgroundColor: "#FF0000"}} />' | figma-use render --stdin
|
|
274
|
-
|
|
275
|
-
# Nested elements
|
|
276
|
-
echo '<Frame style={{padding: 20, gap: 10}}>
|
|
277
|
-
<Text style={{fontSize: 24}}>Title</Text>
|
|
278
|
-
<Rectangle style={{width: 100, height: 50, backgroundColor: "#3B82F6"}} />
|
|
279
|
-
</Frame>' | figma-use render --stdin
|
|
280
|
-
|
|
281
|
-
# Full component from stdin (with imports/exports)
|
|
282
|
-
cat component.tsx | figma-use render --stdin
|
|
283
|
-
|
|
284
|
-
# Into specific parent
|
|
285
|
-
figma-use render ./Card.figma.tsx --parent "1:23"
|
|
286
|
-
|
|
287
|
-
# Dry run (output NodeChanges JSON without sending)
|
|
288
|
-
figma-use render ./Card.figma.tsx --dryRun
|
|
289
|
-
```
|
|
290
|
-
|
|
291
|
-
**Important:** The `render` command requires:
|
|
292
|
-
1. Figma running with remote debugging: `figma --remote-debugging-port=9222`
|
|
293
|
-
2. Proxy server running: `figma-use proxy`
|
|
294
|
-
|
|
295
|
-
The proxy maintains persistent WebSocket connections for fast repeated renders:
|
|
296
|
-
- First render: ~4s (establishes connection)
|
|
297
|
-
- Subsequent renders: ~0.4s (reuses connection)
|
|
298
|
-
|
|
299
|
-
Example component (`Card.figma.tsx`):
|
|
300
|
-
|
|
301
|
-
```tsx
|
|
302
|
-
import * as React from 'react'
|
|
303
|
-
import { Frame, Text, Rectangle } from '@dannote/figma-use/components'
|
|
304
|
-
|
|
305
|
-
interface CardProps {
|
|
306
|
-
title: string
|
|
307
|
-
items: string[]
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
export default function Card({ title, items }: CardProps) {
|
|
311
|
-
return (
|
|
312
|
-
<Frame name="Card" style={{
|
|
313
|
-
width: 300,
|
|
314
|
-
flexDirection: 'column',
|
|
315
|
-
padding: 24,
|
|
316
|
-
gap: 16,
|
|
317
|
-
backgroundColor: '#FFFFFF',
|
|
318
|
-
borderRadius: 12,
|
|
319
|
-
}}>
|
|
320
|
-
<Text name="Title" style={{ fontSize: 24, fontWeight: 'bold', color: '#000' }}>
|
|
321
|
-
{title}
|
|
322
|
-
</Text>
|
|
323
|
-
<Frame name="Items" style={{ flexDirection: 'column', gap: 8 }}>
|
|
324
|
-
{items.map((item, i) => (
|
|
325
|
-
<Text key={i} style={{ fontSize: 16, color: '#666' }}>{item}</Text>
|
|
326
|
-
))}
|
|
327
|
-
</Frame>
|
|
328
|
-
</Frame>
|
|
329
|
-
)
|
|
330
|
-
}
|
|
251
|
+
figma-use variable list
|
|
252
|
+
figma-use variable create "Primary" --collection <id> --type COLOR --value "#3B82F6"
|
|
253
|
+
figma-use style list
|
|
254
|
+
figma-use style create-paint "Brand/Primary" --color "#E11D48"
|
|
331
255
|
```
|
|
332
256
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
### Advanced
|
|
257
|
+
### Escape Hatch
|
|
336
258
|
|
|
337
259
|
```bash
|
|
338
|
-
# Execute arbitrary JavaScript in Figma
|
|
339
260
|
figma-use eval "return figma.currentPage.name"
|
|
340
|
-
figma-use eval "
|
|
341
|
-
figma-use eval "await figma.loadFontAsync({family: 'Inter', style: 'Bold'})"
|
|
342
|
-
|
|
343
|
-
# Import SVG
|
|
344
|
-
figma-use import --svg "<svg>...</svg>" --x 0 --y 0
|
|
345
|
-
```
|
|
346
|
-
|
|
347
|
-
### Performance Profiling
|
|
348
|
-
|
|
349
|
-
Profile any command using Chrome DevTools Protocol:
|
|
350
|
-
|
|
351
|
-
```bash
|
|
352
|
-
# Start Figma with debug port
|
|
353
|
-
/Applications/Figma.app/Contents/MacOS/Figma --remote-debugging-port=9222
|
|
354
|
-
|
|
355
|
-
# Profile a command
|
|
356
|
-
figma-use profile "get components --limit 20"
|
|
357
|
-
figma-use profile "node tree --depth 2"
|
|
358
|
-
figma-use profile "find --type INSTANCE"
|
|
261
|
+
figma-use eval "figma.createRectangle().resize(100, 100)"
|
|
359
262
|
```
|
|
360
263
|
|
|
361
|
-
|
|
264
|
+
---
|
|
362
265
|
|
|
363
|
-
## Output
|
|
266
|
+
## Output
|
|
364
267
|
|
|
365
268
|
Human-readable by default:
|
|
366
269
|
|
|
367
|
-
```
|
|
368
|
-
$ figma-use
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
$ figma-use node children "1:2"
|
|
375
|
-
[0] frame "Header" (1:3)
|
|
376
|
-
box: 1200x80 at (0, 0)
|
|
377
|
-
fill: #FFFFFF
|
|
378
|
-
|
|
379
|
-
[1] text "Title" (1:4)
|
|
380
|
-
box: 200x32 at (20, 24)
|
|
381
|
-
font: 24px
|
|
270
|
+
```
|
|
271
|
+
$ figma-use node tree
|
|
272
|
+
[0] frame "Card" (1:23)
|
|
273
|
+
400×300 at (0, 0) | fill: #FFFFFF | layout: col gap=16
|
|
274
|
+
[0] text "Title" (1:24)
|
|
275
|
+
"Hello World" | 24px Inter Bold
|
|
382
276
|
```
|
|
383
277
|
|
|
384
|
-
Add `--json` for machine
|
|
278
|
+
Add `--json` for machine parsing:
|
|
385
279
|
|
|
386
280
|
```bash
|
|
387
|
-
|
|
388
|
-
{
|
|
389
|
-
"id": "1:2",
|
|
390
|
-
"name": "Frame",
|
|
391
|
-
"type": "FRAME",
|
|
392
|
-
...
|
|
393
|
-
}
|
|
281
|
+
figma-use node get <id> --json
|
|
394
282
|
```
|
|
395
283
|
|
|
396
|
-
## Environment Variables
|
|
397
|
-
|
|
398
|
-
| Variable | Default | Description |
|
|
399
|
-
|----------|---------|-------------|
|
|
400
|
-
| `PORT` | 38451 | Proxy server port |
|
|
401
|
-
| `FIGMA_PROXY_URL` | `http://localhost:38451` | Proxy URL for CLI |
|
|
402
|
-
|
|
403
284
|
## For AI Agents
|
|
404
285
|
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
### Using with Claude Code
|
|
408
|
-
|
|
409
|
-
Copy the included skill to teach your agent how to use figma-use:
|
|
286
|
+
**Includes ready-to-use [SKILL.md](./SKILL.md)** — a comprehensive reference that teaches AI agents all commands and patterns. Works with Claude Code, Cursor, and any agent that supports skill files.
|
|
410
287
|
|
|
411
288
|
```bash
|
|
412
|
-
#
|
|
289
|
+
# Claude Code / pi
|
|
413
290
|
mkdir -p ~/.claude/skills/figma-use
|
|
414
291
|
cp node_modules/@dannote/figma-use/SKILL.md ~/.claude/skills/figma-use/
|
|
415
292
|
|
|
416
|
-
# Or download directly
|
|
293
|
+
# Or download directly
|
|
417
294
|
curl -o ~/.claude/skills/figma-use/SKILL.md \
|
|
418
|
-
https://raw.githubusercontent.com/
|
|
295
|
+
https://raw.githubusercontent.com/anthropics/figma-use/main/SKILL.md
|
|
419
296
|
```
|
|
420
297
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
```
|
|
424
|
-
Create a card component with an avatar, title, and description in Figma
|
|
425
|
-
```
|
|
426
|
-
|
|
427
|
-
### Minimal Setup
|
|
428
|
-
|
|
429
|
-
For agents that don't support skills, add to your project's `CLAUDE.md` or `AGENTS.md`:
|
|
298
|
+
For simpler setups, add to your project's `AGENTS.md`:
|
|
430
299
|
|
|
431
300
|
```markdown
|
|
432
|
-
## Figma
|
|
301
|
+
## Figma
|
|
302
|
+
|
|
303
|
+
Use `figma-use` CLI. For complex layouts, use `figma-use render --stdin` with JSX.
|
|
304
|
+
Run `figma-use --help` for all commands.
|
|
305
|
+
```
|
|
433
306
|
|
|
434
|
-
|
|
307
|
+
## How It Works
|
|
435
308
|
|
|
436
|
-
Workflow:
|
|
437
|
-
1. `figma-use status` - Check plugin connection
|
|
438
|
-
2. `figma-use create frame --x 0 --y 0 --width 400 --height 300 --fill "#FFF" --name "Card"`
|
|
439
|
-
3. `figma-use create text --x 20 --y 20 --text "Title" --fontSize 24 --fill "#000" --parent "1:2"`
|
|
440
|
-
4. `figma-use export screenshot --output preview.png` - Verify result
|
|
441
309
|
```
|
|
310
|
+
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
|
311
|
+
│ AI Agent │────▶│ figma-use │────▶│ Plugin │
|
|
312
|
+
│ │ CLI │ proxy │ WS │ │
|
|
313
|
+
└─────────────┘ └──────┬──────┘ └─────────────┘
|
|
314
|
+
│
|
|
315
|
+
│ WebSocket (multiplayer)
|
|
316
|
+
▼
|
|
317
|
+
┌─────────────┐
|
|
318
|
+
│ Figma │
|
|
319
|
+
│ Server │
|
|
320
|
+
└─────────────┘
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
- **CLI commands** → Plugin API (full Figma access)
|
|
324
|
+
- **render command** → Multiplayer protocol (~100x faster, experimental)
|
|
442
325
|
|
|
443
326
|
## License
|
|
444
327
|
|