AI-driven Figma design automation. Any LLM coding assistant writes Figma Plugin API scripts, a persistent Playwright/Firefox session pastes them into the Scripter plugin, and the result appears on the Figma canvas.
To build UI: write JS to
/tmp/<name>.js, run./bin/figma-run /tmp/<name>.js, readresult.png. That's the entire loop.
AI agents: read
AGENTS.md— tool-agnostic workflow usable from Claude Code, Cursor, Aider, Windsurf, Continue.dev, Copilot, or any model API client.
Claude Code → run.py (Playwright/Firefox) → Figma Scripter → Figma canvas
run.pylaunches Firefox, signs into Figma, and opens the Scripter plugin.- Claude Code sends Plugin API scripts through a named pipe (
/tmp/claude-figma.fifo). - Scripter runs the code inside Figma — creating frames, components, text, Auto Layout.
- Canvas state is read back via
output.txtdumps fromprint()/figma.notify()(no screenshots by default).
- Python 3.10+
- Playwright (
pip install playwright && playwright install firefox) - A Figma account with the Scripter plugin installed.
Keyboard shortcuts are OS-aware out of the box: Cmd on macOS, Ctrl on Linux/Windows.
No display or sandbox fiddling needed. Firefox runs natively with a visible window.
pip install playwright
playwright install firefoxThen jump to Starting the server below — python run.py --ensure URL just works.
Playwright's Firefox needs a display. Either run on a workstation (X/Wayland already available) or use Xvfb on a headless server.
# Playwright
pip install playwright
playwright install firefox
playwright install-deps # grabs system libs (libgtk, etc.)
# If AppArmor blocks unprivileged user namespaces (Ubuntu 23+):
sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
# Headless display (only if no X server)
sudo apt install xvfb
Xvfb :99 -screen 0 1920x1080x24 &Prepend DISPLAY=:99 to the run.py command when using Xvfb.
Not actively tested. In theory works the same as macOS/Linux (Playwright supports Windows). Run PowerShell / cmd with the same pip install playwright && playwright install firefox incantation. run.py treats Windows like Linux for keyboard shortcuts (Ctrl).
Idempotent — safe to call on every turn. If the fifo exists, it exits in under a second.
# No credentials: opens the login page and waits up to 5 min for you to finish manually
python run.py --ensure "FIGMA_FILE_URL"
# With credentials: fills the email/password form automatically
python run.py --ensure "FIGMA_FILE_URL" EMAIL PASSWORD
# Manual foreground start (blocks the terminal until shutdown)
python run.py --serve "FIGMA_FILE_URL"On Linux with Xvfb prefix: DISPLAY=:99 python run.py --ensure "FIGMA_FILE_URL".
Priority order:
.auth-state.jsonexists → session is restored, no login step.- Credentials passed on CLI → email/password form is auto-filled; we wait up to 2 min for the post-login redirect.
- No credentials → the login page opens and the server waits up to 5 min for you to finish in the browser. Google, SSO, 2FA, or plain password all work. Session is saved after any successful login.
# Inline
python run.py "figma.createRectangle()"
# From a file (recommended for anything non-trivial)
python run.py --file script.jsAfter each run:
output.txt— capturedprint()/figma.notify()text.result.png— full-page screenshot (only consult when visual verification is needed)./tmp/claude-figma.log— server log;tailforOKorError:.
# Invoke any Figma plugin (optionally select an action within it)
python run.py "__plugin__:Propstar > Create property table"
# Other plugins steal focus from Scripter — re-open it
python run.py "__reopen_scripter__"run.py — Playwright server: browser automation + fifo listener
scripter.md — Code-generation rules for Figma Scripter
add-component.md — Universal pipeline for adding components from code to Figma
pdf-import.md — Pipeline for importing PDF presentations into Figma
figma-comments.md — Figma REST API comments → Scripter edits
AGENTS.md — Single source of instructions for all AI agents
plugin/ — Custom Figma plugin (alternative to Scripter)
code.js — Plugin backend (eval + print capture)
ui.html — Plugin UI (code editor + output)
manifest.json — Plugin manifest
- Two-step builds. Create the visual structure first (Step 1, hardcoded RGB colours), bind Figma variables second (Step 2,
findOne/findAllby node name). Mixing them in one script triggers silent failures. - No screenshots by default. Verify canvas state through
print()dumps — cheaper, more reliable, token-efficient. - Atomic components. Complex components are assembled from instances of atomic components. Style bindings live on the atoms; instances inherit automatically.
- Figma Variables. All colours, radii, sizes bind to Figma Variables via
setBoundVariableForPaint()(fills/strokes) andsetBoundVariable()(numerics). - Text Styles. All text uses local Figma Text Styles (
body/sm/medium,heading/h1/bold, etc.). - Propstar. After creating a Component Set, run Propstar to lay variants out in a grid.
- Clipboard paste. Scripts are injected via
navigator.clipboard.writeText+ the OS paste shortcut (Cmd+V on macOS, Ctrl+V elsewhere).
See scripter.md for the full ruleset that prevents runtime crashes:
- Load fonts before any text operation.
appendChild()beforeresize()or layout properties.- Set
layoutModebefore any Auto Layout props. - Colours in RGB 0–1, not hex.
findOne()for text overrides in instances.
See figma-comments.md — read comments via REST API and apply fixes through Scripter:
Fetch unresolved comments → Parse → Apply via Scripter → Verify
Requires a Figma Personal Access Token (create one at https://www.figma.com/developers/api#access-tokens).
See pdf-import.md:
Read PDF → Analyse slides → 1 script per slide → Verify
Text is preserved in full; images and charts become placeholder rectangles. Each slide becomes a 1920×1080 frame.
See add-component.md:
Read source code → Step 1 (create) → Verify sizes →
Step 2 (bind variables) → Verify bindings → Propstar
Includes colour/radius/text-style mappings, helpers (bF(), bS(), bN(), bT(), bR(), bE()), and a common-mistakes table.
MIT