Claude Code is a capable coding agent. Feed it a screenshot of a Figma screen and it will produce something that looks vaguely right. Feed it a structured context bundle — typed design tokens, a layout IR, reference renders, and a machine-readable spec — and it produces code you can actually ship.
figmascope generates that bundle client-side, entirely in your browser. No backend, no upload, no intermediary service with access to your Figma files. This guide walks through the full Figma → figmascope → Claude Code workflow with real CLI examples. If you use Cursor instead of Claude Code, see Figma to Cursor for the Cursor-specific workflow.
Prerequisites
- Claude Code installed:
npm install -g @anthropic-ai/claude-code(or the current install method per docs.anthropic.com/claude-code) - A Figma file URL
- A Figma Personal Access Token with File content: read-only scope
Export the context bundle from figmascope
Open figmascope.dev, paste the Figma file URL and your token, click Export Context Bundle. You'll get a zip like figmascope-ABC123.zip.
Unzip it into a design/ directory in your project:
unzip figmascope-ABC123.zip -d design/
The resulting tree:
design/
├── CONTEXT.md
├── tokens.json
├── _meta.json
├── components/
│ └── inventory.json
├── screens/
│ ├── Home.json
│ ├── Home.png
│ ├── Settings.json
│ └── Settings.png
└── strings.json
Commit it to source control. The _meta.json manifest records the export timestamp and Figma file key, so the team always knows which version of the design the bundle corresponds to.
How Claude Code reads the context bundle
CONTEXT.md is the entry point. It's a structured spec document that tells the agent:
- Which frames were exported and in what order
- The token naming conventions in use
- Scope notes — e.g. which screens were out of scope due to being non-frame nodes, or which components were excluded
- Worked examples showing how a token reference like
{ "$ref": "color.accent" }resolves to a value intokens.json - Any warnings emitted during export (collision in string keys, inferred layout mode on containers)
Claude Code reads files before acting. Starting a session with CONTEXT.md orients the agent before it touches any screen JSON.
Starting a Claude Code session
The most direct approach — launch claude in your project root and point it at the design directory:
claude
Then in the interactive session:
Read design/CONTEXT.md, then implement the Home screen as a React component.
Use:
- design/tokens.json for all design token values
- design/screens/Home.json for the layout tree
- design/screens/Home.png as visual reference
- design/strings.json for all copy (use dot-notation keys as i18n identifiers)
Constraints:
- Tailwind CSS for styles, mapping token values to theme config
- TypeScript
- No hardcoded color or spacing values — all values must come from tokens
Claude Code will read the files sequentially, resolve token references from the IR, and generate a component that reflects your actual design system rather than a generic approximation.
One-shot prompts with --print
For CI pipelines or scripted codegen, use the non-interactive --print mode:
claude --print "$(cat <<'EOF'
Read design/CONTEXT.md. Then implement design/screens/Home.json as
src/screens/Home.tsx (React + Tailwind + TypeScript).
- All tokens from design/tokens.json
- All strings from design/strings.json using dot-notation keys
- Visual reference: design/screens/Home.png
- Component names from design/components/inventory.json
EOF
)"
The heredoc keeps the prompt readable in shell scripts. --print writes Claude's response to stdout, so you can pipe it or capture it as needed.
Claude Code works best when you give it one screen at a time. The layout IR for a single screen is already dense; keep sessions focused.
Multi-screen projects — a sensible approach
For files with many frames, work incrementally. A loop over screen files:
for screen_json in design/screens/*.json; do
screen=$(basename "$screen_json" .json)
echo "Implementing $screen..."
claude --print "$(cat <
The instruction "do not re-implement components that already exist" matters when the component inventory is shared. Claude Code can read design/components/inventory.json to identify which components are already implemented and import them rather than regenerating them.
Wiring up design tokens
The tokens.json exported by figmascope uses a W3C-ish nested structure with $value and $type fields:
{
"color": {
"surface": { "$value": "#f6f2ea", "$type": "color" },
"ink": { "$value": "#1f1d1a", "$type": "color" },
"accent": { "$value": "#d96a3a", "$type": "color" }
},
"spacing": {
"1": { "$value": "4px", "$type": "dimension" },
"2": { "$value": "8px", "$type": "dimension" },
"4": { "$value": "16px", "$type": "dimension" },
"8": { "$value": "32px", "$type": "dimension" }
},
"typography": {
"body": {
"fontFamily": { "$value": "Inter", "$type": "fontFamily" },
"fontSize": { "$value": "14px", "$type": "dimension" },
"lineHeight": { "$value": 1.45, "$type": "number" }
}
}
}
Ask Claude Code to generate a tailwind.config.ts theme extension block from this file as a first step, before implementing any screens. That way all subsequent screen implementations can use the Tailwind token aliases consistently:
claude --print "Read design/tokens.json and generate a tailwind.config.ts
theme.extend block. Map color tokens to theme.extend.colors,
spacing tokens to theme.extend.spacing, and typography to
theme.extend.fontFamily / fontSize. Output only the config object."
See Design Token Export for AI Agents for a deep dive on the token format and the frequency-inference fallback figmascope uses when Figma Variables aren't set up.
Handling the strings layer
Every text node in the Figma file gets a slot in strings.json. The keys use dot-notation derived from the frame hierarchy:
{
"home.hero.title": "Everything you need",
"home.hero.subtitle": "Ship faster with structured context",
"home.cta.primary": "Get started",
"settings.account.heading": "Account settings"
}
Instruct Claude Code to use these keys as i18n identifiers. Rather than hardcoding the string "Everything you need" in JSX, the generated component calls t('home.hero.title') (or your i18n library's equivalent). The resource file is already in strings.json — you just need to import it or wire it to your i18n setup.
If figmascope detects a collision — two nodes that hash to the same key — it emits a strings-collision warning in _meta.json and appends a numeric suffix to disambiguate. Check _meta.json before starting a session so you know what to expect.
CLAUDE.md integration
If you use a CLAUDE.md project context file, add a short section pointing the agent at the design directory. This pairs well with the approach described in AI Design Handoff and complements why figmascope differs from Figma inspector plugins.
Add a design section like this:
## Design context
Design tokens, layout IR, reference renders, and strings live in `design/`.
Always read `design/CONTEXT.md` before implementing any screen.
Token values are in `design/tokens.json` — never hardcode color or spacing.
Component canonical names are in `design/components/inventory.json`.
This means every Claude Code session in the project will automatically have the design context as part of its working knowledge, without you having to repeat it in each prompt.
What the agent actually gets right
With structured context, Claude Code reliably gets:
- Spacing values — because they're in
tokens.jsonasspacing.4 → 16px, not eyeballed from a screenshot - Color — exact hex values, not "looks like a warm orange"
- Typography — font family, size, weight, line-height, all typed
- Layout direction — stack nodes have an explicit
directionandgapfield - Component naming — inventory.json is the canonical source, so no invented names
- Copy — strings.json prevents the agent from paraphrasing or making up placeholder text
What still needs human review: interaction states (hover, focus, active) that aren't visible in static Figma frames, animation timing, and responsive breakpoints that weren't explicitly designed in the file. The IR captures static layout; dynamic behavior is out of scope.
Using --dangerously-skip-permissions in controlled environments
For automated pipelines where you want Claude Code to operate without interactive approval prompts — for example in a CI step that generates component stubs after a design update — you can use --dangerously-skip-permissions. Only appropriate in sandboxed environments with no production credentials.
claude --dangerously-skip-permissions --print "$(cat <<'EOF'
Read design/CONTEXT.md. Generate component stub files for any components
in design/components/inventory.json that don't already exist in src/components/.
Use TypeScript + React functional component format. Include a TODO comment
for each component referencing the relevant screen JSON.
EOF
)"
In production developer workflows, leave permissions interactive. The prompts exist for good reason — Claude Code can and will write files, and you want to know which ones before it does.
Checking the export warnings before you prompt
figmascope emits warnings into _meta.json for conditions that might affect output quality. Check them before starting a Claude Code session:
python3 -c "
import json
meta = json.load(open('design/_meta.json'))
for w in meta.get('warnings', []):
print(f\"{w['code']}: {w['message']}\")
print(f\"Frames exported: {meta['frameCount']}\")
print(f\"Tokens source: {meta.get('tokensSource', 'variables')}\")
"
Two warnings to pay attention to:
layout-mode-none-inferred— a frame had no auto-layout set. figmascope inferred layout from child absolute positions, which is less reliable. Flag the relevant screen in your prompt: "This screen uses absolute positioning; generate accordingly."strings-collision— two text nodes produced the same resource key. figmascope disambiguates with a numeric suffix, but you should verify the strings instrings.jsonare correct before the agent generates i18n calls.
Android and iOS workflows
Claude Code isn't limited to web frameworks. The context bundle is framework-agnostic — the layout IR and tokens are data, not CSS. For Jetpack Compose:
claude --print "$(cat <<'EOF'
Read design/CONTEXT.md and design/tokens.json.
Implement design/screens/Home.json as a Jetpack Compose screen.
- Map color tokens to a MaterialTheme ColorScheme
- Map spacing tokens to Dp values (strip 'px' suffix, use .dp)
- Map typography tokens to MaterialTheme.typography
- Use the component names from design/components/inventory.json as Composable names
- Reference design/screens/Home.png for visual accuracy
EOF
)"
The IR's stack nodes map naturally to Column (direction: vertical) and Row (direction: horizontal) in Compose. leaf nodes with type: "text" become Text composables; type: "image" becomes Image or a placeholder. See Jetpack Compose from Figma for the full pattern.
Versioning the design bundle
Treat the design/ directory like any other project dependency. When the design changes significantly, re-export from figmascope.dev, commit, and note the change in the PR:
# Check when the bundle was last exported vs when Figma file was last modified
python3 -c "
import json
from datetime import datetime
meta = json.load(open('design/_meta.json'))
exported = datetime.fromisoformat(meta['exportedAt'].replace('Z', '+00:00'))
modified = datetime.fromisoformat(meta['figmaLastModified'].replace('Z', '+00:00'))
delta = modified - exported
if delta.total_seconds() > 0:
print(f'WARNING: Figma file was modified {delta} after last export')
else:
print('Bundle is current')
"
A stale bundle means the agent is working from an outdated design. The timestamp check catches this before you spend time on a codegen session that's based on superseded specs.