@radicool/throughline 0.21.2 → 0.21.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/README.md +8 -8
  2. package/adapters/codex/prompts/component-builder.md +1 -1
  3. package/adapters/codex/prompts/design-system-audit.md +3 -1
  4. package/adapters/codex/prompts/figma-environment-setup.md +28 -30
  5. package/adapters/codex/prompts/storybook-chromatic-builder.md +4 -0
  6. package/adapters/codex/prompts/token-builder.md +1 -1
  7. package/adapters/codex/prompts/token-sheet-builder.md +1 -1
  8. package/adapters/codex/prompts/token-sync-layer.md +2 -2
  9. package/adapters/cursor/.cursor/rules/component-builder.mdc +1 -1
  10. package/adapters/cursor/.cursor/rules/design-system-audit.mdc +3 -1
  11. package/adapters/cursor/.cursor/rules/figma-environment-setup.mdc +28 -30
  12. package/adapters/cursor/.cursor/rules/storybook-chromatic-builder.mdc +4 -0
  13. package/adapters/cursor/.cursor/rules/token-builder.mdc +1 -1
  14. package/adapters/cursor/.cursor/rules/token-sheet-builder.mdc +1 -1
  15. package/adapters/cursor/.cursor/rules/token-sync-layer.mdc +2 -2
  16. package/adapters/generic/skills/component-builder/SKILL.md +1 -1
  17. package/adapters/generic/skills/design-system-audit/SKILL.md +3 -1
  18. package/adapters/generic/skills/figma-environment-setup/SKILL.md +28 -30
  19. package/adapters/generic/skills/storybook-chromatic-builder/SKILL.md +4 -0
  20. package/adapters/generic/skills/token-builder/SKILL.md +1 -1
  21. package/adapters/generic/skills/token-sheet-builder/SKILL.md +1 -1
  22. package/adapters/generic/skills/token-sync-layer/SKILL.md +2 -2
  23. package/package.json +1 -1
  24. package/references/manifest-schema.md +6 -4
  25. package/scripts/README.md +2 -2
  26. package/scripts/guard-token-removal.mjs +4 -4
  27. package/scripts/lib/source-scan.mjs +3 -3
package/README.md CHANGED
@@ -73,9 +73,9 @@ Everything above was created during a single working session and synced directly
73
73
 
74
74
  | | |
75
75
  |---|---|
76
- | **A supported agent** | Required — [Claude Code](https://docs.claude.com/en/docs/claude-code) (native plugin), or **Cursor**, **Codex**, or any **AGENTS.md**-aware agent via `npx @radicool/throughline init`. |
76
+ | **A supported agent** | Required — [Claude Code](https://docs.claude.com/en/docs/claude-code) (native plugin), or **Cursor**, **Codex**, or any **AGENTS.md**-aware agent via `npx @radicool/throughline@0.21.4 init`. |
77
77
  | **Figma** | Required, **desktop app** (the browser version causes connection errors). **Professional plan or higher recommended** — multi-mode variables (Light/Dark, brand themes) need it. |
78
- | **Figma access token** | Required — read/write your file. The setup skill walks you through it; your token stays yours and is never shared in chat. |
78
+ | **Figma access token** | Optional — only for the few Figma calls the Desktop Bridge can't make, like reading a published library. Without it, you work through the bridge alone. The setup skill walks you through it; your token stays yours and is never shared in chat. |
79
79
  | **GitHub** (or similar) | Optional — only when you're ready to graduate to a real remote repo with PRs and CI. |
80
80
 
81
81
  ### What it runs on your machine
@@ -114,9 +114,9 @@ Update anytime with `/plugin marketplace update throughline-marketplace`.
114
114
  Run the installer in your project — it stamps in the skills, the reference docs, the scripts, and the Figma MCP config for your tool:
115
115
 
116
116
  ```
117
- npx @radicool/throughline init --target=cursor # → .cursor/rules + .cursor/mcp.json
118
- npx @radicool/throughline init --target=codex # → prompts/ + AGENTS.md index + codex-mcp.toml
119
- npx @radicool/throughline init --target=generic # → skills/ + AGENTS.md index
117
+ npx @radicool/throughline@0.21.4 init --target=cursor # → .cursor/rules + .cursor/mcp.json
118
+ npx @radicool/throughline@0.21.4 init --target=codex # → prompts/ + AGENTS.md index + codex-mcp.toml
119
+ npx @radicool/throughline@0.21.4 init --target=generic # → skills/ + AGENTS.md index
120
120
  ```
121
121
 
122
122
  It's safe to re-run (it merges `AGENTS.md` and `.cursor/mcp.json` non-destructively) and stages everything the skills read into `.throughline/`. Then open the `figma-environment-setup` skill/rule/prompt for your tool to begin. For Codex, add the printed `codex-mcp.toml` block to your Codex config to enable Figma access.
@@ -127,7 +127,7 @@ ThroughLine is more than a pile of skills — it's a small system designed to st
127
127
 
128
128
  **🛠 Twelve skills — the steps.** Each owns one stage of the journey, from connecting Figma to retrofitting an existing system to standing up CI. They're sequenced, and each knows its prerequisites.
129
129
 
130
- **📐 Ten reference docs — the constitution.** Shared standards every skill obeys: Figma component rules (auto-layout-on-everything, slot contracts, naming-as-contract, a required post-build audit), the brainstorm-before-build protocol, the sync-adapter specs, the manifest schema, coding-level adaptivity, the publishing flow, and the brownfield-retrofit discipline (read-before-assert, the safe migration sequence, the crosswalk contract). This is *why* two different runs produce the same structure — the rules live in one place, not scattered per skill.
130
+ **📐 The reference docs — the constitution.** Shared standards every skill obeys: Figma component rules (auto-layout-on-everything, slot contracts, naming-as-contract, a required post-build audit), the brainstorm-before-build protocol, the sync-adapter specs, the manifest schema, coding-level adaptivity, the publishing flow, and the brownfield-retrofit discipline (read-before-assert, the safe migration sequence, the crosswalk contract). This is *why* two different runs produce the same structure — the rules live in one place, not scattered per skill.
131
131
 
132
132
  **🧭 An orchestration layer — the memory.** A `design-system.json` manifest in your project records exactly what's set up, with a versioned schema and immutability rules. Every skill reads it, tells you what it's about to do, and offers to run anything missing first. Run **`/design-system-status`** anytime for a plain-language picture of where you stand.
133
133
 
@@ -162,7 +162,7 @@ For the technically curious — how the machine actually runs.
162
162
 
163
163
  **Modes, within Figma's limits.** Light/Dark lives on the semantic collections; brand variants live on the primitive palette. Splitting the two axes across two collections keeps each one under Figma's 4-modes-per-collection cap on the Professional plan while still resolving correctly (`bg/default` → `{gray/50}` → the active brand's gray).
164
164
 
165
- **Model routing.** ThroughLine routes work by *cognition, not guesswork* — the expensive thinking on the best model, the mechanical doing on a cheap one. Setup runs on **Haiku** automatically to keep first-run costs low. Inside a skill, the deciding — a token architecture, a variant matrix, a slot contract — is planned once on the strongest tier, while the long mechanical part — placing Figma nodes, transcribing component code, running SVGR — runs on a cheap tier and self-verifies. You get the best model where it matters and a cheap one where it doesn't, without micromanaging it. The recommended mapping is **Haiku → Sonnet → Opus** for the `fast < balanced < deep` tiers, but nothing is hardcoded — the ladder resolves against whatever models your install actually has, and on hosts without subagents skills degrade cleanly to a single model. You can still steer the session yourself (`/model opus` for the heaviest authoring, back to `/model sonnet` after); nothing forces an expensive model on you.
165
+ **Model routing.** ThroughLine routes work by *cognition, not guesswork* — the expensive thinking on the best model, the mechanical doing on a cheap one. Setup pins **Haiku** to keep first-run costs low. Inside a skill, the deciding — a token architecture, a variant matrix, a slot contract — is planned once on the strongest tier, while the long mechanical part — placing Figma nodes, transcribing component code, running SVGR — runs on a cheap tier and self-verifies. You get the best model where it matters and a cheap one where it doesn't, without micromanaging it. The recommended mapping is **Haiku → Sonnet → Opus** for the `fast < balanced < deep` tiers, but apart from setup's Haiku pin, nothing is hardcoded — the ladder resolves against whatever models your install actually has, and on hosts without subagents skills degrade cleanly to a single model. You can still steer the session yourself (`/model opus` for the heaviest authoring, back to `/model sonnet` after); nothing forces an expensive model on you.
166
166
 
167
167
  ## Who it's for
168
168
 
@@ -212,7 +212,7 @@ Future improvements and planned capabilities. Have a request? **[Open an issue](
212
212
  - **Deeper Code Connect coverage** — richer Figma-to-code mappings as more plans support it.
213
213
  - **Expanded component starters** — a larger foundational kit out of the box.
214
214
  - **Richer status & auditing** — more from `/design-system-status`, including drift detection between Figma and code.
215
- - **Built-in accessibility checks** — the color half is shipped. Eight semantic text-on-surface pairs are checked against WCAG AA's 4.5:1 when tokens are created in Figma, and derived again from the token source when they sync to code — in every mode, so a system that clears in light and fails in dark fails. A failing pair stops the build rather than warning. Components are checked too: on web frameworks, a Figma build stops when a focus state has no visible ring, and in JSX code the adherence gate fails an icon-only button with no accessible name and a status badge that relies on color alone. Still ahead: focus-ring contrast (WCAG's 3:1 for non-text).
215
+ - **Built-in accessibility checks** — the color half is shipped. Eight semantic text-on-surface pairs are checked against WCAG AA's 4.5:1 when tokens are created in Figma, and derived again from the token source when they sync to code — in every mode, so a system that clears in light and fails in dark fails. A failing pair stops the build rather than warning. Components are checked too: on web frameworks, a Figma build stops when a focus state has no visible ring, and in JSX code the adherence gate is built to fail an icon-only button with no accessible name and a status badge that relies on color alone — proven by unit tests. The one real app it has run on had almost nothing for it to check, so it hasn't caught a bug in the wild yet. Still ahead: focus-ring contrast (WCAG's 3:1 for non-text).
216
216
  - **Token fan-out to more platforms** — the DTCG token source is platform-neutral, and web targets are in daily use. Every target is **validated per build, not assumed**: `tokens:validate-output` checks generated output against its source, native Swift and Kotlin as well as web CSS, because the stock transforms have been measured emitting wrong-but-compiling values. iOS/Swift is a curated adapter whose Style Dictionary configuration ships as tested code, and Android/Kotlin uses the same configuration through the Tier 2 protocol. JavaScript theme output (MUI, a Tailwind v3 config) isn't checked yet.
217
217
  - **Native component code generation** — producing a SwiftUI view or a Compose composable the way Storybook components are produced for React. This does not exist yet; it is a separate, larger effort than token fan-out, and the two were previously described as one roadmap item.
218
218
 
@@ -8,7 +8,7 @@ translate cleanly to code later.
8
8
 
9
9
  Needs tokens (`tokens.semanticBuilt` true) — offer to run `token-builder` if
10
10
  missing. Needs a live Figma connection (offer `figma-environment-setup` if not).
11
- Use the mechanism in `figma.mechanism`.
11
+ The plugin writes to Figma through Console MCP. If `figma.mechanism` holds anything other than `console-mcp`, say that value is no longer supported and offer `figma-environment-setup` to reset it.
12
12
 
13
13
  **Before scripting any `figma_execute`, read
14
14
  `.throughline/references/figma-scripting.md`** — the single-bridge-instance
@@ -22,7 +22,9 @@ across levels.
22
22
 
23
23
  Read the manifest. This skill needs Figma connected (`figma.connected: true`) for the
24
24
  inventory step, and a repo path for the code-surface step (`workspace.localPath`). If
25
- Figma isn't connected, offer to run `figma-environment-setup` first. The code-surface
25
+ Figma isn't connected, offer to run `figma-environment-setup` first. Before the
26
+ inventory, do a cheap liveness read to confirm the connection is actually live right
27
+ now; if it fails, offer `figma-environment-setup`. The code-surface
26
28
  step works on any repo regardless of `workspace.stage`.
27
29
 
28
30
  ## Step 1 — Size the code surface
@@ -9,8 +9,10 @@ This skill does three foundational jobs, in order:
9
9
  3. **Connect Codex to Figma** so later skills can read and write the file,
10
10
  then verify the connection works.
11
11
 
12
- It is the required first step. Every other Figma skill does a cheap liveness
13
- check and, if it fails, points the user back here.
12
+ It is the required first step. Every other skill that calls Figma itself does a
13
+ cheap liveness check and, if it fails, points the user back here. (The orchestrators
14
+ `component-pipeline` and `retrofit-planner` call Figma only through the skills they
15
+ invoke, and `token-crosswalk-builder` works from the manifest and token files.)
14
16
 
15
17
  ## Who you're talking to
16
18
 
@@ -223,28 +225,23 @@ Make clear it changes only how much detail they get, never what they can build.
223
225
  This is set now because it colors every later interaction. The Figma phase
224
226
  itself doesn't lean on it much, but the code phase (repo, sync, Storybook) does.
225
227
 
226
- ## Step 3 — Choose the Figma write mechanism
228
+ ## Step 3 — Figma write mechanism
227
229
 
228
- Explain there are two ways to connect Codex to Figma, and recommend the first:
230
+ ThroughLine connects to Figma through the **Figma Console MCP**. It can create
231
+ many variables at once efficiently (which saves time and usage), and it can read
232
+ your variables on any Figma plan, including free and Pro. The setup is light:
233
+ you'll run a small helper plugin inside Figma, and can optionally create one
234
+ access token.
229
235
 
230
- - **Figma Console MCP (recommended).** More capable — it can create many
231
- variables at once efficiently (which saves time and usage), and it can read
232
- your variables on any Figma plan, including free and Pro. Slightly more setup:
233
- you'll create one access token and run a small helper plugin inside Figma.
234
- - **Official Figma plugin (simpler fallback).** Less setup, but more limited —
235
- some bulk operations are slower, and reading variables through it can be
236
- restricted on non-Enterprise plans. Fine if the user wants the lightest path.
237
-
238
- Let the user choose. Record their choice in `figma.mechanism`
239
- (`"console-mcp"` or `"official-plugin"`). Default to `console-mcp` if they have
240
- no preference.
236
+ Record `figma.mechanism` as `"console-mcp"`. There is nothing for the user to
237
+ choose.
241
238
 
242
239
  The MCP server configuration ships **bundled with this plugin** (in the plugin's
243
240
  `.mcp.json`), so the user does not hand-edit any config files. The one thing the
244
241
  bundle can't contain is their personal access token — that's a per-user secret,
245
242
  handled in the next step.
246
243
 
247
- ## Step 4 — Connect to Figma (Console MCP path)
244
+ ## Step 4 — Connect to Figma
248
245
 
249
246
  Walk through these one at a time, confirming each before moving on. Never rush
250
247
  the user past a step.
@@ -257,10 +254,16 @@ browser version of Figma causes connection and token errors that are painful to
257
254
  debug. If they don't have the desktop app, point them to figma.com/downloads to
258
255
  install it first. Desktop app, every time.
259
256
 
260
- ### 4b. Create a Figma access token
257
+ ### 4b. Create a Figma access token (optional)
258
+
259
+ A token is like a password that lets Codex talk to Figma on your behalf. It's
260
+ **optional**: the desktop bridge does the reading and writing on its own. The
261
+ token only adds the few calls the bridge can't make, such as reading a published
262
+ library or a file's version history. Offer it, and say plainly that they can skip
263
+ it and add it later in **Configure options**. If they skip, record nothing about
264
+ it, leave the field blank, and go straight to 4c. Nothing later in setup needs it.
261
265
 
262
- A token is like a password that lets Codex talk to Figma on your behalf. Walk
263
- them through it:
266
+ If they want it, walk them through it:
264
267
 
265
268
  1. In a browser, go to figma.com and sign in (same account as the desktop app).
266
269
  2. Click your account menu, then Settings.
@@ -309,14 +312,6 @@ Codex and Figma are linked for this session."
309
312
  If the config was just added (token placed for the first time), the MCP client
310
313
  may need a restart to load it. Tell them how, simply, and confirm they're back.
311
314
 
312
- ## Step 4 (alt) — Connect to Figma (official plugin path)
313
-
314
- If the user chose the official plugin, the flow is lighter: install the official
315
- Figma plugin for Codex per its setup, ensure the desktop app is open with
316
- the file, and authenticate through the desktop app (again: desktop, not
317
- browser). The same secret-handling rule applies — any token goes into config by
318
- the user, never through the chat.
319
-
320
315
  ## Step 5 — Capture the file key
321
316
 
322
317
  Ask the user for the URL of the Figma file they want to build the design system
@@ -384,7 +379,7 @@ tokens or pairing here is useless. Diagnose in order:
384
379
 
385
380
  **B. The server started but the connection failed.** If there's no launch error
386
381
  and the server is clearly running, diagnose gently and in order: Is the desktop
387
- app open with the file? Was the token placed correctly (have them re-check,
382
+ app open with the file? If they added a token, was it placed correctly (have them re-check,
388
383
  without showing you the value)? Is the bridge plugin running and paired? Did the
389
384
  client need a restart? Walk them back through the relevant sub-step.
390
385
 
@@ -400,7 +395,8 @@ neutral placeholder built against nothing.
400
395
 
401
396
  - Create one trivial throwaway node (e.g. a small frame or text node named
402
397
  `__throughline write test`) on any page.
403
- - Confirm it landed with a quick read or `figma_capture_screenshot`.
398
+ - Confirm it landed with a quick read or `figma_capture_screenshot`. Neither needs
399
+ a token.
404
400
  - **Delete it.** If both the write and the delete succeed, writes are proven.
405
401
 
406
402
  Leave `figma.coverPageBuilt` = `false` here — that flag is set later, when the
@@ -445,7 +441,9 @@ restore point:
445
441
  `figma_get_file_versions`) or have the user name a Figma version so there's a known-good
446
442
  point to restore to. The plugin can read versions; it does not auto-create named
447
443
  versions, so if none exists, ask the user to add one ("File → Save to version
448
- history") and record that you did.
444
+ history") and record that you did. If the user skipped the access token and
445
+ the version read fails, say in one sentence that you can't read version history
446
+ without it, and have them name the version themselves.
449
447
  - **Token export** — if the repo already emits tokens, snapshot the current generated
450
448
  output (git is the natural baseline once `workspace.stage` is `local-git`+).
451
449
 
@@ -16,6 +16,10 @@ This skill needs:
16
16
  - Figma components (`components.built`) with their slot contracts, so stories
17
17
  reflect the real component APIs.
18
18
 
19
+ The Figma-touching steps (Code Connect in Step 5, the doc-card write-back in Step 6)
20
+ also need a live Figma connection — do a cheap liveness read before the first Figma
21
+ call; if it fails, offer `figma-environment-setup`.
22
+
19
23
  Strongly recommend `github` stage so Chromatic's CI integration works; it can be
20
24
  set up locally first and wired to CI when the remote exists.
21
25
 
@@ -35,7 +35,7 @@ now. If it isn't, say so plainly and offer to run the `figma-environment-setup`
35
35
  skill first: "Figma isn't connected yet — want me to set that up? It's a
36
36
  one-time thing." Don't proceed until Figma is reachable.
37
37
 
38
- Use the write mechanism recorded in `figma.mechanism` (default `console-mcp`).
38
+ The plugin writes to Figma through Console MCP. If `figma.mechanism` holds anything other than `console-mcp`, say that value is no longer supported and offer `figma-environment-setup` to reset it.
39
39
  With Console MCP, prefer `figma_execute` to create variables in scripted loops
40
40
  rather than one tool call per variable — this is dramatically more
41
41
  token-efficient for the potentially hundreds of primitives across modes.
@@ -24,7 +24,7 @@ a sensible companion step — the sheet and the synced code both reflect Figma.)
24
24
 
25
25
  Needs tokens in Figma (`tokens.semanticBuilt` true) and a live Figma connection.
26
26
  If tokens don't exist, offer to run `token-builder`. If Figma isn't connected,
27
- offer `figma-environment-setup`. Use the mechanism in `figma.mechanism`.
27
+ offer `figma-environment-setup`. The plugin writes to Figma through Console MCP. If `figma.mechanism` holds anything other than `console-mcp`, say that value is no longer supported and offer `figma-environment-setup` to reset it.
28
28
 
29
29
  **Before scripting any `figma_execute`, read
30
30
  `.throughline/references/figma-scripting.md`.** This sheet builds large
@@ -66,8 +66,8 @@ it.
66
66
 
67
67
  ## Step 2 — Extract Figma variables to DTCG JSON
68
68
 
69
- Using the active write mechanism (`figma.mechanism`, default Console MCP —
70
- prefer its full-design-system extraction, which works on any Figma plan), read
69
+ The plugin talks to Figma through Console MCP. If `figma.mechanism` holds anything other than `console-mcp`, say that value is no longer supported and offer `figma-environment-setup` to reset it. Using Console MCP's
70
+ full-design-system extraction (which works on any Figma plan), read
71
71
  **every variable collection** (there are now several per tier, e.g.
72
72
  `_Color/Primitive`, `Spacing/Primitive`, `Color/Semantic`, …) and normalize them
73
73
  into **DTCG-format JSON** (`$value`, `$type`, with semantic tokens expressed as
@@ -12,7 +12,7 @@ translate cleanly to code later.
12
12
 
13
13
  Needs tokens (`tokens.semanticBuilt` true) — offer to run `token-builder` if
14
14
  missing. Needs a live Figma connection (offer `figma-environment-setup` if not).
15
- Use the mechanism in `figma.mechanism`.
15
+ The plugin writes to Figma through Console MCP. If `figma.mechanism` holds anything other than `console-mcp`, say that value is no longer supported and offer `figma-environment-setup` to reset it.
16
16
 
17
17
  **Before scripting any `figma_execute`, read
18
18
  `.throughline/references/figma-scripting.md`** — the single-bridge-instance
@@ -26,7 +26,9 @@ across levels.
26
26
 
27
27
  Read the manifest. This skill needs Figma connected (`figma.connected: true`) for the
28
28
  inventory step, and a repo path for the code-surface step (`workspace.localPath`). If
29
- Figma isn't connected, offer to run `figma-environment-setup` first. The code-surface
29
+ Figma isn't connected, offer to run `figma-environment-setup` first. Before the
30
+ inventory, do a cheap liveness read to confirm the connection is actually live right
31
+ now; if it fails, offer `figma-environment-setup`. The code-surface
30
32
  step works on any repo regardless of `workspace.stage`.
31
33
 
32
34
  ## Step 1 — Size the code surface
@@ -13,8 +13,10 @@ This skill does three foundational jobs, in order:
13
13
  3. **Connect Cursor to Figma** so later skills can read and write the file,
14
14
  then verify the connection works.
15
15
 
16
- It is the required first step. Every other Figma skill does a cheap liveness
17
- check and, if it fails, points the user back here.
16
+ It is the required first step. Every other skill that calls Figma itself does a
17
+ cheap liveness check and, if it fails, points the user back here. (The orchestrators
18
+ `component-pipeline` and `retrofit-planner` call Figma only through the skills they
19
+ invoke, and `token-crosswalk-builder` works from the manifest and token files.)
18
20
 
19
21
  ## Who you're talking to
20
22
 
@@ -227,28 +229,23 @@ Make clear it changes only how much detail they get, never what they can build.
227
229
  This is set now because it colors every later interaction. The Figma phase
228
230
  itself doesn't lean on it much, but the code phase (repo, sync, Storybook) does.
229
231
 
230
- ## Step 3 — Choose the Figma write mechanism
232
+ ## Step 3 — Figma write mechanism
231
233
 
232
- Explain there are two ways to connect Cursor to Figma, and recommend the first:
234
+ ThroughLine connects to Figma through the **Figma Console MCP**. It can create
235
+ many variables at once efficiently (which saves time and usage), and it can read
236
+ your variables on any Figma plan, including free and Pro. The setup is light:
237
+ you'll run a small helper plugin inside Figma, and can optionally create one
238
+ access token.
233
239
 
234
- - **Figma Console MCP (recommended).** More capable — it can create many
235
- variables at once efficiently (which saves time and usage), and it can read
236
- your variables on any Figma plan, including free and Pro. Slightly more setup:
237
- you'll create one access token and run a small helper plugin inside Figma.
238
- - **Official Figma plugin (simpler fallback).** Less setup, but more limited —
239
- some bulk operations are slower, and reading variables through it can be
240
- restricted on non-Enterprise plans. Fine if the user wants the lightest path.
241
-
242
- Let the user choose. Record their choice in `figma.mechanism`
243
- (`"console-mcp"` or `"official-plugin"`). Default to `console-mcp` if they have
244
- no preference.
240
+ Record `figma.mechanism` as `"console-mcp"`. There is nothing for the user to
241
+ choose.
245
242
 
246
243
  The MCP server configuration ships **bundled with this plugin** (in the plugin's
247
244
  `.mcp.json`), so the user does not hand-edit any config files. The one thing the
248
245
  bundle can't contain is their personal access token — that's a per-user secret,
249
246
  handled in the next step.
250
247
 
251
- ## Step 4 — Connect to Figma (Console MCP path)
248
+ ## Step 4 — Connect to Figma
252
249
 
253
250
  Walk through these one at a time, confirming each before moving on. Never rush
254
251
  the user past a step.
@@ -261,10 +258,16 @@ browser version of Figma causes connection and token errors that are painful to
261
258
  debug. If they don't have the desktop app, point them to figma.com/downloads to
262
259
  install it first. Desktop app, every time.
263
260
 
264
- ### 4b. Create a Figma access token
261
+ ### 4b. Create a Figma access token (optional)
262
+
263
+ A token is like a password that lets Cursor talk to Figma on your behalf. It's
264
+ **optional**: the desktop bridge does the reading and writing on its own. The
265
+ token only adds the few calls the bridge can't make, such as reading a published
266
+ library or a file's version history. Offer it, and say plainly that they can skip
267
+ it and add it later in **Configure options**. If they skip, record nothing about
268
+ it, leave the field blank, and go straight to 4c. Nothing later in setup needs it.
265
269
 
266
- A token is like a password that lets Cursor talk to Figma on your behalf. Walk
267
- them through it:
270
+ If they want it, walk them through it:
268
271
 
269
272
  1. In a browser, go to figma.com and sign in (same account as the desktop app).
270
273
  2. Click your account menu, then Settings.
@@ -313,14 +316,6 @@ Cursor and Figma are linked for this session."
313
316
  If the config was just added (token placed for the first time), the MCP client
314
317
  may need a restart to load it. Tell them how, simply, and confirm they're back.
315
318
 
316
- ## Step 4 (alt) — Connect to Figma (official plugin path)
317
-
318
- If the user chose the official plugin, the flow is lighter: install the official
319
- Figma plugin for Cursor per its setup, ensure the desktop app is open with
320
- the file, and authenticate through the desktop app (again: desktop, not
321
- browser). The same secret-handling rule applies — any token goes into config by
322
- the user, never through the chat.
323
-
324
319
  ## Step 5 — Capture the file key
325
320
 
326
321
  Ask the user for the URL of the Figma file they want to build the design system
@@ -388,7 +383,7 @@ tokens or pairing here is useless. Diagnose in order:
388
383
 
389
384
  **B. The server started but the connection failed.** If there's no launch error
390
385
  and the server is clearly running, diagnose gently and in order: Is the desktop
391
- app open with the file? Was the token placed correctly (have them re-check,
386
+ app open with the file? If they added a token, was it placed correctly (have them re-check,
392
387
  without showing you the value)? Is the bridge plugin running and paired? Did the
393
388
  client need a restart? Walk them back through the relevant sub-step.
394
389
 
@@ -404,7 +399,8 @@ neutral placeholder built against nothing.
404
399
 
405
400
  - Create one trivial throwaway node (e.g. a small frame or text node named
406
401
  `__throughline write test`) on any page.
407
- - Confirm it landed with a quick read or `figma_capture_screenshot`.
402
+ - Confirm it landed with a quick read or `figma_capture_screenshot`. Neither needs
403
+ a token.
408
404
  - **Delete it.** If both the write and the delete succeed, writes are proven.
409
405
 
410
406
  Leave `figma.coverPageBuilt` = `false` here — that flag is set later, when the
@@ -449,7 +445,9 @@ restore point:
449
445
  `figma_get_file_versions`) or have the user name a Figma version so there's a known-good
450
446
  point to restore to. The plugin can read versions; it does not auto-create named
451
447
  versions, so if none exists, ask the user to add one ("File → Save to version
452
- history") and record that you did.
448
+ history") and record that you did. If the user skipped the access token and
449
+ the version read fails, say in one sentence that you can't read version history
450
+ without it, and have them name the version themselves.
453
451
  - **Token export** — if the repo already emits tokens, snapshot the current generated
454
452
  output (git is the natural baseline once `workspace.stage` is `local-git`+).
455
453
 
@@ -20,6 +20,10 @@ This skill needs:
20
20
  - Figma components (`components.built`) with their slot contracts, so stories
21
21
  reflect the real component APIs.
22
22
 
23
+ The Figma-touching steps (Code Connect in Step 5, the doc-card write-back in Step 6)
24
+ also need a live Figma connection — do a cheap liveness read before the first Figma
25
+ call; if it fails, offer `figma-environment-setup`.
26
+
23
27
  Strongly recommend `github` stage so Chromatic's CI integration works; it can be
24
28
  set up locally first and wired to CI when the remote exists.
25
29
 
@@ -39,7 +39,7 @@ now. If it isn't, say so plainly and offer to run the `figma-environment-setup`
39
39
  skill first: "Figma isn't connected yet — want me to set that up? It's a
40
40
  one-time thing." Don't proceed until Figma is reachable.
41
41
 
42
- Use the write mechanism recorded in `figma.mechanism` (default `console-mcp`).
42
+ The plugin writes to Figma through Console MCP. If `figma.mechanism` holds anything other than `console-mcp`, say that value is no longer supported and offer `figma-environment-setup` to reset it.
43
43
  With Console MCP, prefer `figma_execute` to create variables in scripted loops
44
44
  rather than one tool call per variable — this is dramatically more
45
45
  token-efficient for the potentially hundreds of primitives across modes.
@@ -28,7 +28,7 @@ a sensible companion step — the sheet and the synced code both reflect Figma.)
28
28
 
29
29
  Needs tokens in Figma (`tokens.semanticBuilt` true) and a live Figma connection.
30
30
  If tokens don't exist, offer to run `token-builder`. If Figma isn't connected,
31
- offer `figma-environment-setup`. Use the mechanism in `figma.mechanism`.
31
+ offer `figma-environment-setup`. The plugin writes to Figma through Console MCP. If `figma.mechanism` holds anything other than `console-mcp`, say that value is no longer supported and offer `figma-environment-setup` to reset it.
32
32
 
33
33
  **Before scripting any `figma_execute`, read
34
34
  `.throughline/references/figma-scripting.md`.** This sheet builds large
@@ -70,8 +70,8 @@ it.
70
70
 
71
71
  ## Step 2 — Extract Figma variables to DTCG JSON
72
72
 
73
- Using the active write mechanism (`figma.mechanism`, default Console MCP —
74
- prefer its full-design-system extraction, which works on any Figma plan), read
73
+ The plugin talks to Figma through Console MCP. If `figma.mechanism` holds anything other than `console-mcp`, say that value is no longer supported and offer `figma-environment-setup` to reset it. Using Console MCP's
74
+ full-design-system extraction (which works on any Figma plan), read
75
75
  **every variable collection** (there are now several per tier, e.g.
76
76
  `_Color/Primitive`, `Spacing/Primitive`, `Color/Semantic`, …) and normalize them
77
77
  into **DTCG-format JSON** (`$value`, `$type`, with semantic tokens expressed as
@@ -8,7 +8,7 @@ translate cleanly to code later.
8
8
 
9
9
  Needs tokens (`tokens.semanticBuilt` true) — offer to run `token-builder` if
10
10
  missing. Needs a live Figma connection (offer `figma-environment-setup` if not).
11
- Use the mechanism in `figma.mechanism`.
11
+ The plugin writes to Figma through Console MCP. If `figma.mechanism` holds anything other than `console-mcp`, say that value is no longer supported and offer `figma-environment-setup` to reset it.
12
12
 
13
13
  **Before scripting any `figma_execute`, read
14
14
  `.throughline/references/figma-scripting.md`** — the single-bridge-instance
@@ -22,7 +22,9 @@ across levels.
22
22
 
23
23
  Read the manifest. This skill needs Figma connected (`figma.connected: true`) for the
24
24
  inventory step, and a repo path for the code-surface step (`workspace.localPath`). If
25
- Figma isn't connected, offer to run `figma-environment-setup` first. The code-surface
25
+ Figma isn't connected, offer to run `figma-environment-setup` first. Before the
26
+ inventory, do a cheap liveness read to confirm the connection is actually live right
27
+ now; if it fails, offer `figma-environment-setup`. The code-surface
26
28
  step works on any repo regardless of `workspace.stage`.
27
29
 
28
30
  ## Step 1 — Size the code surface
@@ -9,8 +9,10 @@ This skill does three foundational jobs, in order:
9
9
  3. **Connect the agent to Figma** so later skills can read and write the file,
10
10
  then verify the connection works.
11
11
 
12
- It is the required first step. Every other Figma skill does a cheap liveness
13
- check and, if it fails, points the user back here.
12
+ It is the required first step. Every other skill that calls Figma itself does a
13
+ cheap liveness check and, if it fails, points the user back here. (The orchestrators
14
+ `component-pipeline` and `retrofit-planner` call Figma only through the skills they
15
+ invoke, and `token-crosswalk-builder` works from the manifest and token files.)
14
16
 
15
17
  ## Who you're talking to
16
18
 
@@ -223,28 +225,23 @@ Make clear it changes only how much detail they get, never what they can build.
223
225
  This is set now because it colors every later interaction. The Figma phase
224
226
  itself doesn't lean on it much, but the code phase (repo, sync, Storybook) does.
225
227
 
226
- ## Step 3 — Choose the Figma write mechanism
228
+ ## Step 3 — Figma write mechanism
227
229
 
228
- Explain there are two ways to connect the agent to Figma, and recommend the first:
230
+ ThroughLine connects to Figma through the **Figma Console MCP**. It can create
231
+ many variables at once efficiently (which saves time and usage), and it can read
232
+ your variables on any Figma plan, including free and Pro. The setup is light:
233
+ you'll run a small helper plugin inside Figma, and can optionally create one
234
+ access token.
229
235
 
230
- - **Figma Console MCP (recommended).** More capable — it can create many
231
- variables at once efficiently (which saves time and usage), and it can read
232
- your variables on any Figma plan, including free and Pro. Slightly more setup:
233
- you'll create one access token and run a small helper plugin inside Figma.
234
- - **Official Figma plugin (simpler fallback).** Less setup, but more limited —
235
- some bulk operations are slower, and reading variables through it can be
236
- restricted on non-Enterprise plans. Fine if the user wants the lightest path.
237
-
238
- Let the user choose. Record their choice in `figma.mechanism`
239
- (`"console-mcp"` or `"official-plugin"`). Default to `console-mcp` if they have
240
- no preference.
236
+ Record `figma.mechanism` as `"console-mcp"`. There is nothing for the user to
237
+ choose.
241
238
 
242
239
  The MCP server configuration ships **bundled with this plugin** (in the plugin's
243
240
  `.mcp.json`), so the user does not hand-edit any config files. The one thing the
244
241
  bundle can't contain is their personal access token — that's a per-user secret,
245
242
  handled in the next step.
246
243
 
247
- ## Step 4 — Connect to Figma (Console MCP path)
244
+ ## Step 4 — Connect to Figma
248
245
 
249
246
  Walk through these one at a time, confirming each before moving on. Never rush
250
247
  the user past a step.
@@ -257,10 +254,16 @@ browser version of Figma causes connection and token errors that are painful to
257
254
  debug. If they don't have the desktop app, point them to figma.com/downloads to
258
255
  install it first. Desktop app, every time.
259
256
 
260
- ### 4b. Create a Figma access token
257
+ ### 4b. Create a Figma access token (optional)
258
+
259
+ A token is like a password that lets the agent talk to Figma on your behalf. It's
260
+ **optional**: the desktop bridge does the reading and writing on its own. The
261
+ token only adds the few calls the bridge can't make, such as reading a published
262
+ library or a file's version history. Offer it, and say plainly that they can skip
263
+ it and add it later in **Configure options**. If they skip, record nothing about
264
+ it, leave the field blank, and go straight to 4c. Nothing later in setup needs it.
261
265
 
262
- A token is like a password that lets the agent talk to Figma on your behalf. Walk
263
- them through it:
266
+ If they want it, walk them through it:
264
267
 
265
268
  1. In a browser, go to figma.com and sign in (same account as the desktop app).
266
269
  2. Click your account menu, then Settings.
@@ -309,14 +312,6 @@ the agent and Figma are linked for this session."
309
312
  If the config was just added (token placed for the first time), the MCP client
310
313
  may need a restart to load it. Tell them how, simply, and confirm they're back.
311
314
 
312
- ## Step 4 (alt) — Connect to Figma (official plugin path)
313
-
314
- If the user chose the official plugin, the flow is lighter: install the official
315
- Figma plugin for your coding agent per its setup, ensure the desktop app is open with
316
- the file, and authenticate through the desktop app (again: desktop, not
317
- browser). The same secret-handling rule applies — any token goes into config by
318
- the user, never through the chat.
319
-
320
315
  ## Step 5 — Capture the file key
321
316
 
322
317
  Ask the user for the URL of the Figma file they want to build the design system
@@ -384,7 +379,7 @@ tokens or pairing here is useless. Diagnose in order:
384
379
 
385
380
  **B. The server started but the connection failed.** If there's no launch error
386
381
  and the server is clearly running, diagnose gently and in order: Is the desktop
387
- app open with the file? Was the token placed correctly (have them re-check,
382
+ app open with the file? If they added a token, was it placed correctly (have them re-check,
388
383
  without showing you the value)? Is the bridge plugin running and paired? Did the
389
384
  client need a restart? Walk them back through the relevant sub-step.
390
385
 
@@ -400,7 +395,8 @@ neutral placeholder built against nothing.
400
395
 
401
396
  - Create one trivial throwaway node (e.g. a small frame or text node named
402
397
  `__throughline write test`) on any page.
403
- - Confirm it landed with a quick read or `figma_capture_screenshot`.
398
+ - Confirm it landed with a quick read or `figma_capture_screenshot`. Neither needs
399
+ a token.
404
400
  - **Delete it.** If both the write and the delete succeed, writes are proven.
405
401
 
406
402
  Leave `figma.coverPageBuilt` = `false` here — that flag is set later, when the
@@ -445,7 +441,9 @@ restore point:
445
441
  `figma_get_file_versions`) or have the user name a Figma version so there's a known-good
446
442
  point to restore to. The plugin can read versions; it does not auto-create named
447
443
  versions, so if none exists, ask the user to add one ("File → Save to version
448
- history") and record that you did.
444
+ history") and record that you did. If the user skipped the access token and
445
+ the version read fails, say in one sentence that you can't read version history
446
+ without it, and have them name the version themselves.
449
447
  - **Token export** — if the repo already emits tokens, snapshot the current generated
450
448
  output (git is the natural baseline once `workspace.stage` is `local-git`+).
451
449
 
@@ -16,6 +16,10 @@ This skill needs:
16
16
  - Figma components (`components.built`) with their slot contracts, so stories
17
17
  reflect the real component APIs.
18
18
 
19
+ The Figma-touching steps (Code Connect in Step 5, the doc-card write-back in Step 6)
20
+ also need a live Figma connection — do a cheap liveness read before the first Figma
21
+ call; if it fails, offer `figma-environment-setup`.
22
+
19
23
  Strongly recommend `github` stage so Chromatic's CI integration works; it can be
20
24
  set up locally first and wired to CI when the remote exists.
21
25
 
@@ -35,7 +35,7 @@ now. If it isn't, say so plainly and offer to run the `figma-environment-setup`
35
35
  skill first: "Figma isn't connected yet — want me to set that up? It's a
36
36
  one-time thing." Don't proceed until Figma is reachable.
37
37
 
38
- Use the write mechanism recorded in `figma.mechanism` (default `console-mcp`).
38
+ The plugin writes to Figma through Console MCP. If `figma.mechanism` holds anything other than `console-mcp`, say that value is no longer supported and offer `figma-environment-setup` to reset it.
39
39
  With Console MCP, prefer `figma_execute` to create variables in scripted loops
40
40
  rather than one tool call per variable — this is dramatically more
41
41
  token-efficient for the potentially hundreds of primitives across modes.
@@ -24,7 +24,7 @@ a sensible companion step — the sheet and the synced code both reflect Figma.)
24
24
 
25
25
  Needs tokens in Figma (`tokens.semanticBuilt` true) and a live Figma connection.
26
26
  If tokens don't exist, offer to run `token-builder`. If Figma isn't connected,
27
- offer `figma-environment-setup`. Use the mechanism in `figma.mechanism`.
27
+ offer `figma-environment-setup`. The plugin writes to Figma through Console MCP. If `figma.mechanism` holds anything other than `console-mcp`, say that value is no longer supported and offer `figma-environment-setup` to reset it.
28
28
 
29
29
  **Before scripting any `figma_execute`, read
30
30
  `.throughline/references/figma-scripting.md`.** This sheet builds large
@@ -66,8 +66,8 @@ it.
66
66
 
67
67
  ## Step 2 — Extract Figma variables to DTCG JSON
68
68
 
69
- Using the active write mechanism (`figma.mechanism`, default Console MCP —
70
- prefer its full-design-system extraction, which works on any Figma plan), read
69
+ The plugin talks to Figma through Console MCP. If `figma.mechanism` holds anything other than `console-mcp`, say that value is no longer supported and offer `figma-environment-setup` to reset it. Using Console MCP's
70
+ full-design-system extraction (which works on any Figma plan), read
71
71
  **every variable collection** (there are now several per tier, e.g.
72
72
  `_Color/Primitive`, `Spacing/Primitive`, `Color/Semantic`, …) and normalize them
73
73
  into **DTCG-format JSON** (`$value`, `$type`, with semantic tokens expressed as
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@radicool/throughline",
3
- "version": "0.21.2",
3
+ "version": "0.21.4",
4
4
  "description": "Build a complete design system end to end — author in Figma, sync tokens to code, generate Storybook. Usable from Claude Code, Cursor, Codex, or any AGENTS.md agent.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -162,10 +162,12 @@ bailing or running silently.
162
162
  - `syncLayer` — `style-dictionary.config.js` or `*.style-dictionary.js` files present at the project root or within immediate subdirectories
163
163
 
164
164
  ### `figma`
165
- - `mechanism` — which write mechanism is active. One of `"console-mcp"`
166
- (default, recommended) or `"official-plugin"` (lower-setup fallback). Set by
167
- skill 0. The adapter layer in every Figma skill reads this to know which tool
168
- names to use.
165
+ - `mechanism` — which write mechanism is active. `"console-mcp"` is the only
166
+ supported value. Set by skill 0. The adapter layer in every Figma skill reads
167
+ this to know which tool names to use. A manifest written by an earlier version
168
+ may hold `"official-plugin"`; that value is unsupported (no agent or bundled
169
+ MCP server backs it), and re-running `figma-environment-setup` resets it to
170
+ `"console-mcp"`.
169
171
  - `fileKey` — the Figma file key the system writes into (extracted from the
170
172
  file URL). Lets skills target the right file without re-asking.
171
173
  - `connected` — whether setup completed successfully at least once. Note this is
package/scripts/README.md CHANGED
@@ -9,7 +9,7 @@ tested here; copied verbatim by `token-crosswalk-builder` into the user's
9
9
  | --- | --- | --- |
10
10
  | `validate-crosswalk.mjs` | Resolve every `newToken` against the DTCG token source; assert resolved value == `newValue`, N/N. The CI gate. | `tokens:validate` |
11
11
  | `build-reverse-index.mjs` | Emit a `codeToken -> newToken` map from the crosswalk to semi-automate SCSS/Tailwind swaps. | `tokens:reverse-index` |
12
- | `guard-token-removal.mjs` | Grep `.ts/.tsx` (minus generated + tests) for about-to-be-deleted symbols; blocks cleanup until zero references remain. | run during the cleanup phase |
12
+ | `guard-token-removal.mjs` | Grep every source file the shared walker reads — `.scss`, `.css`, `.tsx?`, `.jsx?`, `.html` and the rest of `SOURCE_EXT` (minus generated + tests) for about-to-be-deleted symbols; blocks cleanup until zero references remain. | run during the cleanup phase |
13
13
  | `validate-token-output.mjs` | Assert generated token output — Swift, Kotlin, or web CSS custom properties — matches its DTCG source: authored-unit fidelity and no mode collisions everywhere, plus no leaked CSS syntax and no bare unit literals in Swift and Kotlin. Fails when no emitted symbol matches a source token, and reports match rate, unparsed lines, and unemitted tokens on every run. | `tokens:validate-output` |
14
14
  | `validate-adherence.mjs` | Assert the code *consuming* a design system still adheres to it: every referenced component exists, every literal variant value is one the system declares, and no colour, spacing, radius or type literal duplicates a token that already holds that value. `unnamed-control` fails a Button or IconButton (or a component whose doc record says `archetype: "button"`) with no accessible name: no text, and no `aria-label`, `aria-labelledby` or `title` on it or anything inside it. `colour-only-status` fails a Badge or Tag (or a record with `archetype: "badge"`) the same way, so its status isn't carried by colour alone. Both read script files only (`.js`, `.jsx`, `.ts`, `.tsx`, `.mjs`, `.cjs`), abstain rather than guess on anything they can't read, print how many elements they checked and abstained on, and can be switched off with `--skip`. Fails when an enabled rule had nothing to check, so a green run always means something was verified. | `adherence:check` |
15
15
  | `lib/source-scan.mjs` | Shared source-tree walker (`walk`, `DEFAULT_EXCLUDES`, `SOURCE_EXT`) plus `normalizeName`, the display-name-to-code-identifier fold. Every gate that scans a consumer's repo reads it from here rather than carrying its own copy. | copied alongside `guard-token-removal.mjs`, and in the documentation set for `validate-adherence.mjs` and `verify-check.mjs` |
@@ -245,7 +245,7 @@ the committed `adapters/<target>/` tree plus the runtime payload
245
245
  (`references/` + `scripts/`, minus `scripts/adapters/`) into `.throughline/`,
246
246
  rewriting `${CLAUDE_PLUGIN_ROOT}` → `.throughline`:
247
247
 
248
- npx @radicool/throughline init --target=cursor|codex|generic
248
+ npx @radicool/throughline@0.21.4 init --target=cursor|codex|generic
249
249
 
250
250
  See `scripts/install.mjs` (pure core + CLI + `install.test.mjs`).
251
251
 
@@ -1,4 +1,4 @@
1
- // Repo-wide token-removal guard: grep .ts/.tsx (minus generated + tests) for
1
+ // Repo-wide token-removal guard: grep source files (minus generated + tests) for
2
2
  // references to about-to-be-deleted symbols. Zero dependencies.
3
3
  //
4
4
  // Cleanup must not proceed until this returns zero references — deleted Tailwind
@@ -33,9 +33,9 @@ export function scanFile(path, symbols) {
33
33
 
34
34
  export function guard(root, symbols, excludes = DEFAULT_EXCLUDES) {
35
35
  const findings = [];
36
- // .ts/.tsx is this guard's own contract, so the filter stays here rather
37
- // than moving into the shared walker's default.
38
- for (const file of walk(root, { excludes, fileFilter: /\.tsx?$/ })) {
36
+ // A token can be referenced from a stylesheet or markup as easily as from
37
+ // TypeScript, so this reads every file type the shared walker defaults to.
38
+ for (const file of walk(root, { excludes })) {
39
39
  for (const hit of scanFile(file, symbols)) {
40
40
  findings.push({ file: relative(root, file), ...hit });
41
41
  }
@@ -5,9 +5,9 @@
5
5
  // extensions it yielded. The duplication was the shape #57 was filed for: two
6
6
  // definitions of one rule, agreeing today, with nothing keeping them in step.
7
7
  //
8
- // The file filter is the caller's, not a built-in: a colour scan wants
9
- // stylesheets and a symbol guard does not, and neither should have to fork the
10
- // walker to say so.
8
+ // The file filter is the caller's, not a built-in: a caller that
9
+ // wants stylesheets and HTML takes them, and one that wants only .ts/.tsx can
10
+ // narrow it, without forking the walker.
11
11
  import { readdirSync, statSync } from 'node:fs';
12
12
  import { join } from 'node:path';
13
13