Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Pull a Figma file's node tree, design tokens, and embedded assets into the project cwd as a structured snapshot.
.claude/skills/nexu-io-figma-extract/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-07 | ✗→✓ | ▲ Improved | -50% | 0% |
| case-01 | ✗→✓ | ▲ Improved | -20% | 0% |
| case-04 | ✗→✓ | ▲ Improved | -44% | 0% |
| case-05 | ✗→✓ | ▲ Improved | -39% | 0% |
| case-06 | ✗→✓ | ▲ Improved | -38% | 0% |
Spec §10 / §21.3.1: the figma-migration scenario starts with a Figma file URL + an OAuth token. This atom turns that pair into the authoritative on-disk record subsequent stages (token-map, generate, critique) operate on.
| Source | Required | Notes | | --- | --- | --- | | Figma file URL or node-id | yes | Provide via the figma-oauth GenUI surface or od plugin apply --input fileUrl=… | | Figma OAuth token | yes | Routed through oauth-prompt with oauth.route='connector' and connectorId='figma'; the daemon never stores the token in SQLite |
The atom writes a deterministic, JSON-shaped extract under the project cwd:
textproject-cwd/ ├── figma/ │ ├── tree.json # canonical node tree (id / type / parent / children / box / fills / text) │ ├── tokens.json # color + typography + spacing tokens lifted off the file │ ├── assets/ # rasterised exports of every leaf node that the file marks for export │ │ └── <node-id>.<png|svg|webp> │ └── meta.json # { fileUrl, version, lastModified, exportedAt, atomDigest }
figma/tree.json is the canonical pivot for every downstream atom. figma/tokens.json is the input to token-map. assets/ is the input to generate's media stage.
The atom completes when figma/tree.json exists and is non-empty. The until evaluator reads figma.tree.nodes >= 1; if the figma file is empty or the OAuth token expired, the atom emits a clear error event and the run aborts (the user fixes auth or picks a different file).
always re-prompt the user; never make up node ids.
meta.json.unsupportedNodes[] so the human can audit gaps.
componentReflinks so token-map can de-duplicate at the right boundary.
Implemented by the daemon runner in apps/daemon/src/plugins/atoms/figma-extract.ts. It fetches and walks the Figma REST tree, records unsupported nodes, lifts tokens, and rasterizes supported assets.
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-07 | fail→pass | 16,485 | 3,577 | -78% | 1 | 1 | 0% | 2,431 | 1,208 | -50% | 0 | 0 | — |
case-01 | fail→pass | 11,057 | 14,431 | +31% | 1 | 1 | 0% | 2,086 | 1,665 | -20% | 0 | 0 | — |
case-02 | fail→fail | 3,029 | 10,708 | +254% | 1 | 1 | 0% | 487 | 2,814 | +478% | 0 | 0 | — |
case-03 | fail→fail | 12,169 | 4,520 | -63% | 1 | 1 | 0% | 2,415 | 1,400 | -42% | 0 | 0 | — |
case-04 | fail→pass | 13,035 | 3,445 | -74% | 1 | 1 | 0% | 2,136 | 1,189 | -44% | 0 | 0 | — |
case-05 | fail→pass | 14,497 | 4,703 | -68% | 1 | 1 | 0% | 2,202 | 1,342 | -39% | 0 | 0 | — |
case-06 | fail→pass | 13,894 | 4,947 | -64% | 1 | 1 | 0% | 2,206 | 1,378 | -38% | 0 | 0 | — |
case-08 | fail→pass | 11,545 | 4,867 | -58% | 1 | 1 | 0% | 2,008 | 1,406 | -30% | 0 | 0 | — |
case-09 | fail→pass | 15,365 | 7,097 | -54% | 1 | 1 | 0% | 2,255 | 1,861 | -17% | 0 | 0 | — |
case-10 | fail→pass | 13,490 | 4,578 | -66% | 1 | 1 | 0% | 2,450 | 1,490 | -39% | 0 | 0 | — |
case-11 | pass→pass | 13,696 | 7,427 | -46% | 1 | 1 | 0% | 2,364 | 1,583 | -33% | 0 | 0 | — |
case-12 | fail→pass | 13,235 | 7,530 | -43% | 1 | 1 | 0% | 2,176 | 1,674 | -23% | 0 | 0 | — |
case-13 | fail→pass | 12,054 | 6,781 | -44% | 1 | 1 | 0% | 1,983 | 1,820 | -8% | 0 | 0 | — |
case-14 | fail→pass | 12,211 | 3,185 | -74% | 1 | 1 | 0% | 2,102 | 1,117 | -47% | 0 | 0 | — |
case-15 | fail→pass | 14,273 | 2,282 | -84% | 1 | 1 | 0% | 890 | 1,007 | +13% | 0 | 0 | — |
case-16 | fail→pass | 14,959 | 2,501 | -83% | 1 | 1 | 0% | 2,354 | 1,122 | -52% | 0 | 0 | — |
case-17 | fail→pass | 10,951 | 2,247 | -79% | 1 | 1 | 0% | 1,709 | 926 | -46% | 0 | 0 | — |
case-18 | fail→pass | 10,398 | 1,636 | -84% | 1 | 1 | 0% | 1,655 | 840 | -49% | 0 | 0 | — |
case-19 | fail→pass | 11,765 | 2,038 | -83% | 1 | 1 | 0% | 1,962 | 930 | -53% | 0 | 0 | — |
case-20 | pass→pass | 16,419 | 15,771 | -4% | 1 | 1 | 0% | 2,954 | 3,562 | +21% | 0 | 0 | — |
case-21 | pass→pass | 20,205 | 20,496 | +1% | 1 | 1 | 0% | 4,036 | 4,336 | +7% | 0 | 0 | — |
case-22 | fail→fail | 32,664 | 19,457 | -40% | 1 | 1 | 0% | 6,577 | 4,096 | -38% | 0 | 0 | — |
case-23 | pass→pass | 9,135 | 9,316 | +2% | 1 | 1 | 0% | 1,695 | 2,287 | +35% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 23 cases were attempted, and 22 counted toward the lift figure. The other 1 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +70 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.