An agent-agnostic extension for GitHub SpecKit that grounds spec / plan / task / implementation generation in Figma design context. It works on any project that follows the same architecture. It defaults to a single-repo (one repository, one front-end app) and also supports mono-repo (Nx / Turborepo / pnpm / yarn / Lerna) and multi-repo (git submodules) layouts.
- Activates Figma integration only for front-end targets, driven by a single
figma.projects.config.json(back-end / infra / BFF are excluded silently). - Lets the agent autonomously introspect the mapped Figma design context from
any level of the hierarchy — a single file, a whole project, or an entire
team (organization > team > projects > files) — without per-page approval.
The REST snapshot indexes pages, top-level frames and the file's
component/style metadata; deeper node detail (nested layers, variants, layout
constraints) is fetched on demand via
--depth/--node. - Ships two design-context engines: a portable REST engine (default — curl +
jq, CI-friendly) and an optional MCP engine (
figma.contextSource: "mcp") that delivers richer context and more faithful mockup implementation when a Figma MCP server is available, with automatic REST fallback when the server is absent. - Enforces a 3-level component resolution (reuse → create-in-DS → create-in-app) with the Design System kept purely presentational (no business logic). Works with or without a Design System: when none is configured, the resolution collapses to reuse → app/lib and token gaps are not raised.
- Honors review remarks: direct Figma links in the input, shared mockups across apps or features, a project-defined responsive policy (declared in the overlay), creative confirmation checkpoints, token-gap detection (the agent never edits the DS directly), and mandatory automated tests on UI changes (plus a component-catalog entry when the project uses one, e.g. Storybook).
.
├── extension.yml # SpecKit extension manifest (read by `specify extension add`)
├── CHANGELOG.md # version history (Keep a Changelog format)
├── .extensionignore # development-only files excluded from the installed copy
├── install.sh # optional manual installer (single/mono/multi-repo)
├── install.ps1 # the same installer for Windows (PowerShell 7+)
├── commands/ # agent-agnostic command templates
│ ├── speckit.figma.setup.md
│ ├── speckit.figma.update.md # re-sync assets/hooks + re-register commands (idempotent)
│ ├── speckit.figma.ensure.md # auto-context (before_specify/before_plan/before_tasks hooks)
│ ├── speckit.figma.introspect.md
│ └── speckit.figma.verify.md # post-gen section check (after_* hooks; CI gate via --strict)
├── config/
│ ├── figma.projects.config.schema.json
│ ├── figma.projects.config.singlerepo.example.json
│ ├── figma.projects.config.multirepo.example.json
│ ├── figma.projects.config.monorepo.example.json
│ └── figma.projects.config.organization.example.json
├── scripts/
│ ├── bash/ # curl + jq, 429 backoff, keychain token loading (macOS/Linux)
│ └── powershell/ # PowerShell 7+ ports — same flags/JSON/exit codes (Windows)
├── tests/ # bats test suite + Pester (PowerShell) suite + fixtures
├── templates/
│ ├── spec-figma-section.template.md
│ ├── plan-figma-section.template.md
│ ├── tasks-figma-section.template.md
│ └── figma-readme-block.template.md # managed section install.sh appends to the workspace README
├── .figma/
│ ├── figma-design-rules.md # non-negotiable agent rules (constitution base; overwritten on update)
│ └── figma-design-rules.custom.md # your overlay — overrides the base, preserved across updates (cache/ stays git-ignored)
└── docs/
└── INSTALL.md CREDENTIALS.md MONOREPO.md
# from the latest tagged release (reproducible, matches the catalog entry)
specify extension add figma --from https://github.com/Fyloss/spec-kit-figma/archive/refs/tags/v1.6.0.zip
# from the development branch (may be ahead of the latest release)
specify extension add figma --from https://github.com/Fyloss/spec-kit-figma/archive/refs/heads/main.zip
# or from a local checkout
specify extension add --dev /path/to/spec-kit-figmaOnce the extension is listed in the Spec Kit community catalog, it is also
discoverable via specify extension search figma.
This registers the /speckit.figma.setup, /speckit.figma.update,
/speckit.figma.ensure, /speckit.figma.introspect and
/speckit.figma.verify commands with your agent. Then run
/speckit.figma.setup once.
Figma context is refreshed automatically: the manifest's
before_specify / before_plan / before_tasks hooks invoke
/speckit.figma.ensure, which runs
./.specify/scripts/bash/figma-ensure-context.sh before generation, piping in the
user's raw feature input (--input -). When Figma applies, the script renders a
ready-to-paste design section per phase and reports mustInject: true so the
agent integrates it regardless of model — never silently omitting it. After
generation, the after_specify / after_plan / after_tasks hooks invoke
/speckit.figma.verify, which confirms the section actually landed in the
document (and self-corrects if it did not). Run
figma-verify-section.sh --phase <spec|plan|tasks> --strict in CI to fail the
build when a detected Figma mockup was not integrated. Direct Figma links pasted in the
feature description are detected automatically: the linked file and frames
become authoritative design targets and are introspected at node level — no
manual command needed. The script is a safe no-op when the extension is
unconfigured, the target is excluded, or the snapshot is fresh (and covers the
linked nodes) — and it never blocks spec/tasks generation. Running
/speckit.figma.introspect manually remains available for deep dives
(specific nodes, custom depth).
Warning
Use a capable model (Claude Sonnet or better). Lighter models are strongly discouraged for this extension.
Each Spec Kit SDD command is a multi-step protocol, not just Markdown generation:
the agent must first run a setup script (under .specify/scripts/) that detects
the feature branch, resolves plan/spec file paths, etc., then read that output and
apply the template. The Figma hooks add another such step — run
figma-ensure-context.sh, read its mustInject report, and integrate the rendered
design section.
Lightweight models such as Claude Haiku are built for fast, read-only exploration
and intermittently skip exactly this "run the script → read the result → apply the
instruction" chain. It is not really random — it is a reliability gap on structured,
multi-step instructions. With such a model there is a real risk the Figma hook is
silently skipped and the design section is never injected. (Inside Claude Code, the
exploration agent currently runs on Haiku for quick codebase searches — its real
niche, but not Spec Kit orchestration.) The after_* verify hooks reduce, but do
not eliminate, this risk.
For the steps that actually interpret the mockups (specify, plan), Opus is
preferable — that's where visual intent is translated into the spec, and an error
there propagates downstream.
The workspace's /speckit.specify, /speckit.plan and /speckit.tasks prompt
files are never modified by default. If your agent does not support SpecKit
extension hooks, opt into prompt injection with ./install.sh --prompt-hooks
(a managed block, refreshed in place on re-runs); a default install.sh run
removes any block injected by a previous extension version.
# run from the target workspace root (or pass --target /path/to/workspace-root)
# single-repo (default)
./install.sh
# mono-repo
./install.sh --mode mono-repo
# multi-repo (git submodules)
./install.sh --mode multi-repo
# then edit figma.projects.config.json, add credentials, and:
./.specify/scripts/bash/figma-validate-config.shOn Windows, run the PowerShell 7+ port instead — same flags, same output
(./install.ps1, then ./.specify/scripts/powershell/figma-validate-config.ps1).
Both installers copy both script families into the workspace
(.specify/scripts/bash/ and .specify/scripts/powershell/), so a mixed
macOS/Linux/Windows team shares one committed setup.
The installer also copies these guides into the workspace at .figma/docs/
(refreshed on every update, so they match the installed version) and appends a
short managed figma section to the workspace README.md (created if
missing): extension version + layout mode, the read-only PAT setup every
developer needs, and links to the local guides. Only the marked block is ever
touched, and it is refreshed in place on re-runs — pass --no-readme to opt
out.
See docs/INSTALL.md, docs/CREDENTIALS.md and docs/MONOREPO.md.
git, plus one script toolchain per developer machine:- macOS / Linux:
bash4+,curl,jq(runsscripts/bash/*.sh); - Windows: PowerShell 7+ (
pwsh) — runs thescripts/powershell/*.ps1ports, which use PowerShell's built-in JSON and HTTP support (nocurl, nojq). Same flags, same JSON output, same exit codes as the bash helpers, so commands, hooks and CI gates behave identically.
- macOS / Linux:
- A read-only Figma PAT (local) or a CI/Cloud secret (pipelines). Scopes scale
with the introspection level: a single file needs
file_content:read+file_metadata:read; project- or team-level introspection (figmaProjectId/figmaTeamId/figmaTeamIds) additionally requiresprojects:read(and the token must belong to a member of those teams) so the organization > team > projects > files hierarchy can be enumerated. See docs/CREDENTIALS.md for the full scope matrix. - Behind a corporate proxy? A transport failure (
curlexit 5, HTTP000) is a proxy/network problem, not a bad token. The single curl chokepoint auto-retries once with the proxy stripped; if it still fails, see docs/CREDENTIALS.md → Troubleshooting — proxy vs auth.
The engine is selected per workspace via figma.contextSource:
| Value | Engine | When |
|---|---|---|
"rest" (default) |
curl + jq against the Figma REST API | Always portable; the only engine guaranteed in CI. |
"mcp" |
A Figma MCP (Model Context Protocol) server | Richer context, and more faithful mockup implementation, for users who run the server locally. |
MCP yields more accurate implementations. Because the MCP engine exposes the design's structured node data — exact spacing, layout constraints, tokens, variants and component bindings — the agent reproduces mockups far more precisely than from the REST snapshot alone. When fidelity to the original Figma design matters, prefer
figma.contextSource: "mcp".
Tip
Using Claude Code? Install the official Figma plugin. It is by far the most reliable way to get MCP design context with Claude Code:
claude plugin install figma@claude-plugins-officialThe plugin wires Figma's hosted MCP server (https://mcp.figma.com/mcp) in
as a native Claude Code tool — no local Dev Mode server, no extra config — and
then you simply set figma.contextSource: "mcp" in
figma.projects.config.json. When the extension's scripts run inside Claude
Code and the plugin is absent, figma-resolve-source.sh (and /speckit.figma.setup)
print a one-line reminder; silence it with FIGMA_NO_PLUGIN_ADVICE=1. Note
this hosted server differs from the local Dev Mode MCP server
(http://127.0.0.1:3845/mcp), which the extension's curl probe targets by
default via figma.mcp.url.
Tip
Using VS Code? Add Figma's hosted MCP server. The same hosted server
(https://mcp.figma.com/mcp) works with any VS Code agent that supports MCP —
no local Dev Mode server required. With GitHub Copilot (agent mode), which
consumes VS Code's native MCP support, run MCP: Add Server… from the Command
Palette (pick HTTP, URL https://mcp.figma.com/mcp), or add it to your
workspace .vscode/mcp.json:
Other VS Code agents (Cline, Continue, the Claude Code extension…) do not
read .vscode/mcp.json — add the same URL through their own MCP configuration
instead. Sign in to Figma when prompted for OAuth, then set
figma.contextSource: "mcp" in figma.projects.config.json. (Auto-detection of
this server is Claude-Code-only; in VS Code, add it manually as above.)
With "mcp", configure figma.mcp (url, optional serverName,
fallbackToRest). The extension probes the server and, when it is unreachable,
transparently falls back to REST — unless fallbackToRest: false, which makes
an absent server a hard error. Resolve the effective engine at any time:
./.specify/scripts/bash/figma-resolve-source.sh
# -> {"requested":"mcp","effective":"rest","fellBack":true,
# "claudeCode":{"detected":true,"officialFigmaPlugin":false}, ...}The claudeCode block reports whether the run is inside Claude Code and whether
the official Figma plugin is installed, so tooling can recommend it when missing.
You keep full portability (REST) while offering MCP richness to those who have it.
The bash scripts are covered by a bats
test suite and linted with shellcheck.
# install tooling (macOS)
# bash is required: bats under the system bash 3.2 silently ignores failing
# assertions that are not the last command of a test (errexit limitation).
brew install bats-core shellcheck bash
# run the linter and the tests
shellcheck -x scripts/bash/*.sh install.sh
bats tests/The same checks run automatically on every pull request via GitHub Actions (.github/workflows/ci.yml).
Same routing rules, component resolution, token handling, responsive and
credential policies. Only the topology wrapper differs: a single-repo and a
mono-repo use a single repo object (the mono-repo additionally declares its
internal apps/libs), while a multi-repo uses a submodules map. Details
in docs/MONOREPO.md.
{ "servers": { "figma": { "type": "http", "url": "https://mcp.figma.com/mcp" } } }