A pi extension that lets the agent read Figma files without drowning in tokens.
Raw Figma REST responses are enormous — a single design file can return 10–100 MB of JSON, most of which is metadata the LLM will never use (vector paths, gradient stops, blend modes, render bounds). Dropping that directly into an agent's context is wasteful and often blows past the context window entirely.
pi-figma sits between pi and the Figma REST API and does three things:
- Transforms every response into a compact shape before returning it. Hex colors instead of 0–1 RGB, integer bboxes, auto-layout essentials only, vectors stripped. On a real frame we measured 84.9% size reduction vs the raw Figma response.
- Caches by Figma's native
versionfield. When the file hasn't been edited, repeat calls in the same session are local disk reads (~1 ms). When a designer edits, theversionstring changes and we refetch automatically. - Ships a skill (
skills/figma/) that teaches the model cost-ordered tool selection — always usefigma_copybeforefigma_inspect, alwaysfigma_mapbefore fetching subtrees, never dump the whole file.
The extension exposes four tools the agent can call directly and one utility command (/figma-cache-stats).
- Not a Figma plugin (those run inside Figma itself).
- Not the Figma Dev Mode MCP server (that's a separate paid product that requires Figma Desktop open).
- Not a web scraper. Figma's canvas is WebGL, so CDP-based approaches don't see node data.
# global — available in every pi session
pi install npm:@originintelligence/pi-figma
# or project-local — only for this project
cd your-project
pi install -l npm:@originintelligence/pi-figmapi install git:github.com/sanchezcodes/pi-figmaPin a version with @vX.Y.Z. Git installs skip pi update when pinned.
If you've cloned the repo and want pi to load your working copy directly — useful for iterating on the extension itself:
pi install /absolute/path/to/pi-figma
# or project-local:
pi install -l /absolute/path/to/pi-figmaPi reads local paths directly — no copying, no rebuild step. Any code change in pi-figma/ is picked up the next time pi starts (or when you run /reload in an active session).
Verify it loaded:
pi
> /extension-status # should list pi-figmaThe extension needs a Figma personal access token. Generate one at https://www.figma.com/developers/api#access-tokens — only the File content read scope is required for v1.
Add to ~/.zshrc (or ~/.bashrc):
export FIGMA_PAT=figd_XXXXXXXXXXXXXXXXXXXXReload with source ~/.zshrc or open a new terminal. Launch pi normally.
mkdir -p ~/.pi-figma
echo '{"pat":"figd_XXXXXXXXXXXXXXXXXXXX"}' > ~/.pi-figma/config.json
chmod 600 ~/.pi-figma/config.jsonThe extension checks FIGMA_PAT first, then falls back to this file. Useful if you can't modify shell rc files (shared hosts, locked-down macs).
In a pi session:
> map this Figma file https://www.figma.com/design/SOME_KEY/Name
Pi should call figma_map and return a list of pages/frames. If it errors with "No Figma token found", the env var isn't visible to the pi process — usually because you exported in .zshrc but didn't restart the terminal.
Four tools, ordered cheapest to most expensive. The skill in skills/figma/ tells the model to prefer the cheaper one whenever possible.
| Tool | What it returns | Typical payload |
|---|---|---|
figma_copy |
Flat list of UX text: { id, path, text } per TEXT node |
smallest |
figma_tokens |
Registered design-system Styles (names only, no resolved values) | small |
figma_map |
Page/frame tree: { id, name, type } at configurable depth |
small |
figma_inspect |
Compact layout + visuals for one or more nodes (Dev-Mode-style) | medium |
- File: a raw key (
abc123XYZ) OR any Figma URL (figma.com/file/...,figma.com/design/...). - Node IDs:
1:234(API form),1-234(URL form), or a full URL with?node-id=— all parsed automatically.
- Hex colors (
#1a80e6) orrgba()when alpha < 1 — never Figma's raw 0–1 RGB objects. - Integer bboxes as
[x, y, w, h]. No sub-pixel noise. - Auto-layout essentials only: direction, padding, gap, radius. Skipped when at defaults.
truncatedChildren: Ncounter when depth is capped — the agent knows what it didn't see.- No vector path data, gradient stops, effect details, render bounds, export settings, blend modes (unless non-default).
/figma-cache-stats
Shows current disk usage of ~/.pi-figma/cache/.
Drop any of these into a pi session. Replace <FILE_URL> with a Figma file link and <FRAME_URL> with a link that includes ?node-id= (copy from Figma's "Copy link to selection").
list the figma tools you have available and tell me which one is cheapest
Sanity check — verifies the skill loaded and pi knows the cost ordering.
map this figma file and tell me what pages and top-level frames exist: <FILE_URL>
Cheapest discovery. Returns the tree skeleton only.
audit every piece of written copy in this figma file for typos or inconsistent capitalization: <FILE_URL>
Flat {id, path, text} list so the agent can tell you where each issue lives.
what design tokens (colors, text styles) are registered in this file? check if the naming follows a consistent convention.
Style names only in v1. If the file uses Figma Variables, counts come back as 0 — see Known limitations.
inspect this specific frame and describe its layout, colors, and text styles: <FRAME_URL>
pi auto-parses ?node-id= from the URL. Compact output with hex colors and integer bboxes.
convert the frame at <FRAME_URL> into a self-contained React component with Tailwind classes. match spacing, colors, and typography exactly.
The end-to-end workflow: figma_map → figma_inspect → code generation, all inside the context budget.
that last frame had truncated children — pick the most complex-looking child and inspect it at higher depth
Drill-down when truncatedChildren appears. Never guess — target a child id and raise depth.
/figma-cache-stats
Utility command. Shows current disk usage of ~/.pi-figma/cache/.
pi-figma/
├── src/
│ ├── index.ts # extension entry: registers tools + /figma-cache-stats
│ ├── client.ts # REST fetch, auth resolution, URL/node-id parsing
│ ├── cache.ts # gzipped disk cache, version-keyed, bounded at 2 versions/file
│ ├── transforms.ts # raw Figma → compact (the token-saving layer)
│ ├── types.ts # narrow types for what we actually consume
│ └── tools/
│ ├── map.ts
│ ├── inspect.ts
│ ├── copy.ts
│ └── tokens.ts
├── skills/figma/SKILL.md
└── scripts/smoke.ts # end-to-end test script
Rule of the house: no code path returns a raw Figma response to the LLM. The content text in every tool is always the output of a transforms.ts function.
figma_tokensmisses Figma Variables. v1 only reads the top-levelstylesmap on/v1/files/:key. Modern files increasingly use Variables instead (separate endpoint at/v1/files/:key/variables/local). Iffigma_tokensreturns zeroes on a file you know has colors, fall back tofigma_inspecton a consuming node and read itsfill. Fixing this is the #1 item on the v0.2 roadmap.- Personal access tokens are broad. A Figma PAT has access to every file your account can see. Generate a separate PAT with minimal scope if this worries you.
- Large sections still produce large output.
figma_inspecton a SECTION containing 12 full screens returns ~60 KB even after transform. The skill tells the agent to drill into a single frame when an inspect result is oversized, but it can still happen. If you see this, instruct the agent: "inspect just the first child, not the whole section."
v0.2 — ordered by proven need:
- Variables support in
figma_tokens— the big one, see limitation above. figma_export(file, nodeIds, format, scale)— render frames to PNG/SVG/PDF. Named after Figma's "Export" button.figma_find(file, query)— locate nodes by name pattern.figma_components(file)— component/variant registry.detail: "full"param onfigma_inspect— opt-in unredacted fields (effects, gradient stops) for DS reverse-engineering.
v0.3+ — stretch:
- Webhook ingestion for "notify on file change".
- Companion Figma plugin for inside-Figma selection → tool-call bridging.
- OAuth flow alternative to PAT, for shareable team setups.
Typecheck:
cd /path/to/pi-figma
npm install
npm run typecheckEnd-to-end smoke test against a live file (requires FIGMA_PAT in env):
npx -y tsx scripts/smoke.tsThe smoke script exercises all four tools against a real Figma file and reports payload sizes, fetch times, and cache-hit latencies. Use it as a regression harness after any change to client.ts or transforms.ts.
MIT — see LICENSE.