Co-Pilot
Updated 24 days ago

figma-use

Ddannote
0.4k
dannote/figma-use
82
Agent Score

💡 Summary

Figma-use allows users to control Figma via CLI for design automation and JSX rendering.

🎯 Target Audience

UI/UX DesignersFront-end DevelopersProduct ManagersDesign Automation EngineersFigma Enthusiasts

🤖 AI Roast:Powerful, but the setup might scare off the impatient.

Security AnalysisMedium Risk

Risk: Medium. Review: shell/CLI command execution; outbound network access (SSRF, data egress); filesystem read/write scope and path traversal; dependency pinning and supply-chain risk. Run with least privilege and audit before enabling in production.


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/SecondaryButton.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

5-Dim Analysis
Clarity9/10
Novelty7/10
Utility8/10
Completeness9/10
Maintainability8/10
Pros & Cons

Pros

  • Streamlines design tasks through CLI.
  • Supports both imperative and declarative modes.
  • Integrates with JSX for component rendering.

Cons

  • Requires Figma to run with remote debugging.
  • Learning curve for non-technical users.
  • Limited to Figma's capabilities.

Related Skills

flutter-claude-code

A
toolCo-Pilot
82/ 100

“Powerful, but the setup might scare off the impatient.”

design-tokens-skill

A
toolCo-Pilot
82/ 100

“Powerful, but the setup might scare off the impatient.”

claude-designer-skill

A
toolCo-Pilot
82/ 100

“Powerful, but the setup might scare off the impatient.”

Disclaimer: This content is sourced from GitHub open source projects for display and rating purposes only.

Copyright belongs to the original author dannote.