💡 摘要
figma-use 允许用户通过 CLI 控制 Figma 进行设计自动化和 JSX 渲染。
🎯 适合人群
🤖 AI 吐槽: “看起来很能打,但别让配置把人劝退。”
风险:Medium。建议检查:是否执行 shell/命令行指令;是否发起外网请求(SSRF/数据外发);文件读写范围与路径穿越风险;依赖锁定与供应链风险。以最小权限运行,并在生产环境启用前审计代码与依赖。
name: figma-use 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.
figma-use
CLI for Figma. Two modes: commands and JSX.
# Commands figma-use create frame --width 400 --height 300 --fill "#FFF" --layout VERTICAL --gap 16 figma-use create icon mdi:home --size 32 --color "#3B82F6" figma-use set fill 1:23 "$Colors/Primary" # JSX (props directly on elements, NOT style={{}}) echo '<Frame p={24} bg="#3B82F6" rounded={12}> <Text size={18} color="#FFF">Hello</Text> </Frame>' | figma-use render --stdin --x 100 --y 100
Before You Start
figma-use status # Check connection
If not connected — start Figma with remote debugging:
# macOS open -a Figma --args --remote-debugging-port=9222 # Windows "C:\Users\%USERNAME%\AppData\Local\Figma\Figma.exe" --remote-debugging-port=9222 # Linux figma --remote-debugging-port=9222
Start Figma with --remote-debugging-port=9222 and you're ready.
Two Modes
Imperative — single operations:
figma-use create frame --width 400 --height 300 --fill "#FFF" --radius 12 figma-use set fill <id> "#FF0000" figma-use node move <id> --x 100 --y 200
Declarative — render JSX trees:
echo '<Frame p={24} gap={16} flex="col" bg="#FFF" rounded={12}> <Text size={24} weight="bold" color="#000">Title</Text> <Text size={14} color="#666">Description</Text> </Frame>' | figma-use render --stdin --x 100 --y 200
stdin supports both pure JSX and full module syntax with imports:
import { Frame, Text, defineComponent } from 'figma-use/render' const Button = defineComponent( 'Button', <Frame bg="#3B82F6" p={12} rounded={6}> <Text color="#FFF">Click</Text> </Frame> ) export default () => ( <Frame flex="row" gap={8}> <Button /> <Button /> </Frame> )
Elements: Frame, Rectangle, Ellipse, Text, Line, Star, Polygon, Vector, Group, Icon, Image, Instance
Use <Instance> to create component instances:
<Frame flex="row" gap={8}> <Instance component="59763:10626" /> <Instance component="59763:10629" /> </Frame>
⚠️ Always use --x and --y to position renders. Don't stack everything at (0, 0).
Icons
150k+ icons from Iconify by name:
figma-use create icon mdi:home figma-use create icon lucide:star --size 48 --color "#F59E0B" figma-use create icon heroicons:bell-solid --component # as Figma component
In JSX:
<Icon name="mdi:home" size={24} color="#3B82F6" />
Images
Load images from URL:
<Image src="https://example.com/photo.jpg" w={200} h={150} />
Export JSX
Convert Figma nodes back to JSX code:
figma-use export jsx <id> # Minified figma-use export jsx <id> --pretty # Formatted # Format options figma-use export jsx <id> --pretty --semi --tabs # Match vector shapes to Iconify icons (requires: npm i whaticon) figma-use export jsx <id> --match-icons figma-use export jsx <id> --match-icons --icon-threshold 0.85 --prefer-icons lucide,tabler
Round-trip workflow:
# Export → edit → re-render figma-use export jsx <id> --pretty > component.tsx # ... edit the file ... figma-use render component.tsx --x 500 --y 0
Compare two nodes as JSX:
figma-use diff jsx <from-id> <to-id>
Export Storybook (Experimental)
Export all components on current page as Storybook stories:
figma-use export storybook # Output to ./stories/ figma-use export storybook --out ./src/stories # Custom output dir figma-use export storybook --match-icons # Match vectors to Iconify icons figma-use export storybook --no-semantic-html # Disable semantic HTML conversion
Semantic HTML: By default, components are converted to semantic HTML elements based on their names:
Input/*,TextField/*→<input type="text">Textarea/*→<textarea>Checkbox/*→<input type="checkbox">Radio/*→<input type="radio">Button/*→<button>Select/*,Dropdown/*→<select>
Use --no-semantic-html to disable this and keep <Frame> elements.
Generates .stories.tsx files:
- ComponentSets → React component with props + stories with args
- VARIANT properties → Union type props (
variant?: 'Primary' | 'Secondary') - TEXT properties → Editable string props (
label?: string) - Components grouped by
/prefix →Button/Primary,Button/Secondary→Button.stories.tsx
Example output for Button with variant and label:
// Button.tsx export interface ButtonProps { label?: string variant?: 'Primary' | 'Secondary' } export function Button({ label, variant }: ButtonProps) { if (variant === 'Primary') return ( <Frame> <Text>{label}</Text> </Frame> ) // ... } // Button.stories.tsx export const Primary: StoryObj<typeof Button> = { args: { label: 'Click', variant: 'Primary' } }
Variables as Tokens
Reference Figma variables in any color option with var:Name or $Name:
figma-use create rect --width 100 --height 100 --fill 'var:Colors/Primary' figma-use set fill <id> '$Brand/Accent'
In JSX:
<Frame bg="$Colors/Primary" /> <Text color="var:Text/Primary">Hello</Text>
Style Shorthands
Size & Position:
| Short | Full | Values |
|-------|------|--------|
| w, h | width, height | number or "fill" |
| minW, maxW | minWidth, maxWidth | number |
| minH, maxH | minHeight, maxHeight | number |
| x, y | position | number |
Layout:
| Short | Full | Values |
|-------|------|--------|
| flex | flexDirection | "row", "col" |
| gap | spacing | number |
| wrap | layoutWrap | true |
| justify | justifyContent | "start", "center", "end", "between" |
| items | alignItems | "start", "center", "end" |
| p, px, py | padding | number |
| pt, pr, pb, pl | padding sides | number |
| position | layoutPositioning | "absolute" |
| grow | layoutGrow | number |
| stretch | layoutAlign | true → STRETCH |
Appearance:
| Short | Full | Values |
|-------|------|--------|
| bg | fill | hex or $Variable |
| stroke | strokeColor | hex |
| strokeWidth | strokeWeight | number |
| strokeAlign | strokeAlign | "inside", "outside" |
| opacity | opacity | 0..1 |
| blendMode | blendMode | "multiply", etc. |
Corners:
| Short | Full | Values |
|-------|------|--------|
| rounded | cornerRadius | number |
| roundedTL/TR/BL/BR | individual corners | number |
| cornerSmoothing | squircle smoothing | 0..1 (iOS style) |
Effects:
| Short | Full | Values |
|-------|------|--------|
| shadow | dropShadow | "0px 4px 8px rgba(0,0,0,0.25)" |
| blur | layerBlur | number |
| overflow | clipsContent | "hidden" |
| rotate | rotation | degrees |
Text:
| Short | Full | Values |
|-------|------|--------|
| size | fontSize | number |
| weight | fontWeight | "bold", number |
| font | fontFamily | string |
| color | textColor | hex |
Grid (CSS Grid layout):
| Short | Full | Values |
|-------|------|--------|
| display | layoutMode | "grid" |
| cols | gridTemplateColumns | "100px 1fr auto" |
| rows | gridTemplateRows | "auto auto" |
| colGap | columnGap | number |
| rowGap | rowGap | number |
Components (via .figma.tsx)
First call creates master, rest create instances:
import { defineComponent, Frame, Text } from 'figma-use/render' const Card = defineComponent( 'Card', <Frame p={24} bg="#FFF" rounded={12}> <Text size={18} color="#000"> Card </Text> </Frame> ) export default () => ( <Frame gap={16} flex="row"> <Card /> <Card /> </Frame> )
figma-use render ./Card.figma.tsx --x 100 --y 200 figma-use render --examples # Full API reference
Variants (ComponentSet)
import { defineComponentSet, Frame, Text } from 'figma-use/render' const Button = defineComponentSet( 'Button', { variant: ['Primary', 'Secondary'] as const, size: ['Small', 'Large'] as const }, ({ variant, size }) => ( <Frame p={size === 'Large' ? 16 : 8} bg={variant === 'Primary' ? '#3B82F6' : '#E5E7EB'} rounded={8} > <Text color={variant === 'Primary' ? '#FFF' : '#111'}> {variant} {size} </Text> </Frame> ) )
Creates real ComponentSet with all combinations.
Diffs
Compare frames and generate patch:
figma-use diff create --from <id1> --to <id2>
--- /Card/Header #123:457 +++ /Card/Header #789:013 type: FRAME size: 200 50 -fill: #FFFFFF +fill: #F0F0F0
⚠️ Context lines need space prefix: size: 200 50 not size: 200 50
Apply with validation:
figma-use diff apply patch.diff # Fails if old values don't match figma-use diff apply patch.diff --dry-run # Preview figma-use diff apply patch.diff --force # Skip validation
Visual diff (red = changed pixels):
figma-use diff visual --from <id1> --to <id2> --output diff.png
⚠️ After initial render, use diffs or direct commands. Don't re-render full JSX trees.
Query (XPath)
Find nodes using XPath selectors:
figma-use query "//FRAME" # All frames figma-use query "//FRAME[@width < 300]" # Frames narrower than 300px figma-use query "//COMPONENT[starts-with(@name, 'Button')]" # Name starts with figma-use query "//FRAME[contains(@name, 'Card')]" # Name contains figma-use query "//SECTION/FRAME" # Direct children figma-use query "//SECTION//TEXT" # All descendants figma-use query "//*[@cornerRadius > 0]" # Any node with radius figma-use query "//FRAME[@width > 100 and @width < 500]" # Range
Attributes: name, width, height, x, y, `cornerRadi
优点
- 通过 CLI 简化设计任务。
- 支持命令式和声明式模式。
- 与 JSX 集成以进行组件渲染。
缺点
- 需要 Figma 以远程调试模式运行。
- 非技术用户的学习曲线。
- 仅限于 Figma 的功能。
相关技能
免责声明:本内容来源于 GitHub 开源项目,仅供展示和评分分析使用。
版权归原作者所有 dannote.
