Markdown Converter
Agent skill for markdown-converter
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.
Sign in to like and favorite skills
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
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.
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
and --x
to position renders. Don't stack everything at (0, 0).--y
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" />
Load images from URL:
<Image src="https://example.com/photo.jpg" w={200} h={150} />
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 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:
variant?: 'Primary' | 'Secondary')label?: string)/ prefix → Button/Primary, Button/Secondary → Button.stories.tsxExample 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' } }
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>
Size & Position:
| Short | Full | Values |
|---|---|---|
, | width, height | number or |
, | minWidth, maxWidth | number |
, | minHeight, maxHeight | number |
, | position | number |
Layout:
| Short | Full | Values |
|---|---|---|
| flexDirection | , |
| spacing | number |
| layoutWrap | |
| justifyContent | , , , |
| alignItems | , , |
, , | padding | number |
, , , | padding sides | number |
| layoutPositioning | |
| layoutGrow | number |
| layoutAlign | → STRETCH |
Appearance:
| Short | Full | Values |
|---|---|---|
| fill | hex or |
| strokeColor | hex |
| strokeWeight | number |
| strokeAlign | , |
| opacity | 0..1 |
| blendMode | , etc. |
Corners:
| Short | Full | Values |
|---|---|---|
| cornerRadius | number |
| individual corners | number |
| squircle smoothing | 0..1 (iOS style) |
Effects:
| Short | Full | Values |
|---|---|---|
| dropShadow | |
| layerBlur | number |
| clipsContent | |
| rotation | degrees |
Text:
| Short | Full | Values |
|---|---|---|
| fontSize | number |
| fontWeight | , number |
| fontFamily | string |
| textColor | hex |
Grid (CSS Grid layout):
| Short | Full | Values |
|---|---|---|
| layoutMode | |
| gridTemplateColumns | |
| gridTemplateRows | |
| columnGap | number |
| rowGap | number |
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
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.
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.
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, cornerRadius, opacity, visible, characters, fontSize, layoutMode, itemSpacing
XPath functions:
contains(), starts-with(), string-length(), not(), and, or
# Create figma-use create frame --width 400 --height 300 --fill "#FFF" --layout VERTICAL --gap 16 figma-use create text --text "Hello" --font-size 24 --fill "#000" figma-use create rect --width 100 --height 50 --fill "#F00" --radius 8 # Find figma-use query "//FRAME[@name = 'Header']" figma-use find --name "Button" figma-use find --type FRAME figma-use selection get # Explore figma-use node ancestors <id> # Get parent chain (useful for navigation) figma-use node bindings <id> # Get variable bindings for fills/strokes figma-use page bounds # Find free space for new objects figma-use variable find "Text/Neutral" # Search variables by name # Modify figma-use set fill <id> "#FF0000" figma-use set radius <id> 12 figma-use set text <id> "New text" figma-use set text-resize <id> height # Wrap text (height auto, fixed width) figma-use set layout <id> --mode VERTICAL --gap 12 --padding 16 figma-use set layout <id> --mode GRID --cols "1fr 1fr 1fr" --rows "auto" --gap 16 figma-use node move <id> --x 100 --y 200 figma-use node resize <id> --width 300 --height 200 figma-use node delete <id> [id2...] figma-use arrange # Tidy up overlapping frames on canvas figma-use node to-component <id> # Export figma-use export node <id> --output design.png figma-use export screenshot --output viewport.png # Navigate figma-use page list figma-use page set "Page Name" figma-use viewport zoom-to-fit <id>
Full reference: REFERENCE.md
Discovery tools for understanding design systems:
# Repeated patterns — potential components figma-use analyze clusters figma-use analyze clusters --min-count 5 # Color palette figma-use analyze colors # Usage frequency figma-use analyze colors --show-similar # Find similar colors to merge # Typography figma-use analyze typography # All font combinations figma-use analyze typography --group-by size # Spacing figma-use analyze spacing --grid 8 # Check 8px grid compliance # Accessibility snapshot — extract interactive elements figma-use analyze snapshot # Full page figma-use analyze snapshot <id> -i # Interactive only (buttons, inputs, etc.) figma-use analyze snapshot --depth 6 # Limit depth
Use cases:
Output shows counts, examples, and warnings (e.g., off-grid spacing, hardcoded colors).
Check designs for consistency and accessibility issues:
figma-use lint # Recommended preset figma-use lint --page "Components" # Lint specific page figma-use lint --preset strict # Stricter rules figma-use lint --preset accessibility # A11y only (contrast, touch targets) figma-use lint --rule color-contrast # Single rule figma-use lint -v # With fix suggestions figma-use lint --json # For CI/CD figma-use lint --list-rules # Show all rules
Presets:
recommended, strict, accessibility, design-system
17 rules:
no-hardcoded-colors, consistent-spacing, consistent-radius, effect-style-requiredprefer-auto-layout, pixel-perfecttext-style-required, min-text-size, no-mixed-stylescolor-contrast, touch-target-sizeno-default-names, no-hidden-layers, no-deeply-nested, no-empty-frames, no-groupsno-detached-instancesExit code 1 if errors found — use in CI pipelines.
Human-readable by default — prefer this to save tokens. Use
--json only when you need to parse specific fields programmatically.
Format:
session:local (e.g., 1:23). Inside instances: I<instance-id>;<internal-id>.
Get IDs from
figma-use selection get or figma-use node tree.
Hex:
#RGB, #RRGGBB, #RRGGBBAA
Variables: var:Colors/Primary or $Colors/Primary
figma-use export node <id> --output /tmp/check.png
figma-use viewport zoom-to-fit <id>
echo '...' | figma-use render --stdin --x 0 --y 0 echo '...' | figma-use render --stdin --x 500 --y 0 # Not at same position!
After creating multiple frames/sections, run
arrange to spread them out:
figma-use arrange --mode grid --gap 60 # Grid layout (default) figma-use arrange --mode squarify --gap 60 # Smart packing for mixed sizes
figma-use node clone <id> [id2...] --json | jq -r '.[].id' figma-use node set-parent <new-id> --parent <target-page-id> figma-use node move <new-id> --x 50 --y 50
# Replace with component (creates instance) figma-use node replace-with <id> --target <component-id> # Replace with JSX from stdin echo '<Icon name="lucide:x" size={16} />' | figma-use node replace-with <id> --stdin
figma-use node to-component <id> figma-use node to-component "1:2 1:3 1:4" # Multiple
figma-use set text "I123:456;789:10" "New text" # I<instance>;<internal>
# ❌ Collapses to 1×1 <Frame flex="row" gap={8}> # ✅ Explicit width <Frame w={300} flex="row" gap={8}>
figma-use create section --name "Buttons" --x 0 --y 0 --width 600 --height 200 figma-use node set-parent <id> --parent <section-id>
⚠️ Deleting section deletes all children!
Wait for designer feedback and react:
figma-use comment watch --json
Output when comment arrives:
{ "id": "123456", "message": "Make this button bigger", "user": { "handle": "designer" }, "client_meta": { "node_id": "1:23" } }
Agent workflow — run once per comment, then restart:
figma-use comment watch --json — blocks until new commentmessage and target_node (exact element under comment)figma-use comment add "Done!" --reply <comment-id>figma-use comment resolve <comment-id>Options:
--timeout 60 — exit after 60s if no comment (returns {"timeout":true})--interval 5 — poll every 5s (default: 3s)Draw, screenshot, adjust, repeat — like a designer tweaking Bezier curves:
# 1. Draw initial shape figma-use create vector --path "M 50 0 L 100 100 L 0 100 Z" --fill "#F00" # 2. Check result figma-use export node <id> --output /tmp/shape.png # 3. Adjust: scale, move, flip figma-use path scale <id> --factor 0.8 figma-use path move <id> --dx 20 --dy -10 figma-use path flip <id> --axis x # 4. Or replace path entirely figma-use path set <id> "M 50 0 C 80 30 80 70 50 100 C 20 70 20 30 50 0 Z" # 5. Screenshot again, repeat until good figma-use export node <id> --output /tmp/shape.png
For complex illustrations, import SVG:
figma-use import --svg "$(cat icon.svg)"