

Design tokens live in code. Figma variables live in Figma. Keeping them in sync is manual, error-prone, and nobody wants to do it. You spend 2+ hours copying hex values, creating variables by hand, naming them, and hoping nothing drifts. One typo and your design system is out of sync. One missing token and nothing works.
For a system with 128+ variables across color, spacing, and typography — primitives, semantic tokens, light mode, dark mode — manual entry is unsustainable. What if you could just write your decisions down in a markdown file and sync?
That was the idea: color/brand/primary: #00A7E1 → Boom. Figma variables created.
The first version worked, but it was held together with duct tape. The stack: Claude API (Anthropic SDK) to parse the design token markdown into structured JSON, figma-console-mcp — a community MCP server that talked to Figma through the browser console, a Figma Desktop Bridge plugin that relayed commands from the CLI to the Figma desktop app via WebSocket, and custom MCP wrapper scripts to manage the server lifecycle.
The pain was real. The Desktop Bridge plugin had to be manually opened in Figma before every sync. WebSocket connections were flaky — the CLI had to scan ports, detect zombie processes, and retry connections. Three heavy dependencies: @anthropic-ai/sdk, @modelcontextprotocol/sdk, ws. Users needed both an Anthropic API key AND a Figma access token.
It worked, but explaining the setup to someone took longer than the actual sync. “Open Figma, launch the Desktop Bridge plugin, make sure the MCP server is running, check that the WebSocket port isn't blocked...” — not exactly “it just works.”
Figma released their official MCP server with use_figma — a single tool that can create collections, variables, aliases, modes, everything. No plugins, no WebSockets, no browser console hacks. Just an HTTP endpoint with OAuth authentication.
This changed the entire architecture. Every piece of custom plumbing in V1 existed because the right tool didn't exist yet. Now it did.
What got ripped out: the Anthropic SDK — replaced token parsing with a local deterministic parser. Zero API calls, instant, fully testable. 30 tests covering every markdown pattern. figma-console-mcp and the Desktop Bridge plugin — replaced by Figma's official MCP server. All the WebSocket plumbing, port scanning, zombie process cleanup, MCP wrapper scripts. ~2,100 lines of code deleted. Dependencies dropped from 6 to 3.
What replaced it: src/parser.js — a local parser that converts design-token.md into a structured token map. No AI needed for this step. A Claude Code subprocess — spawned with --print mode, given the token map and explicit instructions to use Figma's MCP to write variables. The Figma MCP server handles all the Figma API complexity behind the scenes.
The new flow: designpull init — interactive wizard, generates design-token.md + .env. designpull sync — local parser → token map → Claude Code → Figma MCP → variables in Figma. Done. No plugins to open. No servers to manage.
The rewrite wasn't plug-and-play. Shipping v0.2.0 surfaced a chain of issues that each revealed something about the stack.
The CLI flag was wrong — spawning Claude Code with --message (doesn't exist). The prompt needed to be passed via stdin. shell: true deprecation — Node.js flagged security warnings on every spawn call. MCP servers didn't load in the subprocess — Claude Code spawned with --print from a different project directory doesn't inherit MCP servers from user config. Had to build an MCP config JSON and pass it explicitly via --mcp-config.
False success — Claude would exit 0 with a polite “I don't have Figma tools” message, and the CLI would report “Variables written to Figma!” with nothing actually written. Added output validation to catch this. Wrong tool name — the prompt referenced “figma-use skill” but the actual MCP tool is mcp__figma__use_figma. Aliases weren't created — semantic tokens were written as raw hex values instead of referencing Primitives variables. Dark mode was broken — border and icon colors used the same mid-gray in both modes.
Each fix was small, but they compounded. The gap between “it works on my machine” and “it works for anyone who installs it” was about 6 iterations.
Before: 6 dependencies, Anthropic API key required, Desktop Bridge plugin required, flaky WebSocket connections, ~3,500 lines of infrastructure code.
After: 3 dependencies, no API key, no plugins, one claude mcp add command for setup, 128 variables written to Figma in one shot — with proper collections, modes, and variable aliases.
The lesson: sometimes the best feature is deleting code and waiting for the platform to catch up.