swarm.ingfield reports vol. i / no. 04
abu dhabi 20 may 2026
Field Report · Figma → Pencil → Claude Code · May 2026

cmd‑C in Figma. cmd‑V in Pencil.
Styles preserved.

The predictable, reproducible 2026 workflow for migrating pixel-perfect designs from Figma into Pencil.dev — and then iterating inside Claude Code with a continuous visual-feedback loop that actually closes.

Source of truth
Figma during design · .pen during iteration · code after handoff
Fidelity gate
Playwright as measurement instrument, not regression baseline
Loop closure
Screenshot → vision-read → numerical diff → patch → repeat
Inner loop time
~30 sec per iteration · max 3–5 before human review
§ i — the loop in one paragraph
2-minute read

The whole workflow, in one breath.

Select a frame in Figma → cmd+C. Open a .pen file in Cursor or Claude Code → cmd+V. Styles, auto-layout, and color variables come over pixel-perfect. Now you have a git-versioned canvas the agent can read and write. Ask Claude Code to generate React from the .pen. Run the dev server. A Playwright skill takes a screenshot of the rendered output, the agent reads the PNG via its vision capability, compares against the Figma reference, fixes specific numerical diffs, and iterates. Three to five rounds, total ~2 min, and the output matches the design with measured fidelity — not eyeballed.

The core insight (from Vadim's March 2026 writeup) Use Playwright not for visual regression — that catches code-to-code drift but never code-to-design drift. Use it as a measurement instrument. Extract getComputedStyle().fontSize and getBoundingClientRect() values from the rendered output, compare against the Figma spec, and feed numerical diffs to Claude Code: "heading is 28px, spec says 24px, change size from 7 to 6." Specific, numerical, unambiguous. The AI is the labor; Playwright is the quality gate; Figma is the source of truth.
§ ii — the pipeline
four stages, three minutes

Four stages, three minutes per round.

The canonical pipeline is opinionated and CLI-runnable. Each stage is independently testable. Each stage has a verifiable output you can commit to git. No clipboard rituals required after stage 1 — once the .pen lives in the repo, every subsequent iteration is prompt-driven from Claude Code.

stage 01 · ingest

Cmd-C in Figma, Cmd-V in Pencil

Select frames in Figma, paste into a .pen file opened in Cursor or VS Code. Auto-layout, padding, color/typography variables, components, and instances all preserve per Pencil's documented schema mapping.

$ touch src/designs/landing.pen
# Open in Cursor → Cmd-V
stage 02 · context

Extract tokens via Figma MCP

Figma Dev Mode MCP runs locally at http://127.0.0.1:3845/mcp. Tools: get_design_context, get_variable_defs, get_code_connect_map, get_image. The agent now sees Figma variables as real tokens, not eyeballed hex.

$ claude mcp add --transport http \
  figma https://mcp.figma.com/mcp
stage 03 · generate

Claude Code reads both sides

Claude Code has the .pen in the repo and the Figma MCP at its disposal. Prompt: "Generate the landing page React component from landing.pen, use variables from Figma get_variable_defs, target shadcn/ui."

# in Claude Code
> read landing.pen and impl as
> Next.js + Tailwind + shadcn
stage 04 · close the loop

Playwright sees, Claude reads

Dev server up. Playwright captures three-viewport screenshots. Read screenshots/desktop.png in Claude Code — the agent sees what it built. Measure specific elements, compare to spec, patch. Repeat 3×.

$ npm run screenshot &&
  claude < "Read screens/* and
  compare to figma frame X"
What gets preserved on Cmd-V (officially documented) Vectors come over intact. Text styles intact. Auto-layout (vertical, horizontal, none), padding, flexbox alignment intact. Color variables map to Pencil variables. Components import with reusable: true; instances import with ref. What doesn't: images. Pencil's docs explicitly warn that images don't paste from Figma — drag-drop them separately or use SVG. Complex vectors may lose path data on Figma's clipboard format — export problematic ones as raw SVG first.
§ iii — configs
copy-paste, no edits required

The configs, copy-paste ready.

Three MCP servers cover the entire loop: Figma (read-only source-of-truth), Pencil (read+write canvas), Playwright (visual feedback). Wire all three into Claude Code or Cursor and the inner loop has every primitive it needs.

A. Claude Code — global scope

Run these once, then they're available across all your repos:

# Figma Dev Mode MCP (remote, official) claude mcp add --scope user --transport http \ figma https://mcp.figma.com/mcp # OR Figma Dev Mode MCP (local desktop — selection-based prompting works only here) claude mcp add --scope user --transport sse \ figma-desktop http://127.0.0.1:3845/sse # Pencil MCP — autoinstalled when you launch Pencil, but here's manual: claude mcp add --scope user pencil \ npx -y @anthropic-ai/mcp-pencil # Playwright MCP — for the visual feedback loop claude mcp add --scope user playwright \ npx @playwright/mcp@latest --caps=vision,pdf,devtools # Verify all three are connected claude mcp list

B. Cursor — ~/.cursor/mcp.json

{ "mcpServers": { "figma-desktop": { "url": "http://127.0.0.1:3845/sse" }, "figma-remote": { "url": "https://mcp.figma.com/mcp", "type": "http" }, "playwright": { "command": "npx", "args": ["@playwright/mcp@latest", "--caps=vision,pdf,devtools"] } } }

Pencil's Cursor extension auto-registers its MCP server when you install the extension — no manual entry needed. Verify in Settings → Tools & MCP.

C. Pencil CLI for headless / batch / scripting

# Authenticate once export PENCIL_CLI_KEY=pencil_cli_xxxxx # Headless generate from prompt — supports Opus 4.6 / Sonnet 4.6 / Haiku 4.5 pencil --out landing.pen \ --model claude-opus-4-6 \ --prompt "Generate a landing page matching figma frame 123-456" # Interactive shell for direct MCP tool calls (debugging, scripting) pencil interactive -i landing.pen -o landing.pen > get_editor_state() > batch_get({pattern: "text"}) > snapshot_layout() > export_nodes({nodeIds: ["hero"], format: "png"}) > save() > exit() # Connect interactive shell to running Pencil app via WebSocket pencil interactive --app desktop

D. Pencil MCP tools available to your agent

The CLI, IDE extension, and desktop app all expose the same MCP surface. Memorize these — they're what gives Claude Code write access to the canvas (which Figma never will):

ToolClassWhat it does
batch_designwritewriteInsert, update, delete, move, copy, replace nodes — the workhorse
batch_getreadreadSearch and read nodes by pattern or ID
get_editor_statereadreadDocument metadata and structure
snapshot_layoutreadreadDocument structure with computed bounding boxes
get_screenshotvisualvisualRender a node to PNG — fuel for the visual loop
get_variables / set_variablestokensread+writeRead/update design tokens. The bridge to Tailwind config.
find_empty_space_on_canvaslayoutreadWhere to place new elements without overlap
search_all_unique_propertiesutilityreadRecursive property search on a node tree
replace_all_matching_propertiesutilitywriteRecursive property replacement
export_nodesexportexportPNG / JPEG / WEBP / PDF export
get_guidelinesstylestyleLoads .pen guidelines + style refs
The Pencil + Claude Code dependency Pencil's AI features require Claude Code installed and authenticated. Login via the claude CLI; credentials stored in ~/.claude/. Means: if your team uses Codex or Cursor's Anthropic-via-Cursor proxy primarily, you still need Claude Code installed for Pencil's canvas operations to work. For swarm.ing this is fine (your daily driver is Claude Code on Max plan). For mixed-CLI teams: budget for an extra Claude Code Pro seat per Pencil user.
§ iv — the inner loop
how the agent actually sees

The inner loop, diagrammed.

Claude Code can read PNG files. That single capability is the entire visual feedback loop — the rest is plumbing. Three open-source skills (nukacha/claude-code-mock-starter, tonymfer/design-loop, leadgenjay test-improve) implement the same fundamental pattern with different orchestration. Pick one, don't reinvent it.

SOURCE Figma frame node-id pinned via Cmd-C / MCP link CANVAS .pen file JSON object tree git-versioned in repo IMPLEMENTATION React + Tailwind generated by Claude Code from .pen + Figma tokens RUNTIME Dev server localhost:3000 npm run dev CAPTURE Playwright 3× viewport screenshots + getComputedStyle() CRITIQUE Claude reads PNG vision: Read screenshots/* describes what it sees DIFF Numerical delta heading: 28px → spec 24px gap: 4px → spec 8px PATCH Specific fix change size 7→6 gap-1 → gap-2 PASS? all 5 criteria ≥ 4/5 SHIP git commit .pen + .tsx + tokens all three in PR PASTE MCP read npm dev PNG file vision measure LOOP — max 3–5 iterations PASS FAIL → patch again

The skills that implement this loop (pick one)

Skill / TemplateRepoHow it worksBest for
design-looptonymfer tonymfer/design-loop Section-level screenshots via agent-browser. 5 anti-slop criteria scored 1–5 with weighting. Top-3 issues fixed per iteration, plateau detection after 3 stuck cycles. Marketing pages, landing pages, anything with semantic section structure
claude-code-mock-starternukacha nukacha/claude-code-mock-starter Vite + React template. Embedded Playwright MCP. Builder → critic → fixer agents. /discover → /spec → /tasks → /iterate with human gates only at first three. Tags every gap as [VISUAL] / [DATA] / [INTERACTION] / [STRUCTURAL]. Mock builds, proposal-grade work, client-facing prototypes
test-improveleadgenjay leadgenjay.com/skills/test-improve 4-phase: detect project → multi-viewport screenshot (1440/768/393) → audit against 6-category weighted checklist → fix → re-audit. Max 3 iterations. Auditing existing pages, post-build polish, brand-compliance check
jimmc414 gistvisual development guide gist.github.com/jimmc414/2416424a8e0fd6c0b5de948f28a00b13 The original pattern. Plain npm run screenshotRead screenshots/desktop-*.png. No skill required, just a CLAUDE.md instruction. Greenfield projects where you want minimal harness overhead
For swarm.ing specifically Start with tonymfer/design-loop — it's the most opinionated and has the cleanest plateau detection (gives up after 3 stuck cycles rather than burning tokens in circles, matters when you're running Claude Max). Layer in the jimmc414 pattern as a CLAUDE.md instruction for greenfield work that doesn't need full orchestration. Skip nukacha unless you're spinning up many client-facing mocks fast — it's a starter template, not a permanent harness.
§ v — migration paths
four candidates, one winner

The migration matrix.

Four candidate paths from Figma to AI-iteration. The right path depends on whether Figma stays canonical or you migrate the source-of-truth. For swarm.ing's CLI-first workflow, Pencil is the answer. The others have their use cases.

Path Fidelity Token sync Code reuse Source of truth Best for
Figma → Pencil .penrecommended High · Cmd-V preserves auto-layout, padding, variables, components Native · Figma vars map to Pencil vars on paste High · via Figma Code Connect or shadcn target Drifts to .pen after import; Figma optional thereafter Agent-driven iteration with visual feedback loop · swarm.ing default
Figma → Paper.design High · HTML/CSS-native; 24-tool MCP Good · bidirectional but designer-led Medium Paper.design (after import) GPU-shader-heavy brand work, motion design — niche
Figma → Magic Patterns Medium · React-focused output Low · no direct variable sync High · React-structured handoff Magic Patterns (after import) Client-facing prototypes with versioning + SOC 2 / ISO posture
Figma stays canonicalMCP only Absolute · Figma is single source Native · get_variable_defs always reads live High · with Code Connect investment Figma forever Teams with dedicated designers, strict DS governance, big libraries
Why Pencil wins for swarm.ing Three reasons. (1) Write access: Figma MCP is read-only. Pencil MCP is read+write. An agent that can only see a design can only generate code from it; an agent that can modify the canvas can iterate on the design itself. That's the difference between "AI as assistant" and "AI as collaborator." (2) Git-native: .pen files commit alongside code. Design changes show up in PRs. Branch a feature, branch the design. No more "what version was this designed against?" (3) Real CLI: pencil --out --prompt --model means the entire design loop is scriptable. Cron a nightly design system audit. Pipe Figma exports through Pencil into Cloudflare Pages preview deploys. The boring infrastructure becomes possible.
When to keep Figma canonical instead If your team has 3+ dedicated designers, runs a real design system with hundreds of components, has invested in Figma Code Connect mappings, and treats handoff-to-engineering as a formal stage gate — keep Figma. Use the Figma MCP server to feed context to Claude Code. Don't move the source-of-truth. The Cmd-C / Cmd-V flow into Pencil works per-frame when you need agent-driven iteration on a specific surface; the rest of the design system stays in Figma. Hybrid is the right answer for most non-solo teams.
§ vi — fidelity gate
Playwright as measurement, not regression

The fidelity gate — measured, not eyeballed.

Pixel-perfect doesn't mean pixel-diff. The trap most teams fall into is using Playwright's toHaveScreenshot() as the fidelity check — that catches code-to-code regression (did the UI change from yesterday?) but never catches code-to-design drift (does the baseline match the design at all?). For Figma-as-source fidelity, you need a measurement approach, not a comparison approach.

# Three CI gates, ordered cheapest → most expensive # Gate 1: Deterministic anti-pattern lint (free, no LLM, no API key) npx impeccable detect src/ --json > /tmp/impeccable.json jq '.violations | length' /tmp/impeccable.json # must be 0 # Gate 2: Measurement against Figma spec via Playwright getComputedStyle npx playwright test tests/figma-fidelity.spec.ts # Gate 3: Visual regression against previous build (catches breaks, not design drift) npx backstop test # BackstopJS config in backstop.json

Vadim's measurement pattern — the actual Playwright spec

// tests/figma-fidelity.spec.ts import { test, expect } from '@playwright/test'; test('hero matches Figma frame 123-456', async ({ page }) => { await page.goto('http://localhost:3000'); // pass a string, not a function — tsx adds __name helper that breaks in browser const heading = await page.evaluate( `(() => { const el = document.querySelector('h1'); const s = getComputedStyle(el); const r = el.getBoundingClientRect(); return { fontSize: s.fontSize, top: r.top, height: r.height }; })()` ); expect(heading.fontSize).toBe('24px'); // from Figma get_variable_defs expect(heading.top).toBe(40); // Figma frame padding });
The __name trap (will cost you an hour if you don't know) If you write the measurement function as a TypeScript arrow function and pass it to page.evaluate(), tsx (TypeScript Execution) transforms your code and injects a __name helper that doesn't exist in the browser context. You get ReferenceError: __name is not defined from a script that looks correct. Pass a plain JavaScript string to page.evaluate(), or run via npx playwright test directly (which doesn't use tsx for the inner script). Documented in Vadim's March 2026 writeup.

BackstopJS for regression — the cheap second gate

{ "id": "openclaw-arena", "viewports": [ { "label": "phone", "width": 393, "height": 852 }, { "label": "tablet", "width": 768, "height": 1024 }, { "label": "desktop", "width": 1440, "height": 900 } ], "scenarios": [ { "label": "Arena dashboard", "url": "http://localhost:3000/arena", "selectors": ["document", "#hero", "#leaderboard"], "misMatchThreshold": 0.1, "requireSameDimensions": true } ], "engine": "playwright", "engineOptions": { "args": ["--no-sandbox"] } }
§ vii — gotchas
documented, not theoretical

What breaks, and how to fix it.

Every one of these is a real failure mode documented in Pencil's troubleshooting guide, Figma's MCP setup docs, or 2026 published case studies. Read them once so you don't lose an afternoon to any of them.

Images don't paste from Figma to Pencil

Pencil's docs explicitly call this out as a known limitation. Image elements don't survive the clipboard. Vectors and text do.

FIX → Drag-drop images separately. Or import the entire Figma file via File → Import Image/SVG/Figma.... Or use SVG.
Missing fonts fall back to Inter

If Pencil doesn't have the font registered, your Fraunces hero text becomes Inter and you don't notice until you preview at full size.

FIX → Pre-install all design fonts via the OS, or specify web-font URLs in DESIGN.md and reference from Pencil tokens.
Figma MCP returns no variables

If the designer used raw hex values (#FF0000) instead of Figma variables, get_variable_defs returns nothing.

FIX → Ask the designer to convert styles to variables. Or extract tokens via the Figma REST API and a one-time mapping script.
Figma MCP "Connection refused"

Figma desktop must be running and Dev Mode MCP toggle must be on in Preferences. The local server only runs while Figma is open.

FIX → open -a "Figma"; Figma → Preferences → enable Dev Mode MCP Server. Verify at http://127.0.0.1:3845.
.pen diffs are noisy in git

Pencil's .pen is JSON but the object tree restructures on changes, producing massive diffs even for small visual tweaks.

FIX → Keep .pen files small (one component per file). Use git diff --stat not full diff in PR reviews. Pencil knows; text-diff readability is on their roadmap.
Complex vectors lose path data

Figma's clipboard format doesn't always preserve complex path data on Cmd-V. Decorative SVGs may simplify or drop curves.

FIX → Export problematic SVGs from Figma first (Export → SVG), then drag-drop into Pencil. Or reference them externally via URL.
Remote Figma MCP lacks selection context

Selection-based prompting ("generate code from my current selection") only works with the desktop MCP. Remote requires a full URL with node-id.

FIX → Use desktop MCP for active design phases. Remote is for batch processing or when you can paste node URLs.
Claude Code dependency for Pencil AI

Pencil's AI features require Claude Code installed and logged in. If you're a Codex-only or Gemini CLI shop, you'll need an extra Claude Code seat per Pencil user.

FIX → For swarm.ing this is moot (Claude Max already). For mixed teams, budget for it or use the headless pencil --model flag to route via OpenRouter.
The __name ReferenceError in Playwright

tsx injects a TypeScript helper that doesn't exist in browser context. Your page.evaluate() measurement script crashes.

FIX → Pass plain JS string to page.evaluate(). Or run via npx playwright test directly (no tsx wrapper).
Visual loop infinite iteration

Without plateau detection, the agent will polish a screen forever, burning tokens on diminishing returns.

FIX → Use tonymfer/design-loop or test-improve which both cap at 3 iterations. Or set a hard budget in your CLAUDE.md instruction.
§ viii — decision tree
where the source of truth lives

Where does the source of truth live?

The hardest decision in this whole workflow isn't tool selection — it's where the canonical design lives after migration. Get this wrong and you'll have three out-of-sync sources, designers blaming engineers and vice versa. Five branches, pick one per project.

If you're a solo founder or 2–3 person eng-led team
Pencil-as-source. Move .pen into the repo, abandon Figma after migration.
No designer overhead, no handoff politics. The .pen file is the design. Claude Code edits it directly via MCP. Visual loop closes inside the IDE. This is swarm.ing's default for Openclaw and CuriSphere.
If you have 1 designer + 3–10 engineers
Hybrid — Figma in design phase, Pencil in implementation.
Designer works in Figma (their tool, their flow, their plugins). When a frame is ready for implementation, Cmd-C → Cmd-V into .pen. Engineers iterate the .pen with agents. Updates flow back to Figma manually (or via Pencil → Figma export when Pencil adds it).
If you have a real design system with 100+ components
Figma-as-source, MCP only. Don't migrate.
The investment in Figma libraries, Code Connect mappings, and shared variables is too valuable to throw away. Use the Figma MCP server to feed context to Claude Code. Generate code, never write back to Figma. Pencil becomes optional and per-feature.
If you're building from text spec without an existing design
DESIGN.md as source. Skip Figma entirely.
Run /impeccable teach to seed DESIGN.md + PRODUCT.md. Prompt Claude Code to generate the .pen from text. Iterate in Pencil. Skip Figma until you need a real designer collaborator. This is the swarm.ing greenfield pattern.
If you're tempted to keep all three in sync manually
Don't. Pick one canonical, treat others as derived.
Three sources of truth = three sources of bugs. The team will spend more time reconciling than building. Choose Figma OR .pen OR DESIGN.md as canonical. Generate everything else from it. Refuse "let's update both" — it never happens.
The swarm.ing answer, opinionated For Openclaw arena dashboard and CuriSphere personal RAG UI, the default is DESIGN.md + Pencil + Claude Code. No Figma in the loop. Brand lives in DESIGN.md (already there via Impeccable's /teach). Canvas lives in .pen (commits to git). Code lives in your existing Cloudflare Pages repo. The visual feedback loop runs locally via Playwright. Only introduce Figma when you hire a designer who lives in it — then move to the Hybrid branch above.
§ ix — sources
verifiable, dated

Where this came from.

Twenty primary sources current as of May 2026. Parallel.ai Pro processor synthesized the structural recommendations; Exa confirmed the specific commands, MCP tool names, and the Pencil docs verbatim. Vadim's blog and the Pencil docs do the heavy lifting on the fidelity gate. Verify before deploying to production.

Pencil docs — Import & Export Pencil docs — Troubleshooting (image limitations) Pencil docs — Design ↔ Code workflow Pencil CLI reference (all MCP tools) The .pen format spec Pencil installation + Claude Code dependency tomkrcha — Cmd-C / Cmd-V preserves styles pixel-perfect Pencil.dev vs Figma — April 2026 case study Figma MCP — remote server installation Figma desktop MCP — full setup, May 15 2026 Figma — MCP server setup guide figma/dev-mode-mcp-server-guide Vadim — Playwright as measurement instrument nukacha/claude-code-mock-starter — builder/critic/fixer template tonymfer/design-loop — autonomous visual iteration plugin leadgenjay test-improve — 4-phase visual audit skill jimmc414 — Claude Code visual development guide Playwright MCP — vision mode garris/BackstopJS — regression testing config pbakaus/impeccable + impeccable-detect anti-pattern CLI