Install it. Point Claude at it. Watch it converge.

Fig is a standard npm package with zero runtime dependencies. One reviewable install step wires it into your app; after that it never edits a tracked file again.

Download & install

Pick whichever fits your setup — the first is recommended. Fig ships as the figstate package.

# 1. As a dev-dependency of your app (resolves babel plugins + runtime from node_modules)
npm i -D figstate
npx figstate install          # wraps babel.config → require("figstate/babel"); reversible

# 2. Global — install once, point it at each app
npm i -g figstate
figstate install --app-dir /path/to/app

# 3. No install — run straight from a checkout
npx /path/to/cli install --app-dir /path/to/app

figstate install is the one wiring step: it wraps your babel config with withFigstate (env-gated, committable, and reversed byte-for-byte by figstate uninstall). Verify the wiring any time with figstate doctor.

Non-invasive guarantee. The only tracked change Fig ever makes is that one babel wrap. Everything else is env-gated (FIGSTATE_*) and lands in the gitignored .figstate/ — a normal expo start / EAS build is byte-identical whether or not Fig is installed.

Use with Claude

Fig is built for coding agents. Paste this into Claude (or drop it in your CLAUDE.md) to have it download, install, and drive the loop:

# Fig — design-to-code, measured against the designer's intent.

# 1. Add Fig to the app and wire it in (one-time, reviewable, reversible):
npm i -D figstate && npx figstate install
npx figstate doctor            # confirm babel wrap + env + tools

# 2. Reach the state a Figma frame depicts, then diff it:
npx figstate diff --slug home --figma-url "<frame-url>" --overlay

# 3. Read report.json. Fix whatever keeps parity_trustworthy false,
#    hit the ABSOLUTE targets it gives you, and re-run step 2 until:
#      { "parity_trustworthy": true, "coverage": { "match_score": 1.0 }, "warnings": [] }

The rules that make this work with an agent:

  • Ground truth is the design, never the agent's self-assessment. Success is judged only against the Figma frame.
  • Feed absolute targets, not deltas. The report gives the coordinates/sizes to hit — relaying approximate deltas makes the loop oscillate.
  • Stop on the gate. The loop ends when parity_trustworthy is true and warnings is empty — nothing weaker.

The agent loop

Every Fig workflow is the same four beats:

1 · Reach

Deep-link or drive the app to the exact composed state the frame shows — including interactive/active states a plain link can't reach.

2 · Capture

Dump the app's real on-screen geometry (DOM on web, render tree on mobile) plus a screenshot.

3 · Diff

The shared Python engine compares capture vs frame and emits a deterministic report.json.

4 · Iterate

The agent acts on the report's absolute targets and re-runs — until the gate is green.

The report

Every diff emits the same report.json. These are the fields the loop turns on:

FieldMeaning
parity_trustworthyThe hard gate. true only when the schema is valid, the visual gate passes, everything is within point-tolerance, and warnings is empty.
coverage.match_scoreSymmetric overlap — accounted nodes ÷ (accounted + spare) across design and app. Presence/matching, not placement.
warnings[]Actionable codes: schema_invalid, visual_invalid, uncovered_design (design node with no app match), app_extra (app node with no design match).

CLI reference

Generated from the toolchain source () by website/scripts/gen-cli-docs.mjs — it can't drift from the code.

Ready to close the loop?

One command to install. One gate to trust.

↓ Back to install