designlang 6.0.0 → 7.0.0

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 (35) hide show
  1. package/.github/FUNDING.yml +1 -0
  2. package/.github/ISSUE_TEMPLATE/bug_report.yml +62 -0
  3. package/.github/ISSUE_TEMPLATE/config.yml +8 -0
  4. package/.github/ISSUE_TEMPLATE/feature_request.yml +28 -0
  5. package/CHANGELOG.md +43 -0
  6. package/README.md +111 -1
  7. package/bin/design-extract.js +88 -2
  8. package/docs/superpowers/plans/2026-04-18-designlang-v7.md +1121 -0
  9. package/docs/superpowers/specs/2026-04-18-designlang-v7-design.md +150 -0
  10. package/package.json +5 -4
  11. package/src/config.js +23 -0
  12. package/src/crawler.js +116 -0
  13. package/src/extractors/a11y-remediation.js +47 -0
  14. package/src/extractors/component-clusters.js +39 -0
  15. package/src/extractors/css-health.js +151 -0
  16. package/src/extractors/scoring.js +20 -1
  17. package/src/extractors/semantic-regions.js +44 -0
  18. package/src/extractors/stack-fingerprint.js +88 -0
  19. package/src/formatters/_token-ref.js +44 -0
  20. package/src/formatters/agent-rules.js +116 -0
  21. package/src/formatters/android-compose.js +164 -0
  22. package/src/formatters/dtcg-tokens.js +175 -0
  23. package/src/formatters/flutter-dart.js +130 -0
  24. package/src/formatters/ios-swiftui.js +161 -0
  25. package/src/formatters/markdown.js +25 -0
  26. package/src/formatters/wordpress.js +183 -0
  27. package/src/index.js +30 -0
  28. package/src/mcp/resources.js +64 -0
  29. package/src/mcp/server.js +110 -0
  30. package/src/mcp/tools.js +149 -0
  31. package/tests/cli.test.js +50 -0
  32. package/tests/extractors.test.js +131 -0
  33. package/tests/formatters.test.js +232 -0
  34. package/tests/mcp.test.js +68 -0
  35. package/website/app/globals.css +11 -11
@@ -0,0 +1 @@
1
+ github: [Manavarya09]
@@ -0,0 +1,62 @@
1
+ name: Bug report
2
+ description: Something in designlang is broken or produces wrong output.
3
+ title: "[Bug]: "
4
+ labels: ["bug"]
5
+ body:
6
+ - type: input
7
+ id: url
8
+ attributes:
9
+ label: URL extracted
10
+ description: The site you ran designlang against.
11
+ placeholder: https://example.com
12
+ validations:
13
+ required: true
14
+ - type: input
15
+ id: command
16
+ attributes:
17
+ label: Command used
18
+ description: The exact command you ran.
19
+ placeholder: npx designlang https://example.com --full
20
+ validations:
21
+ required: true
22
+ - type: textarea
23
+ id: expected
24
+ attributes:
25
+ label: What you expected
26
+ validations:
27
+ required: true
28
+ - type: textarea
29
+ id: actual
30
+ attributes:
31
+ label: What actually happened
32
+ description: Include stack traces, log output, or relevant snippets from output files.
33
+ validations:
34
+ required: true
35
+ - type: input
36
+ id: version
37
+ attributes:
38
+ label: designlang version
39
+ description: Output of `npx designlang --version` (or the version in package.json)
40
+ placeholder: 7.0.0
41
+ validations:
42
+ required: true
43
+ - type: input
44
+ id: node
45
+ attributes:
46
+ label: Node.js version
47
+ description: Output of `node --version`
48
+ placeholder: v20.11.0
49
+ validations:
50
+ required: true
51
+ - type: input
52
+ id: os
53
+ attributes:
54
+ label: OS
55
+ placeholder: macOS 14.5 / Ubuntu 22.04 / Windows 11
56
+ validations:
57
+ required: true
58
+ - type: textarea
59
+ id: extra
60
+ attributes:
61
+ label: Anything else
62
+ description: Screenshots, env variables, network constraints, auth requirements, etc.
@@ -0,0 +1,8 @@
1
+ blank_issues_enabled: false
2
+ contact_links:
3
+ - name: Question or discussion
4
+ url: https://github.com/Manavarya09/design-extract/discussions
5
+ about: Ask a question, share an extraction, or discuss ideas.
6
+ - name: designlang website
7
+ url: https://website-five-lime-65.vercel.app
8
+ about: Read more about what designlang does.
@@ -0,0 +1,28 @@
1
+ name: Feature request
2
+ description: Suggest a new extraction, output format, or CLI capability.
3
+ title: "[Feature]: "
4
+ labels: ["enhancement"]
5
+ body:
6
+ - type: textarea
7
+ id: problem
8
+ attributes:
9
+ label: Problem
10
+ description: What are you trying to do that designlang doesn't support today?
11
+ validations:
12
+ required: true
13
+ - type: textarea
14
+ id: proposal
15
+ attributes:
16
+ label: Proposal
17
+ description: What should designlang do? CLI flag, command, new extractor, new output format?
18
+ validations:
19
+ required: true
20
+ - type: textarea
21
+ id: alternatives
22
+ attributes:
23
+ label: Alternatives you've considered
24
+ - type: textarea
25
+ id: context
26
+ attributes:
27
+ label: Additional context
28
+ description: Example sites, example outputs, links to similar tools, screenshots.
package/CHANGELOG.md ADDED
@@ -0,0 +1,43 @@
1
+ # Changelog
2
+
3
+ ## [7.0.0] — 2026-04-18
4
+
5
+ ### Breaking
6
+
7
+ - **Design token JSON format** — the default `*-design-tokens.json` now follows the W3C Design Tokens Community Group (DTCG) v1 spec: every leaf is `{ "$value": ..., "$type": ... }`, with two layers (`primitive.*` and `semantic.*`) and composite tokens for typography, shadow, border, and gradient. If a downstream consumer expects the pre-v7 flat shape, pass `--tokens-legacy` to preserve it.
8
+
9
+ Before (v6):
10
+ ```json
11
+ { "color": { "primary": "#3b82f6" }, "fontFamily": { "sans": "Inter" } }
12
+ ```
13
+
14
+ After (v7, default):
15
+ ```json
16
+ {
17
+ "$metadata": { "generator": "designlang", "version": "7.0.0" },
18
+ "primitive": { "color": { "brand": { "primary": { "$value": "#3b82f6", "$type": "color" } } } },
19
+ "semantic": { "color": { "action": { "primary": { "$value": "{primitive.color.brand.primary}", "$type": "color" } } } }
20
+ }
21
+ ```
22
+
23
+ Migration: either (a) update consumers to read the DTCG shape (recommended — long-term stable, ecosystem-compatible), or (b) add `--tokens-legacy` to the CLI invocation.
24
+
25
+ ### Added
26
+
27
+ - **MCP server** — new `designlang mcp --output-dir <dir>` subcommand. Stdio JSON-RPC. Resources: `designlang://tokens/primitive`, `designlang://tokens/semantic`, `designlang://regions`, `designlang://components`, `designlang://health`. Tools: `search_tokens`, `find_nearest_color`, `get_region`, `get_component`, `list_failing_contrast_pairs`.
28
+ - **Agent rules emitter** — `--emit-agent-rules` writes `.cursor/rules/designlang.mdc`, `.claude/skills/designlang/SKILL.md`, `CLAUDE.md.fragment`, and `agents.md`. All four template from the resolved semantic tokens.
29
+ - **Multi-platform emitters** — `--platforms <csv>` (values `web`, `ios`, `android`, `flutter`, `wordpress`, `all`). Additive to default web output. Emits iOS SwiftUI, Android Compose + XML, Flutter Dart + ThemeData, and a full WordPress block-theme skeleton (`theme.json` v3, `style.css`, `functions.php`, `index.php`, `templates/index.html`).
30
+ - **Stack + Tailwind fingerprint** — framework detection, Tailwind utility-class frequency map, analytics stack inventory. Surfaced on `design.stack`.
31
+ - **CSS health audit** — specificity distribution, `!important` count, duplicate declarations, unused CSS via Playwright Coverage API, `@keyframes` catalog, vendor-prefix audit. Surfaced on `design.cssHealth` and added as an additive `cssHealth` dimension in the design score.
32
+ - **A11y remediation** — for every failing WCAG contrast pair, suggests the nearest palette color that passes AA (4.5:1 / 3:1) or AAA (7:1 / 4.5:1). Surfaced on `design.accessibility.remediation`.
33
+ - **Semantic regions** — classifies page sections into `nav`, `hero`, `features`, `pricing`, `testimonials`, `cta`, `footer`, `sidebar`, `content`. Surfaced on `design.regions`.
34
+ - **Reusable component detection** — DOM subtree structural hash + cosine-similarity style vector clustering with variant detection. Surfaced on `design.componentClusters` and rendered in the markdown output.
35
+ - **MCP companion file** — `*-mcp.json` written at extract time so later `designlang mcp` invocations can serve regions / components / health / remediation from disk, not just memory.
36
+
37
+ ### Dependencies
38
+
39
+ - Added `@modelcontextprotocol/sdk` (runtime).
40
+
41
+ ### Tests
42
+
43
+ - 241/241 passing (baseline 186 + 55 new tests).
package/README.md CHANGED
@@ -47,6 +47,8 @@ npx designlang https://stripe.com --full
47
47
 
48
48
  The markdown output has **19 sections**: Color Palette, Typography, Spacing, Border Radii, Box Shadows, CSS Custom Properties, Breakpoints, Transitions & Animations, Component Patterns (with full CSS snippets), Layout System, Responsive Design, Interaction States, Accessibility (WCAG 2.1), Gradients, Z-Index Map, SVG Icons, Font Files, Image Style Patterns, and Quick Start.
49
49
 
50
+ In v7 a companion `*-mcp.json` file is also written alongside the 8 outputs so that `designlang mcp` can serve regions, components, and health data from disk on later invocations. Opting into `--platforms <csv>` additively emits `ios/`, `android/`, `flutter/`, and/or `wordpress-theme/` directories in the output folder, and `--emit-agent-rules` adds a `.cursor/`, `.claude/`, `CLAUDE.md.fragment`, and `agents.md` set.
51
+
50
52
  ## Install
51
53
 
52
54
  ```bash
@@ -215,6 +217,101 @@ Compare light and dark mode side-by-side — see exactly which colors change and
215
217
  designlang https://vercel.com --dark
216
218
  ```
217
219
 
220
+ ### 17. MCP Server (NEW in v7)
221
+
222
+ One-command integration with any MCP-aware AI agent (Cursor, Claude Code, Windsurf, and more):
223
+
224
+ ```bash
225
+ designlang mcp --output-dir ./design-extract-output
226
+ ```
227
+
228
+ Launches a stdio JSON-RPC server that exposes the extracted design as MCP resources and tools.
229
+
230
+ **Resources:**
231
+
232
+ - `designlang://tokens/primitive` — primitive token layer
233
+ - `designlang://tokens/semantic` — semantic token layer (with DTCG alias references)
234
+ - `designlang://regions` — classified page regions (nav, hero, pricing, etc.)
235
+ - `designlang://components` — reusable component clusters with variants
236
+ - `designlang://health` — CSS health audit
237
+
238
+ **Tools:**
239
+
240
+ - `search_tokens` — query tokens by name, value, or type
241
+ - `find_nearest_color` — snap any color to the nearest palette token
242
+ - `get_region` — fetch a classified region by name
243
+ - `get_component` — fetch a component cluster by id
244
+ - `list_failing_contrast_pairs` — list every WCAG-failing fg/bg pair with remediation suggestions
245
+
246
+ ### 18. Multi-Platform Output (NEW in v7)
247
+
248
+ Emit iOS SwiftUI, Android Compose, Flutter, and WordPress block-theme files in a single run, in addition to the default web output:
249
+
250
+ ```bash
251
+ designlang https://stripe.com --platforms all
252
+ ```
253
+
254
+ Resulting tree:
255
+
256
+ ```
257
+ design-extract-output/
258
+ ├── stripe-com-*.{md,json,css,js,html} (default web output)
259
+ ├── ios/
260
+ │ └── DesignTokens.swift
261
+ ├── android/
262
+ │ ├── Theme.kt
263
+ │ ├── colors.xml
264
+ │ └── dimens.xml
265
+ ├── flutter/
266
+ │ └── design_tokens.dart (+ buildDesignlangTheme())
267
+ └── wordpress-theme/
268
+ ├── theme.json
269
+ ├── style.css
270
+ ├── functions.php
271
+ ├── index.php
272
+ └── templates/index.html
273
+ ```
274
+
275
+ Values for `--platforms` are any comma-separated subset of `web,ios,android,flutter,wordpress,all`. The flag is additive — the default web output is always emitted.
276
+
277
+ ### 19. Agent Rules Emitter (NEW in v7)
278
+
279
+ Write agent-facing rule files generated from the resolved semantic tokens:
280
+
281
+ ```bash
282
+ designlang https://stripe.com --emit-agent-rules
283
+ ```
284
+
285
+ Writes:
286
+
287
+ - `.cursor/rules/designlang.mdc` — Cursor rule
288
+ - `.claude/skills/designlang/SKILL.md` — Claude Code skill
289
+ - `CLAUDE.md.fragment` — snippet you can paste into your project's CLAUDE.md
290
+ - `agents.md` — generic, vendor-neutral agent guidance
291
+
292
+ Each file is templated from the semantic layer of the extracted token set, so the agent sees real token names and values — not placeholders.
293
+
294
+ ### 20. Stack + Tailwind Fingerprint (NEW in v7)
295
+
296
+ Automatic framework, utility-class, and analytics detection surfaced on `design.stack`:
297
+
298
+ - **Framework**: Next.js, Nuxt, Gatsby, Remix, Astro, Shopify, WordPress, Framer, Webflow, and more.
299
+ - **Tailwind**: when Tailwind is in use, records utility-class frequency so you see which utilities drive the design.
300
+ - **Analytics**: inventory of analytics scripts — GA4, Plausible, PostHog, Segment, Mixpanel, Amplitude, and friends.
301
+
302
+ ### 21. CSS Health Audit (NEW in v7)
303
+
304
+ A dedicated audit pass surfaced on `design.cssHealth`:
305
+
306
+ - Specificity graph (distribution, hotspots)
307
+ - `!important` count
308
+ - Duplicate declarations
309
+ - Unused CSS via the Playwright Coverage API
310
+ - `@keyframes` catalog
311
+ - Vendor-prefix audit
312
+
313
+ Also contributes a `cssHealth` dimension to the overall design score.
314
+
218
315
  ## All Features
219
316
 
220
317
  | Feature | Flag / Command | Description |
@@ -243,6 +340,15 @@ designlang https://vercel.com --dark
243
340
  | Multi-brand | `designlang brands <urls...>` | N-site comparison matrix |
244
341
  | Sync | `designlang sync <url>` | Update local tokens from live site |
245
342
  | History | `designlang history <url>` | Track design changes over time |
343
+ | MCP server | `designlang mcp` | Expose extraction as MCP resources + tools |
344
+ | Multi-platform | `--platforms <csv>` | Emit iOS / Android / Flutter / WordPress outputs |
345
+ | Agent rules | `--emit-agent-rules` | Cursor, Claude Code, generic agent rule files |
346
+ | Stack fingerprint | automatic | Framework + Tailwind + analytics detection |
347
+ | CSS health | automatic | Specificity, !important, unused CSS, keyframes |
348
+ | A11y remediation | automatic | Nearest palette color passing AA / AAA for every failing pair |
349
+ | Semantic regions | automatic | nav / hero / pricing / testimonials / cta / footer classification |
350
+ | Reusable components | automatic | DOM subtree + style-vector clustering with variants |
351
+ | DTCG tokens | default | W3C Design Tokens v1 with semantic + composite layers (`--tokens-legacy` for pre-v7) |
246
352
 
247
353
  ## Full CLI Reference
248
354
 
@@ -264,6 +370,9 @@ Options:
264
370
  --cookie <cookies...> Cookies for authenticated pages (name=value)
265
371
  --header <headers...> Custom headers (name:value)
266
372
  --framework <type> Only generate specific theme (react, shadcn)
373
+ --platforms <csv> Additional platforms: web,ios,android,flutter,wordpress,all (additive)
374
+ --emit-agent-rules Emit Cursor / Claude Code / CLAUDE.md / agents.md rule files
375
+ --tokens-legacy Emit pre-v7 flat design-tokens.json shape (backward compat)
267
376
  --no-history Skip saving to history
268
377
  --verbose Detailed progress output
269
378
 
@@ -276,6 +385,7 @@ Commands:
276
385
  brands <urls...> Multi-brand comparison matrix
277
386
  sync <url> Sync local tokens with live site
278
387
  history <url> View design change history
388
+ mcp Launch stdio MCP server (--output-dir <dir>)
279
389
  ```
280
390
 
281
391
  ## Example Output
@@ -351,4 +461,4 @@ See [CONTRIBUTING.md](CONTRIBUTING.md). PRs welcome!
351
461
 
352
462
  ## License
353
463
 
354
- [MIT](LICENSE) - Manavarya Singh
464
+ [MIT](LICENSE) - Manav Arya Singh
@@ -8,14 +8,19 @@ import ora from 'ora';
8
8
  import { extractDesignLanguage } from '../src/index.js';
9
9
  import { formatMarkdown } from '../src/formatters/markdown.js';
10
10
  import { formatTokens } from '../src/formatters/tokens.js';
11
+ import { formatDtcgTokens } from '../src/formatters/dtcg-tokens.js';
11
12
  import { formatTailwind } from '../src/formatters/tailwind.js';
12
13
  import { formatCssVars } from '../src/formatters/css-vars.js';
13
14
  import { formatPreview } from '../src/formatters/preview.js';
14
15
  import { formatFigma } from '../src/formatters/figma.js';
15
16
  import { formatReactTheme, formatShadcnTheme } from '../src/formatters/theme.js';
16
- import { formatWordPress } from '../src/formatters/wordpress.js';
17
+ import { formatWordPress, formatWordPressTheme } from '../src/formatters/wordpress.js';
18
+ import { formatIosSwiftUI } from '../src/formatters/ios-swiftui.js';
19
+ import { formatAndroidCompose } from '../src/formatters/android-compose.js';
20
+ import { formatFlutterDart } from '../src/formatters/flutter-dart.js';
17
21
  import { formatVueTheme } from '../src/formatters/vue-theme.js';
18
22
  import { formatSvelteTheme } from '../src/formatters/svelte-theme.js';
23
+ import { formatAgentRules } from '../src/formatters/agent-rules.js';
19
24
  import { loadConfig, mergeConfig } from '../src/config.js';
20
25
  import { diffDesigns, formatDiffMarkdown, formatDiffHtml } from '../src/diff.js';
21
26
  import { saveSnapshot, getHistory, formatHistoryMarkdown } from '../src/history.js';
@@ -62,6 +67,9 @@ program
62
67
  .option('--cookie <cookies...>', 'cookies for authenticated pages (name=value)')
63
68
  .option('--header <headers...>', 'custom headers (name:value)')
64
69
  .option('--ignore <selectors...>', 'CSS selectors to remove before extraction')
70
+ .option('--tokens-legacy', 'Emit pre-v7 flat token JSON (backward compat)')
71
+ .option('--platforms <csv>', 'Additional platforms: web,ios,android,flutter,wordpress,all (web is always emitted)', 'web')
72
+ .option('--emit-agent-rules', 'Emit Cursor/Claude Code/generic agent rules')
65
73
  .option('--json', 'output raw JSON to stdout (for CI/CD)')
66
74
  .option('--json-pretty', 'output formatted JSON to stdout')
67
75
  .option('--no-history', 'skip saving to history')
@@ -153,7 +161,7 @@ program
153
161
 
154
162
  const files = [
155
163
  { name: `${prefix}-design-language.md`, content: formatMarkdown(design), label: 'Markdown (AI-optimized)' },
156
- { name: `${prefix}-design-tokens.json`, content: formatTokens(design), label: 'Design Tokens (W3C)' },
164
+ { name: `${prefix}-design-tokens.json`, content: merged.tokensLegacy ? formatTokens(design) : JSON.stringify(formatDtcgTokens(design), null, 2), label: merged.tokensLegacy ? 'Design Tokens (legacy)' : 'Design Tokens (DTCG v1)' },
157
165
  { name: `${prefix}-tailwind.config.js`, content: formatTailwind(design), label: 'Tailwind Config' },
158
166
  { name: `${prefix}-variables.css`, content: formatCssVars(design), label: 'CSS Variables' },
159
167
  { name: `${prefix}-preview.html`, content: formatPreview(design), label: 'Visual Preview' },
@@ -178,10 +186,72 @@ program
178
186
  // WordPress theme (always generated)
179
187
  files.push({ name: `${prefix}-wordpress-theme.json`, content: formatWordPress(design), label: 'WordPress Theme' });
180
188
 
189
+ // MCP companion — the subset of `design` the MCP server serves when a
190
+ // user runs `designlang mcp --output-dir <dir>` later.
191
+ const mcpPayload = {
192
+ colors: { all: design.colors?.all || [] },
193
+ regions: design.regions || [],
194
+ componentClusters: design.componentClusters || [],
195
+ accessibility: { remediation: design.accessibility?.remediation || [] },
196
+ cssHealth: design.cssHealth || null,
197
+ };
198
+ files.push({ name: `${prefix}-mcp.json`, content: JSON.stringify(mcpPayload, null, 2), label: 'MCP companion' });
199
+
181
200
  for (const file of files) {
182
201
  writeFileSync(join(outDir, file.name), file.content, 'utf-8');
183
202
  }
184
203
 
204
+ // Multi-platform emission (v7.0). web is already emitted above.
205
+ const platforms = merged.platforms || ['web'];
206
+ const dtcgTokens = formatDtcgTokens(design);
207
+ const platformFiles = [];
208
+ if (platforms.includes('ios')) {
209
+ const dir = join(outDir, 'ios');
210
+ mkdirSync(dir, { recursive: true });
211
+ const path = join(dir, 'DesignTokens.swift');
212
+ writeFileSync(path, formatIosSwiftUI(dtcgTokens), 'utf-8');
213
+ platformFiles.push({ path, label: 'iOS SwiftUI' });
214
+ }
215
+ if (platforms.includes('android')) {
216
+ const dir = join(outDir, 'android');
217
+ mkdirSync(dir, { recursive: true });
218
+ const out = formatAndroidCompose(dtcgTokens);
219
+ for (const name of Object.keys(out)) {
220
+ const p = join(dir, name);
221
+ writeFileSync(p, out[name], 'utf-8');
222
+ platformFiles.push({ path: p, label: `Android (${name})` });
223
+ }
224
+ }
225
+ if (platforms.includes('flutter')) {
226
+ const dir = join(outDir, 'flutter');
227
+ mkdirSync(dir, { recursive: true });
228
+ const p = join(dir, 'design_tokens.dart');
229
+ writeFileSync(p, formatFlutterDart(dtcgTokens), 'utf-8');
230
+ platformFiles.push({ path: p, label: 'Flutter Dart' });
231
+ }
232
+ if (platforms.includes('wordpress')) {
233
+ const dir = join(outDir, 'wordpress-theme');
234
+ mkdirSync(dir, { recursive: true });
235
+ const out = formatWordPressTheme(dtcgTokens, design);
236
+ for (const name of Object.keys(out)) {
237
+ const p = join(dir, name);
238
+ mkdirSync(join(p, '..'), { recursive: true });
239
+ writeFileSync(p, out[name], 'utf-8');
240
+ platformFiles.push({ path: p, label: `WordPress (${name})` });
241
+ }
242
+ }
243
+
244
+ // Agent rules (opt-in, also enabled by --full)
245
+ if (merged.emitAgentRules || merged.full) {
246
+ const agentFiles = formatAgentRules({ design, tokens: dtcgTokens, url });
247
+ for (const rel of Object.keys(agentFiles)) {
248
+ const p = join(outDir, rel);
249
+ mkdirSync(join(p, '..'), { recursive: true });
250
+ writeFileSync(p, agentFiles[rel], 'utf-8');
251
+ platformFiles.push({ path: p, label: `Agent rules (${rel})` });
252
+ }
253
+ }
254
+
185
255
  // Save to history
186
256
  if (opts.history !== false) {
187
257
  const histInfo = saveSnapshot(design);
@@ -197,6 +267,9 @@ program
197
267
  for (const file of files) {
198
268
  console.log(join(outDir, file.name));
199
269
  }
270
+ for (const pf of platformFiles) {
271
+ console.log(pf.path);
272
+ }
200
273
  } else {
201
274
  console.log('');
202
275
  console.log(chalk.bold(' Output files:'));
@@ -205,6 +278,9 @@ program
205
278
  const sizeStr = size > 1024 ? `${(size / 1024).toFixed(1)}KB` : `${size}B`;
206
279
  console.log(` ${chalk.green('✓')} ${chalk.cyan(file.name)} ${chalk.gray(`(${sizeStr})`)} — ${file.label}`);
207
280
  }
281
+ for (const pf of platformFiles) {
282
+ console.log(` ${chalk.green('✓')} ${chalk.cyan(pf.path)} — ${pf.label}`);
283
+ }
208
284
  if (opts.screenshots && design.componentScreenshots && Object.keys(design.componentScreenshots).length > 0) {
209
285
  for (const [, info] of Object.entries(design.componentScreenshots)) {
210
286
  console.log(` ${chalk.green('✓')} ${chalk.cyan(info.path)} — ${info.label} screenshot`);
@@ -685,4 +761,14 @@ program
685
761
  }
686
762
  });
687
763
 
764
+ // ── MCP server command ─────────────────────────────────────
765
+ program
766
+ .command('mcp')
767
+ .description('Launch designlang MCP server over stdio (exposes latest extraction as resources + tools)')
768
+ .option('--output-dir <path>', 'Source extraction directory', './design-extract-output')
769
+ .action(async (opts) => {
770
+ const { run } = await import('../src/mcp/server.js');
771
+ await run(opts);
772
+ });
773
+
688
774
  program.parse();