Layerwright
Turn Claude Design and Claude Code designs into native, editable Figma files, and Figma designs into code that uses your own components.

Select a desktop screen in Figma, press Mobile in the Layerwright window and send it to a Claude Code session. The session builds 390 px mobile versions of two right-to-left Persian screens with Auto Layout, its cursor showing where it works. The window lists the connected sessions and each request's answer. (2× speed.)
npx layerwright init # in your project, then open the plugin in Figma desktop (see Quickstart)
Layerwright is an open-source MCP server and Figma plugin for Claude Code, Codex and Cursor. It imports HTML, such as a Claude Design "standalone HTML" export, into Figma as real frames with Auto Layout, text, images and vector icons. It builds new screens from your own Design System: real component instances, variables and text styles. And it works the other way: select a Figma frame and Claude implements it in your codebase with your existing components and tokens, then checks that it did.
Why
Claude Design exports to HTML, PDF, PPTX and Canva, but not to Figma. Claude Code can write UI code, but it has no native way to put a design into a Figma file your team can edit. Most "HTML to Figma" tools either paste a flat picture or need a cloud account.
Layerwright closes that gap locally:
- Claude Design to Figma: export standalone HTML, run one command, and you get editable Figma frames.
- Claude Code to Figma: ask Claude for a screen or a flow, and it is built from your Design System's components.
- Figma to code: select a frame, and Claude implements it with the React components you already have (not a new copy of each button), mapped once and shared with your team.
- Ask from Figma: select layers, press Mobile version or Build in code in the plugin window, and a session starts on it.
- No API keys, no cloud, no account. Everything runs on your machine. The plugin only talks to
localhost.
Features
Bring designs into Figma
- HTML to Figma import (
import_html_to_plan)- Flexbox becomes Auto Layout: direction, gap, padding, alignment and wrap. Fixed CSS sizes stay fixed.
- Colours, borders, radii, shadows, gradients, fonts, line height and letter spacing come across.
- Text with inline
<b>,<span>and<a>is one text layer with styled ranges. - Pictures come along: images (PNG, JPEG, GIF, WebP, AVIF), SVG files and inline SVG as vectors, sprite icons, CSS background images, CSS-mask icons in their colour, icon fonts and
<canvas>, in both modes. - Desktop (1440) and mobile (390) screens are rendered side by side.
- RTL is supported (Persian, Arabic, Hebrew). Rows keep their visual order and text stays right-aligned.
- Pixel-faithful mode (
figma_import_html) for review boards and art-heavy pages: exact layers, variant sets built from states, and instance swaps. - AI design to Figma from a prompt. Claude writes a typed Design Plan (a JSON DSL). The plan is validated and resolved against your components, variables and text styles, then built deterministically. Claude never writes Figma plugin code.
- Prototypes. Click, hover and timed interactions, navigate / overlay / swap / back, smart animate and push transitions, scrolling frames and flow starting points, in plans or on existing frames.
- Icons and pictures in one step (
figma_import_assets): a folder of SVGs becomes editable vectors (or components, named by their path), pictures become image layers, in a grid on the page. - No AI needed for a plain import.
npx layerwright import ./design.html --to-figmabuilds it in the open Figma file. - Fonts from exports:
npx layerwright fonts ./export --installinstalls the TTF/OTF fonts a design ships.
Use your Design System
- Design System automation. After a Design System scan, buttons, inputs and links become your real Figma components when they clearly match, and you can map any element yourself (
mappings: [{ selector, component }]). - Design System sync. After an import,
figma_analyze_design({ mode: "sync" })swaps buttons and pills for your DS components (the variant that looks closest), gives text your text styles by size and weight, and binds colours to your variables and styles. You approve it; originals are kept hidden. - Audit and fix existing frames. Hard-coded colours become variables, raw text gets text styles, and custom buttons become component instances, in groups you can pick. Originals are hidden, never deleted.
- Work on existing designs (
figma_edit). Rename, move, duplicate, delete, restyle (font weight, size and family, text and fill colours), and turn existing frames into components or variant sets with text properties, in one undo step. - Figma back to a plan. Any subtree exports as an editable Design Plan to clone, refactor or implement in code: layout, tokens, text styles, instances, gradients, shadows, blurs, shapes, and vectors or boolean shapes as SVG icons.
Figma to code
figma_inspect → code_scan_components → code_mapping → code_verify_usage
- Reads the frame as a plan: layout, spacing and colour tokens, text styles, and every component instance with its variant and properties.
- Scans your React / Next.js codebase for exported components (and Tailwind or shadcn/ui) and suggests which code component each Figma component is.
- The mappings you confirm are saved in
.layerwright/mapping.json; commit it and the whole team reuses them. - Claude implements the frame with the mapped components and your theme tokens;
code_verify_usagethen flags design components that weren't used, raw<button>/<input>duplicates, and arbitrary Tailwind values.
Work together with your agents
- Several sessions, several files. Claude Code, Codex and Cursor sessions on your computer share one connection to the plugin, with no port to configure. Open Layerwright in several Figma files at once: each stays connected, and each session works in one file (the one you send it a request from, or the one it's told to use). A change never lands in another file than the one the session works in. Sessions in a project that uses Layerwright join when they start; any other session joins on its first Figma call, and a session that hasn't used Layerwright for 30 minutes leaves until its next Figma call, so the plugin window lists only the sessions you use with Figma now, and what each is doing (sessions name themselves after their task). Your selection and requests from the window go to the session you pick there, until you pick another, and a session never overwrites a layer another one just changed.
- Ask from Figma. Select layers in the plugin window, pick a session and send a request: Build in code, Polish design, Make component, Mobile version, or your own words. A Claude Code session with the plugin starts on it by itself (the plugin's monitor wakes the session); Codex gets it on its next Figma step or with
/layer:inbox. Progress and the session's answer come back to the window. - Notes on the canvas. Type a text layer that starts with
@<session>(or@claudewhen one session is connected) on the frame it's about, and that session gets it like a request from the window. Only notes you type count: edits by collaborators and text Layerwright writes never start a task. - AI cursor and a working toast. While a session works in Figma, a cursor in its colour shows it like a collaborator's, from its first step to the end of the task: it reads where the session reads, drag-selects and works on what it changes, thinks between steps, and goes once the session is done or quiet. Its tag is one short line: the session's name and what it's doing. It stays on while you keep working in the file (select, edit, change page), so you always see which session is at work and where; while the session waits for your answer it waits still, just above the frame, and it never takes your selection. Every undo step is closed with the cursor taken off the canvas, so no step holds one. A toast at the bottom of the canvas says what a session is doing too; it is never a layer. Questions show in the plugin window and on the cursor (Settings → AI cursor turns both off).
- Figma links. Ask for a link to the selection, a frame, a section or a page (
figma_link); what a session builds or selects comes back with links. Paste a Figma link to a session and it finds the layer, opens its page and works in its file. - A guide in the window. The in the plugin window's header explains each tab, the actions and canvas notes. It opens by itself the first time.
Check, learn and stay safe
- You see what was built.
figma_export_imagerenders any node, and compares it with the source HTML (or another node) with a diff heatmap.save: truewrites the PNG to.layerwright/exports/so the agent can show it to you (/layer:shot). - Accessibility and critique. WCAG contrast (on the real background), touch-target and text-size checks, plus consistency signals; Claude uses them with a picture in a critique loop to polish what it builds.
- Safe by default.
- Every run is one undo step, and a failed run rolls back completely.
- Results are checked against the plan: structure, sizes, variants, text overrides and prototype links.
- Existing nodes change only after you approve; deleting without approval only hides and labels a layer.
- Everything Layerwright creates is tagged, so
figma_cleanupcan list and remove a session's leftovers. - Only your paired plugin window and your own sessions can use the local connection: web pages in your browser can't.
- Learns per project. Font substitutions, mappings and component choices are reused next time, your corrections are kept as notes, and recurring problems come with a hint (
.layerwright/memory.json, shareable).npx layerwright reportdrafts a redacted issue from them for you to send. - Updates in one step. When a newer Layerwright is out, Claude Code says so as a session starts (once a day), and so do the plugin window and
doctor./layer:update, the window's Update button (a session does it for you) ornpx -y layerwright@latest update(any folder) updates the Figma plugin, the/layercommands and the server they run; then/reload-plugins(or a new session) and reopen the plugin in Figma. - Your own skills. Next to the skills that ship with it, press Create a skill with Claude in the plugin window's Skills tab: say what it should do, and it opens Claude (the app, a terminal or VS Code) with
/layer:skills new …filled in, or asks a connected session, and Claude drafts it with you. You can also add one from a link, or write it yourself in the Skills tab (edit it there later). They stay on your computer across updates.
Quickstart (3 steps)
Requirements: Node.js 20+, Figma desktop, Claude Code or Codex (or Cursor: npx layerwright init --cursor).
# 1. In your project folder
npx layerwright init
init asks which agents get the Layerwright plugin (the ones it finds are preselected; --agents claude,codex or --no-agents skip the question), installs it with their own claude plugin / codex plugin commands, and pairs the Figma plugin with this computer.
- In Figma desktop (macOS or Windows: Figma has no desktop app for Linux, and the browser can't run development plugins), go to Plugins → Development → Import plugin from manifest…. The plugin sits in a hidden folder (
~/.layerwright/figma-plugin/manifest.json), soinitcopies that path to your clipboard and shows the folder: in the file dialog press ⌘⇧G (Windows: click the File name box), paste, Enter. You do this once; afterwards run Plugins → Development → Layerwright and keep its small window open.npx layerwright pluginshows these steps again. - Start a new Claude Code or Codex session, type
/layer:help, or ask:- "Import ./design.html into Figma": a Claude Design HTML export becomes editable frames.
- "Create a sign-up flow in Figma using our Design System": new screens built from your components.
- Select a frame in Figma, then "Implement the selected Figma frame in code using our components": Figma → code with your mapped React components and theme tokens, checked afterwards.
Requests from the Figma window wake a Claude Code session by themselves: the plugin runs a monitor (layerwright inbox-watch) whose notifications reach the session. npx layerwright claude also turns on Claude Code channels (a research preview; Team and Enterprise organizations must enable them first). In Codex a request waits for the session's next Figma step or /layer:inbox. On Windows, Claude Code's monitor needs Git for Windows (its Git Bash); without it a request waits for the session's next Figma step or /layer:inbox too.
Install from GitHub instead: claude plugin marketplace add shayan-m81/layerwright then claude plugin install layer@layerwright; for Codex, codex plugin marketplace add shayan-m81/layerwright then codex plugin add layer@layerwright. npx -y layerwright@latest update updates it (and the Figma plugin) later.
Another MCP client (Claude Desktop, VS Code, Windsurf)? Add the same layerwright server to its MCP config and start from its prompts: figma_design (the whole guide), html_to_figma, build_in_figma, change_figma or figma_to_code. They are built from the same skill, so every client follows the same workflow.
Want these rules always in Claude's context? Paste this prompt into your project's CLAUDE.md.
Something not working? Run npx layerwright doctor.
For HTML import, Layerwright needs a Chromium. It uses Google Chrome if you have it installed. Otherwise run npx layerwright doctor: it prints the exact command that installs the Chromium it needs (npx -y playwright-core@<version> install chromium; add --with-deps on a fresh Linux).
Want to try the conversion without Figma? npx layerwright import ./design.html prints what would be built.
Want it in Figma without Claude? Run the plugin, then npx layerwright import ./design.html --to-figma --page "Designs"
(--faithful for exact layers, --scan to use your Design System's components).
How it works
flowchart LR
A[Claude Code / Codex / Cursor] -- MCP / stdio --> B[layerwright server<br/>one per session]
H[HTML file or folder] -- headless Chromium --> B
B -- "Zod-validated Design Plan<br/>resolved against your DS" --> B
B -- ws://127.0.0.1 --> K[hub<br/>one per computer]
K -- ws://127.0.0.1 --> C[Figma plugin]
C -- "fixed Plugin API calls<br/>one undo step" --> D[(Figma file)]
- Plan. Claude, or the HTML importer, produces a Design Plan: a small, typed JSON DSL of screens, frames, text, components, tokens and images.
- Validate and resolve. The server checks the plan with Zod. It then resolves every component, variant, property, variable and text style against a cached scan of your Figma file. Unknown names come back as errors with suggestions and never reach Figma.
- Execute. The plugin builds the resolved plan with fixed Plugin API calls. There is no
evaland no model-written code. - Verify. The result is re-inspected and compared with the plan and, for HTML imports, with the page's rendered boxes.
figma_export_imageshows the result next to the source.
Every session reaches Figma through one small local process, the hub. The first session that needs it starts it, and it stops by itself a minute after the last session leaves. It routes each request to the right Figma file's plugin window and the answer back to the session that asked, so several agents can work in one file, or in several files at once.
Read more in docs/architecture.md. The DSL is documented in docs/dsl.md.
MCP tools
| Tool | What it does |
|---|---|
import_html_to_plan | HTML file or folder → editable Design Plan (Auto Layout, DS components, your own mappings). Returns a planId |
figma_execute_plan | Builds a plan in Figma: one undo step, rollback on failure, automatic verification |
figma_preview_plan | Validates and resolves a hand-written plan and returns a summary |
figma_edit | Rename, move, duplicate, set, delete, resize to fit, group / ungroup, boolean shapes, componentize (variants, text properties), swap instances, bind variables, apply styles, annotations, prototype links and flows |
figma_export_image | A node as an image; compared with the source HTML or another node, with a diff heatmap. save: true writes it to .layerwright/exports/ to show the user |
figma_inbox / figma_reply | Requests the user sent from the Figma window to this session, and the answer shown back in the window |
figma_status / figma_scan_design_system / figma_get_design_context | Connection, page and the open Figma files (file to switch), Design System scan (components, variants, variables, styles, duplicate names), task-scoped context |
figma_inspect / figma_verify / figma_select | Snapshots (tree, summary, text, instances, or the subtree as a plan, saved to a file with save), plan-vs-canvas checks, select and zoom (switches page) |
figma_link | Links to the selection, layers or the page, and the file's own link. Any layer argument also takes a Figma link |
figma_analyze_design / figma_apply_transformations | Audit a frame against the DS, or mode: "sync" after an import; apply the groups you approve |
figma_import_html / figma_pages / figma_foundations | Pixel-faithful import, page setup, variables and text styles |
figma_import_assets | Icons and pictures from files or folders: SVGs as vectors (or components), PNG/JPEG/GIF/WebP/AVIF as images, in a grid |
FAQ
Is this an official Anthropic or Figma product? No. It is an independent open-source project that works with Claude Code and Figma.
Does it need an API key, an account or a server?
No. Claude Code runs the MCP server locally, and the Figma plugin connects to it on localhost. Nothing is uploaded.
Can I use it without Claude Code?
Yes. npx layerwright import ./design.html --to-figma builds an HTML file in Figma with no AI at all, and any MCP client can call the tools. The skill and the design workflows (building from a prompt, componentizing, prototyping) are written for Claude Code.
Can it make prototypes?
Yes. Plans and figma_edit set click, hover, press, drag and timed interactions (navigate, overlay, swap, scroll to, change to, back, close, open URL) with transitions, scrolling frames and flow starting points. Overlays open centred: the Plugin API can't set their position.
Does it work with the official Figma MCP? It doesn't need it. If it's connected, Claude can use its library search to find a component your file doesn't use yet and pass its key to Layerwright.
Does the output use Auto Layout? Yes, where the HTML uses flexbox or evenly spaced stacks. Grid and overlapping layers become frames with absolutely positioned children, so the result still looks right.
Will it use my Design System?
Yes. Scan the file that has your components (figma_scan_design_system), and imported buttons, inputs and links become instances of them. Anything that doesn't match stays a styled frame.
Does it work with right-to-left languages? Yes. Direction, text alignment and row order are preserved. Fonts such as Vazirmatn are matched to their real style names.
Can a web page or another app talk to it?
No. The hub listens on 127.0.0.1 only and refuses browser connections. Sessions need the per-computer key that init creates (~/.layerwright/key), and only the plugin window paired with that key can send requests into your sessions. Canvas notes count only when you type them, not when a collaborator does.
Does it work in the Figma browser app? Development plugins need Figma desktop.
Troubleshooting
Start with npx layerwright doctor. It checks Node, .mcp.json, the skill, the plugin files, the running server, the plugin connection and Chromium, and it prints a fix for each problem. More cases are covered in docs/troubleshooting.md.
Limitations
- CSS grid, floats and transforms are imported as positioned layers, not as Auto Layout.
- Linear, radial and conic gradients and
blur()/backdrop-filter: blur()come across; other filters and blend modes are dropped in plan mode (the pixel-faithful mode keeps blend modes). Only the top background layer is used. - The largest corner radius is used when the four corners differ.
- The plan export keeps image fills by their hash, so they show only in the file they came from (a cropped image comes back as fill), keeps one colour, the top image and the top gradient when a layer stacks several fills, and turns a grid layout into a fixed frame with its children at their positions.
- Fonts must be installed on the machine that runs Figma. A missing family falls back to Inter, with a warning.
- Images must be PNG, JPEG or GIF (a Figma limit), up to 10 MB each.
- The scan finds library components only when an instance of them exists in the open file. Others can be used by key (e.g. found with the official Figma MCP's library search).
- Prototype overlays open centred (their position can't be set through the Plugin API). Plans can't hide instance layers by override yet.
- One Layerwright window per Figma file: running the plugin again in the same file hands over to the new window. Sessions from an older Layerwright are asked to update before they can join.
- Figma lets a development plugin read its file's link key; if it doesn't, paste one link from that file once and Layerwright remembers it.
- AI cursors are real, locked layers while a session works (Figma has no API for overlays), so collaborators in the file see them too. They are taken off the canvas around every undo step, so no step holds one, but an undo (⌘Z / Ctrl+Z) during a session's task may first take the cursor away instead of your own last edit, since the cursor keeps working on the frame and Figma counts a plugin's latest drawing as the newest change: press it once more. The cursor comes back with the session's next step.
Roadmap
- Per-corner radii, CSS grid → Auto Layout wrap
- Design tokens export (W3C format) and import
- Figma Community listing (plan)
- Instance-swap properties and hidden-layer overrides in plans
Contributing
Issues and pull requests are welcome. See CONTRIBUTING.md. To develop from a clone:
git clone https://github.com/shayan-m81/layerwright && cd layerwright
npm install && npm run build && npm test
npx tsx apps/mcp-server/src/cli.ts init # wires this checkout into the current folder
License
MIT © Shayan Montazeri
Keywords: claude design to figma, export claude design, claude code figma, html to figma, figma mcp, ai design to figma, design system automation.
Not affiliated with, endorsed or sponsored by Anthropic or Figma. Claude is a trademark of Anthropic; Figma is a trademark of Figma, Inc.