feat(skills): reroute /figma by capability - REST/CLI for phases 1-3, MCP for 4-5 (M4)#1873
Conversation
baa7c79 to
e6617fd
Compare
9783899 to
5473a24
Compare
miga-heygen
left a comment
There was a problem hiding this comment.
Review — feat(skills): reroute /figma by capability (M4, stack 6/6)
Verdict: LGTM with nits
The skill rewrite is excellent. The phase table is immediately legible, the REST-vs-MCP split is well-reasoned (REST where it can, MCP where it must), two-credential scoping is clear with good failure guidance, and the storyboard section is genuinely impressive — the "frames are keyframes, not slides" cardinal rule and the element-chain diffing algorithm read like hard-won production lessons. Rate-limit tactics baked into a skill definition is a nice touch. All four catalog surfaces (CLAUDE.md, README.md, skills.mdx, hyperframes SKILL.md) updated in lockstep.
Findings
-
figma.tsHELP text is stale — thecomponentsubcommand is now registered in thesubCommandsmap (this PR adds that line), but the HELP string still only listsassetandtokens. A user runninghyperframes figmawith no args sees no mention ofcomponent. Suggest adding acomponententry to the HELP block. -
Storyboard batch export typo — SKILL.md, storyboard rule 6:
"Batch exports (elements or stills)::"has a double colon. Cosmetic. -
Storyboard transport gap — The phase table covers phases 1–5 but storyboards (which compose phases 1+3 for export + a custom animatic pipeline) aren't explicitly placed in the table. The routing section handles this, but an agent seeing the phase table alone might wonder which credential storyboards need. Consider a one-liner note: "Storyboard animatics compose Phase-1 asset exports (REST) with agent-driven timeline assembly."
-
skills.mdxtrailing whitespace — The/figmarow indocs/guides/skills.mdxextends well past the table column, making the raw markdown harder to read. Not a rendering issue, just noisy.
Ponytail
+97/-27 is mostly the SKILL.md rewrite (90 of the 97 additions). The skill grew from ~40 lines to ~110 — justified by the 5-phase structure, storyboard grammar, and rate-limit guidance that didn't exist before. The catalog-surface updates are 1-line-each mechanical sync. The figma.ts change is a single subcommand registration. No dead code, no duplication. The HELP text omission (finding 1) is the only real weight — fixing it would add ~1 line.
net: -0 lines possible (the growth is all load-bearing)
Review by Miga
james-russo-rames-d-jusso
left a comment
There was a problem hiding this comment.
Reviewed at b7054993d2 (stack 6/6, chain #1868→…→#1872→this).
Body carries 🤖 footer + AI-trailer per HF convention; noted.
Summary — Reshapes the /figma skill from "MCP-first" to a capability split (REST/CLI for phases 1-3, MCP-only for phases 4-5) and wires the component subcommand into the CLI dispatch map. Small surface (97+/27-), mostly docs + one-line dispatch. Routing determinism is straightforward (all four catalog surfaces updated in lockstep, no dynamic detection). One documentation-completeness gap.
Looks good to me modulo the nits below.
Concerns
🟠 packages/cli/src/commands/figma.ts:27-30 — subcommand added to dispatch map but not to HELP text.
This PR adds component: () => import(...) at line 43 and updates the meta description to "assets, tokens, and components (REST)", but the HELP string block still only lists asset and tokens:
SUBCOMMANDS:
asset Render a node ...
tokens Import variables/styles ...
Running hyperframes figma with no args prints a help block that doesn't advertise the new command — users have to read the skill doc or the PR body to discover it. Similarly the examples array at lines 13-20 has no component example; if _examples.ts feeds hyperframes figma --help or the docs site, component won't show. One-line add: a SUBCOMMANDS entry for component and an examples[] entry ("Import a frame as an editable HTML component", hyperframes figma component 'https://...'). Not a merge blocker, but the whole point of M4 is discoverability of the split.
Nits
🟡 skills/figma/SKILL.md — MCP rate-limit claim "6 tool calls/month" is load-bearing and worth a source link. The number drives the "batch with recursive:true" recommendation throughout the skill. If the plan tier changes upstream or Figma updates the quota, the skill's cache-first stance becomes wrong silently. A footnote citing Figma's public plan matrix (or a comment "@2026-07 Starter tier") would make the drift visible when it happens.
🟡 skills/figma/SKILL.md (Storyboards §, note-verb table) — the "MORPH / REVEALS → crossfade" and "CYCLE THROUGH / EACH ONE → longer hold on that scene" mappings collapse motion that Phase-3 components could animate correctly. Item 8 of the same section addresses this ("a note describing motion inside a scene → Phase-3 component import, not a flat PNG"), but the table above still tells the agent "crossfade" first. Consider a "or upgrade to Phase-3 if pixels differ inside a single scene" nudge on the crossfade rows.
🟡 skills/figma/SKILL.md (Motion §, step 4) — "bake: export_video → freeze MP4 → embed as <video class="clip">" is silent on shader-fallback determinism. The Phase-5 §sat below says "Figma's MCP render path does not execute shaders (they flatten to the base color)". If Motion step 4 falls back to export_video for a shader-driven track, that export flatten-to-base-color happens silently. Worth cross-linking Phase-5's "don't attempt MCP pixel capture of a shader" into step 4 explicitly.
🟡 docs/guides/skills.mdx:87 — trailing whitespace on the updated /figma row that the sibling rows don't have. Markdown-table linting will flag this on the next docs build; the raw diff shows a long tail of spaces after "into a composition." on this row only.
Questions
↩️ Migration path for users mid-flow on the old MCP-first path. A user who ran the old /figma skill yesterday against a Figma file — do they need to re-import (Phase 1) any frozen assets? The skill wording says "Split by capability (design spec §2)" but doesn't call out backwards-compat: are existing .media/figma-bindings.jsonl / manifest records compatible, or does someone need to nuke .media/figma-cache/ because the raw-response shape differs? If the answer is "yes, compat is trivial", one line ("existing frozen assets are unaffected — the split changes only which credential the next import uses") in the SKILL doc would head off support questions.
↩️ Rate-limit claim "REST is per-minute (10+/min)" — is this the file-level or endpoint-level bucket? Figma's public docs distinguish /v1/images (image renders) from /v1/files (tree/version), each with its own token-bucket. The skill treats them uniformly. If the agent hits 429 on /v1/images while a /v1/files call would still succeed, the current guidance ("back off on 429") applies the wrong backoff to the wrong endpoint. Not blocking; the current wording is defensible.
What I didn't verify
- The
skills-manifest.jsonhash values (a02c588600879115,2bd5cdf9f851b4d2) — trusted-as-recomputed by the manifest builder rather than hand-verified. - The two "verified live" storyboard reconstructions (26-scene animatic, 19-scene element-chain) referenced in the PR body — outside-of-diff artifact.
- Whether the
README.md+CLAUDE.md+docs/guides/skills.mdxtriplet is genuinely the exhaustive set of catalog surfaces (PR body claims "all four" but lists five including SKILL.md router and manifest — trusted).
— Rames D Jusso
5473a24 to
6868808
Compare
b42b417 to
0e334ee
Compare
|
Review feedback addressed (pushed in the absorbed update): Fixed
Since this review, the skill also gained a token preflight (checks shell env or project .env before the first CLI call, walks the user through setup instead of harvesting the error) and per-step narration guidance — plus a new docs page 🤖 Generated with Claude Code |
6868808 to
b4b9211
Compare
0e334ee to
4e2420f
Compare
b4b9211 to
2238d2f
Compare
4e2420f to
934e23b
Compare
miga-heygen
left a comment
There was a problem hiding this comment.
Re-review — feat(skills): reroute /figma by capability (M4, stack 6/6)
Verdict: LGTM
Three follow-up commits (e5cc6314, 934e23b5, 7b98354b) address review findings cleanly and add a polished first-run experience. The PR is in good shape.
Previous concerns
| # | Finding | Status |
|---|---|---|
| 1 | figma.ts HELP text missing component subcommand |
Fixed — component now listed with description in the reworked HELP block |
| 2 | Double colon typo in SKILL.md storyboard rule 6 | Fixed — single colon |
| 3 | Storyboard transport gap in phase table | Fixed — added the exact one-liner: "Storyboard animatics compose Phase-1 asset exports (REST) with agent-driven timeline assembly — no MCP needed." |
| 4 | skills.mdx trailing whitespace on /figma row |
Unchanged — cosmetic, not blocking |
New content review
cliError.ts — Clean shared error boundary. Splits on \n to extract title vs body for errorBox, which pairs well with the multi-line NO_TOKEN message. process.exit(1) is standard CLI practice. Non-Error throws rethrow correctly.
figma.ts HELP rework — The HELP block went from a bare env-var hint to a full first-time setup walkthrough (mint → scopes → export) plus a "what to expect" section on provenance/idempotency. This is the kind of CLI output that saves a support thread.
client.ts error enhancements — FORBIDDEN (generic 403) added to the error code union, slotted correctly after the enterpriseGated check so Enterprise 403s still route to REQUIRES_ENTERPRISE. The NO_TOKEN, BAD_TOKEN, and new FORBIDDEN messages are all actionable with specific fix instructions. Error codes in the client match the troubleshooting table in the new Mintlify guide 1:1.
docs/guides/figma.mdx — 117-line Mintlify guide covering all five phases, one-time setup with <Steps>, asset/token/component examples with CLI output, motion/shader/storyboard summary, provenance explanation, and a troubleshooting table. Well-structured user-facing documentation that mirrors the SKILL.md content without duplicating verbatim.
withFigmaErrors wiring — All three subcommands (asset.ts, tokens.ts, component.ts) consistently wrapped. The tokens.ts styles-fallback message got a helpful clarification ("style values resolve at component-import time").
Ponytail
+330/-71 across 14 files. The growth is the Mintlify guide (~117 lines), the reworked HELP/error messages, and the cliError.ts boundary. All load-bearing — no padding, no dead code.
CI: all required checks pass.
Review by Miga
miguel-heygen
left a comment
There was a problem hiding this comment.
LGTM. Stamping after Miga R2 verified the prior Figma-stack blockers are addressed; live checks are green, with only Graphite stack mergeability pending where applicable.
james-russo-rames-d-jusso
left a comment
There was a problem hiding this comment.
R2 verification — reviewed at 934e23b5 (post-force-push). 🟢
R1 was safe, only a docs-completeness nit. On re-read at HEAD, the nit was misframed — I'll withdraw it.
R1 nit (CLI-fallback when MCP unavailable + REST rate-limited) — withdrawn
At HEAD:
skills/figma/SKILL.md:14-18explicitly says Phases 4-5 (Motion, Shaders) are MCP-only — no REST equivalent exists at Figma's end, so there is no CLI to fall back to.skills/figma/SKILL.md:30documents the actual terminal state: "If MCP tools error unauthenticated, tell the user to connect the Figma connector and stop." That's the right shape — it's not a graceful-degrade path, it's a hard prerequisite.- REST rate-limiting on Phases 1-3 is already covered:
SKILL.md:34(per-minute backoff on 429) +docs/guides/figma.mdx:115(RATE_LIMITEDerror → "wait a minute and retry; chunk batch renders").
So the "MCP unavailable + REST rate-limited" case I imagined doesn't exist as a joint failure the docs need to cover — the two transports carry disjoint capabilities. My R1 was pattern-matching on "always document the fallback" without checking whether the fallback actually exists in this domain. Withdrawn.
R2 findings
None. Docs are consistent, rate-limit + credential-failure semantics are covered at all four catalog surfaces (CLAUDE.md, README.md, docs/guides/skills.mdx, SKILL.md), storyboard guidance is field-tested per PR body. Miga's R1 verdict (4621673047, LGTM with nits) holds.
Verdict
✅ LGTM. Clean docs PR. CI all green (perf, preview-regression, regression shards 1-8, player-perf); Graphite mergeability pending (standard for stacked PRs); Mintlify skipped (only skill/SKILL.md + one .mdx changed, no docs.json route add — appears to be intentionally out-of-scope for the Mintlify build).
— Rames D Jusso
…manifest, asset snippet (#1868) ## What Foundations of the `@hyperframes/core/figma` module — the pure, transport-agnostic layer every later phase builds on: - **`types.ts`** — `FigmaRef`, `FigmaProvenance`, `FigmaManifestRecord`, and the Motion model (`MotionDoc`/`MotionTrack`/`TimelineSpec`/`GsapTween`) shared across the stack. - **`parseFigmaRef`** — normalizes any user input (full `/design|/file|/proto` URLs with `?node-id=1-2`, `fileKey:nodeId` shorthand, bare `fileKey`) into `{ fileKey, nodeId }`, including the URL-dash → API-colon node-id conversion. - **`freeze.ts`** — `freezeBytes`/`freezeUrl`/`freezeLocalFile` with a 256 MB cap; every Figma asset is frozen to a local file before it can reach a composition (determinism: no render-time network). - **`manifest.ts`** — the `.media/manifest.jsonl` ledger (same layout `media-use` writes, so a project has one shared media inventory without either skill depending on the other): append/read/find-by-node/next-id, with a pure type-guard (`isFigmaManifestRecord`) instead of `as`-casts. - **`assetSnippet.ts`** — manifest record → composition `<img>` snippet with escaped attrs + `data-figma-id`. - **publishConfig fix** — `./figma` added to `packages/core` `publishConfig.exports` (the packed-manifest CI gate requires every source export to have a dist mapping). ## Why Design spec: `docs/superpowers/specs/2026-06-30-figma-asset-integration-design.md`. These functions are deliberately transport-agnostic — when the project reversed from MCP-first to a REST/MCP split (spec §2), nothing in this layer changed. That was the point. ## Tests Unit tests per module (URL variants, freeze cap edges, manifest round-trip/malformed-line tolerance, snippet escaping). All colocated `*.test.ts`, vitest, no network. --- Stack (1/6): this PR → #1869 → #1870 → #1871 → #1872 → #1873 🤖 Generated with [Claude Code](https://claude.com/claude-code)
2238d2f to
31f5e49
Compare
934e23b to
bc449a0
Compare
31f5e49 to
99a1a03
Compare
bc449a0 to
48b7d40
Compare
99a1a03 to
7bdb532
Compare
48b7d40 to
d659fa4
Compare
7bdb532 to
5ef97f0
Compare
d659fa4 to
b4ab9a4
Compare
5ef97f0 to
2cbb1f7
Compare
b4ab9a4 to
662d6da
Compare
2cbb1f7 to
36ce9c0
Compare
662d6da to
71c25d3
Compare
… MCP for 4-5 (M4) Rewrites the skill from MCP-first to the spec 2 split: asset/tokens/ component route through the hyperframes figma CLI (FIGMA_TOKEN), motion/ shaders stay agent-driven over MCP (no REST equivalent). Adds two- credential guidance, Starter rate-limit tactics (recursive:true, raw- response cache, opt-in screenshots), the 7.1 binding flow (tokens before components, one ask per unknown library, never value matching), and the shader manual-export default. Catalog blurbs updated in lockstep. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Field-tested against a real 26-scene storyboard section: the parsing grammar (frame-sized nodes incl. loose rectangles = scenes, x-order = time order, TEXT below the strip = director notes paired by x-overlap), batched still export (chunk ~4 ids per render call - big frames timeout past ~12), a note-verb -> transition vocabulary (EXPLOSION/SLIDE/MORPH/ CYCLE), and the stills-vs-component routing rule for within-scene motion notes. Catalog blurbs updated in lockstep. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Field-tested against a second real storyboard section: frames sharing an element (matched by name, else geometry similarity) define that element's states through time - tween the element between states, crossfade only when pixels genuinely differ, enter/exit unmatched children, tween frame backgrounds as a color track. Stills demoted to fallback for frames that don't decompose. Validated live: a 4-frame logo-rise reconstructed as one element with four keyframes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- NO_TOKEN/BAD_TOKEN errors now carry the full one-time setup (mint URL, read-only scope checklist, persist hint) instead of a bare pointer - figma subcommands print clean guidance on typed client errors, not a stack trace (shared withFigmaErrors boundary) - CLI help gains component subcommand, FIRST-TIME SETUP and WHAT TO EXPECT blocks - /figma skill: preflight the token before the first CLI call and walk the user through setup up front; narrate landed-artifact + next action at every step - new docs/guides/figma.mdx (setup, per-phase walkthroughs, provenance, troubleshooting table) wired into docs.json nav Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…emantics, docs accuracy - tokens.ts/component.ts called withFigmaErrors without importing it (tsup doesn't typecheck, so every invocation shipped as an immediate ReferenceError); imports added, tsc --noEmit now clean - error boundary widened to all Errors so bad-ref/bad-format input errors print their message instead of a stack trace - 401 no longer claims 'missing scopes' (figma signals that as 403); new FORBIDDEN code maps non-variables 403 to scope/access guidance - docs: asset/component refs require a node id (bare fileKey is tokens-only), example snippet matches real output, FORBIDDEN row - skill: preflight counts a project-.env token as configured (CLI auto-loads it); BAD_TOKEN/FORBIDDEN guidance split Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
71c25d3 to
e414c69
Compare
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Workflows to automatically generate PRs for you. |
e414c69 to
3d97339
Compare
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
3d97339 to
2b0ab8d
Compare

What
M4: the
/figmaskill rewritten from MCP-first to the capability split, plus storyboard guidance — with all four catalog surfaces updated in lockstep (CLAUDE.md,README.md,docs/guides/skills.mdx,skills/hyperframes/SKILL.mdrouter,skills-manifest.json).hyperframes figmaCLI over REST (FIGMA_TOKEN); motion/shaders → agent-driven MCP (no REST equivalent exists). Two-credential guidance: every failure says which credential that phase needs.recursive:truebatching on MCP, raw-response caching so retranslation never spends a second call, verification screenshots opt-in, REST 429 backoff.Verified
Both storyboard recipes executed live against real files before being written down: a 26-scene stills animatic (60s) and a 19-scene element-chain reconstruction (37s, 13 element exports instead of 19 slides), both lint/validate clean.
Stack (6/6): #1868 → #1869 → #1870 → #1871 → #1872 → this PR
🤖 Generated with Claude Code