@noemuch/bridge-ds 2.2.0 → 2.5.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 (31) hide show
  1. package/.claude-plugin/plugin.json +31 -0
  2. package/.cursor-plugin/plugin.json +26 -0
  3. package/.mcp.json +12 -0
  4. package/CHANGELOG.md +66 -0
  5. package/CLAUDE.md +84 -0
  6. package/README.md +7 -3
  7. package/lib/cli.js +107 -134
  8. package/lib/mcp-setup.js +32 -28
  9. package/lib/scaffold.js +6 -3
  10. package/package.json +10 -3
  11. package/skills/design-workflow/SKILL.md +70 -17
  12. package/skills/design-workflow/references/actions/design.md +108 -11
  13. package/skills/design-workflow/references/actions/done.md +21 -3
  14. package/skills/design-workflow/references/actions/learn.md +147 -0
  15. package/skills/design-workflow/references/actions/quick.md +78 -0
  16. package/skills/design-workflow/references/actions/review.md +14 -3
  17. package/skills/design-workflow/references/actions/spec.md +58 -0
  18. package/skills/design-workflow/references/actions/sync.md +176 -0
  19. package/skills/design-workflow/references/figma-api-rules.md +116 -0
  20. package/skills/design-workflow/references/knowledge-base/README.md +18 -1
  21. package/skills/design-workflow/references/knowledge-base/schemas/assets.md +6 -0
  22. package/skills/design-workflow/references/knowledge-base/schemas/components.md +6 -0
  23. package/skills/design-workflow/references/knowledge-base/schemas/learnings.md +250 -0
  24. package/skills/design-workflow/references/knowledge-base/schemas/text-styles.md +6 -0
  25. package/skills/design-workflow/references/knowledge-base/schemas/validation.md +6 -0
  26. package/skills/design-workflow/references/knowledge-base/schemas/variables.md +6 -0
  27. package/skills/design-workflow/references/onboarding.md +51 -9
  28. package/skills/design-workflow/references/quality-gates.md +51 -2
  29. package/skills/design-workflow/references/templates/screen-template.md +37 -3
  30. package/skills/design-workflow/references/templates/spec-template.md +12 -0
  31. package/skills/design-workflow/references/transport-adapter.md +210 -0
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "bridge-ds",
3
+ "displayName": "Bridge Design System",
4
+ "version": "2.5.0",
5
+ "description": "AI-powered design generation in Figma — spec-first, DS-native, with a learning loop that improves over time. Extracts your real design system, writes validated specs, and generates production-ready Figma designs using actual DS components and tokens.",
6
+ "author": {
7
+ "name": "noemuch",
8
+ "url": "https://github.com/noemuch"
9
+ },
10
+ "homepage": "https://github.com/noemuch/bridge",
11
+ "repository": "https://github.com/noemuch/bridge",
12
+ "license": "MIT",
13
+ "keywords": [
14
+ "figma",
15
+ "design-system",
16
+ "design-tokens",
17
+ "mcp",
18
+ "ai-design",
19
+ "figma-plugin-api",
20
+ "spec-first",
21
+ "design-generation"
22
+ ],
23
+ "skills": {
24
+ "design-workflow": "./skills/design-workflow/SKILL.md"
25
+ },
26
+ "commands": {
27
+ "design-workflow": "./commands/design-workflow.md"
28
+ },
29
+ "instructions": "./CLAUDE.md",
30
+ "mcpServers": "./.mcp.json"
31
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "bridge-ds",
3
+ "displayName": "Bridge Design System",
4
+ "version": "2.5.0",
5
+ "description": "AI-powered design generation in Figma — spec-first, DS-native, with a learning loop.",
6
+ "author": "noemuch",
7
+ "homepage": "https://github.com/noemuch/bridge",
8
+ "repository": "https://github.com/noemuch/bridge",
9
+ "license": "MIT",
10
+ "keywords": ["figma", "design-system", "mcp", "ai-design"],
11
+ "skills": {
12
+ "design-workflow": "./skills/design-workflow/SKILL.md"
13
+ },
14
+ "commands": {
15
+ "design-workflow": "./commands/design-workflow.md"
16
+ },
17
+ "mcpServers": {
18
+ "figma-console": {
19
+ "command": "npx",
20
+ "args": ["-y", "figma-console-mcp@latest"],
21
+ "env": {
22
+ "FIGMA_ACCESS_TOKEN": ""
23
+ }
24
+ }
25
+ }
26
+ }
package/.mcp.json ADDED
@@ -0,0 +1,12 @@
1
+ {
2
+ "mcpServers": {
3
+ "figma-console": {
4
+ "command": "npx",
5
+ "args": ["-y", "figma-console-mcp@latest"],
6
+ "env": {
7
+ "FIGMA_ACCESS_TOKEN": ""
8
+ },
9
+ "description": "Figma Console MCP — gives Claude native access to Figma Desktop via Plugin API. Required for design generation."
10
+ }
11
+ }
12
+ }
package/CHANGELOG.md ADDED
@@ -0,0 +1,66 @@
1
+ # Changelog
2
+
3
+ All notable changes to Bridge DS are documented here.
4
+
5
+ ## [2.4.1] — 2026-03-20
6
+
7
+ ### Fixed
8
+ - **review.md**: Sections F (Component API Quality) and G (Learning Opportunity) were in wrong order
9
+ - **CLI help**: Added missing `drop`, `learn`, `sync`, `status` slash commands
10
+ - **README.md**: Added missing `learn` and `sync` commands to table; updated workflow diagram with learning loop
11
+ - **design.md**: Fixed incorrect absolute path to knowledge base (now relative `references/knowledge-base/`)
12
+ - **done.md**: Added `Learnings: {n} persisted` to output template
13
+ - **scaffold.js**: Added `learnings.json` to `.gitignore` entries; `update()` now preserves `learnings.json`
14
+
15
+ ### Added
16
+ - **Templates**: "Known Preferences" section in both `screen-template.md` and `spec-template.md`
17
+ - **CHANGELOG.md**: This file
18
+
19
+ ## [2.4.0] — 2026-03-19
20
+
21
+ ### Added
22
+ - Learning loop: `learn` action diffs Figma corrections against generation snapshot, extracts reusable preferences
23
+ - Incremental DS sync: `sync` action updates registries without full re-setup
24
+ - `status` action shows current workflow state and suggests next step
25
+ - `drop` action abandons work with preserved learnings
26
+ - Snapshot capture after design generation for learn diffing
27
+
28
+ ## [2.3.0] — 2026-03-18
29
+
30
+ ### Added
31
+ - Screen generation with reference inspection and clone-first strategy
32
+ - Auto-enrichment of specs from knowledge base
33
+ - Visual reference pattern matching (blocking gate)
34
+
35
+ ## [2.2.0] — 2026-03-17
36
+
37
+ ### Added
38
+ - `update` command to preserve knowledge base on upgrades
39
+ - Interactive MCP setup during `init`
40
+
41
+ ## [2.1.0] — 2026-03-16
42
+
43
+ ### Added
44
+ - Registry schemas and validation for setup
45
+ - Validation gate before design generation
46
+
47
+ ## [2.0.1] — 2026-03-15
48
+
49
+ ### Fixed
50
+ - Strengthened pre-script audit
51
+ - Added Rule 20 (setTextStyleIdAsync)
52
+
53
+ ## [2.0.0] — 2026-03-14
54
+
55
+ ### Changed
56
+ - Complete rewrite: MCP-powered design workflow via figma-console-mcp
57
+ - Spec-first architecture with atomic generation
58
+ - Knowledge base system (registries, guides, patterns)
59
+ - DS-native generation (zero hardcoded values)
60
+
61
+ ## [1.0.0] — 2026-03-12
62
+
63
+ ### Added
64
+ - Initial release: Bridge for Claude Code
65
+ - CLI with `init` command
66
+ - Design workflow skill scaffold
package/CLAUDE.md ADDED
@@ -0,0 +1,84 @@
1
+ # Bridge DS — Claude Code Instructions
2
+
3
+ Bridge DS is an AI-powered design workflow that generates Figma designs using your real design system. It supports two MCP transports: [figma-console-mcp](https://github.com/southleft/figma-console-mcp) (preferred) and the official Figma MCP server (fallback).
4
+
5
+ ## Architecture
6
+
7
+ ```
8
+ Claude Code ──MCP──> figma-console-mcp ──WebSocket──> Figma Desktop (local, preferred)
9
+ Claude Code ──MCP──> Figma MCP Server ──Cloud──> Figma Cloud (official, fallback)
10
+ ```
11
+
12
+ All Figma operations use MCP tools — no custom server, no HTTP calls, no curl. See `skills/design-workflow/references/transport-adapter.md` for transport detection and tool mapping.
13
+
14
+ ## Key MCP Tools
15
+
16
+ Tools vary by transport. See `references/transport-adapter.md` for the full mapping.
17
+
18
+ | Operation | Console transport | Official transport |
19
+ |-----------|------------------|--------------------|
20
+ | Execute Plugin API code | `figma_execute` | `use_figma` |
21
+ | Take screenshot | `figma_take_screenshot` | `get_screenshot` |
22
+ | Full DS extraction | `figma_get_design_system_kit` | Composite (see transport-adapter.md) |
23
+ | Get variables | `figma_get_variables` | `get_variable_defs` |
24
+ | Get styles | `figma_get_styles` | `search_design_system` |
25
+ | Search components | `figma_search_components` | `search_design_system` |
26
+ | Connection check | `figma_get_status` | `whoami` |
27
+
28
+ ## Script Structure
29
+
30
+ Script format depends on the active transport. See `references/transport-adapter.md` Section C for full rules.
31
+
32
+ **Console transport (figma_execute) — IIFE wrapper mandatory:**
33
+
34
+ ```javascript
35
+ return (async function() {
36
+ await figma.loadFontAsync({ family: "Inter", style: "Regular" });
37
+ // ... Plugin API code ...
38
+ return { success: true };
39
+ })();
40
+ ```
41
+
42
+ **Official transport (use_figma) — top-level await, no IIFE:**
43
+
44
+ ```javascript
45
+ await figma.loadFontAsync({ family: "Inter", style: "Regular" });
46
+ // ... Plugin API code ...
47
+ return { success: true };
48
+ ```
49
+
50
+ Called as: `use_figma({ fileKey: "...", description: "...", code: "..." })`
51
+
52
+ ## Critical Figma API Rules
53
+
54
+ Full rules: `skills/design-workflow/references/figma-api-rules.md`
55
+
56
+ **Top 5 (most common bugs):**
57
+
58
+ 1. **FILL after appendChild** — Set `layoutSizingHorizontal = "FILL"` AFTER `parent.appendChild(child)`, never before
59
+ 2. **resize() overrides sizing** — Call `resize()` FIRST, then set `primaryAxisSizingMode`
60
+ 3. **Colors via setBoundVariableForPaint** — Not `setBoundVariable` (different API for fills/strokes)
61
+ 4. **textAutoResize after width** — Set characters → append → FILL → then `textAutoResize = "HEIGHT"`
62
+ 5. **DS component reuse** — NEVER recreate existing components as raw frames. Always import via `importComponentByKeyAsync`
63
+
64
+ ## Helpers
65
+
66
+ Helpers (`mf`, `appendFill`, `bindPadding`, `bindRadius`) and the standard script boilerplate are defined in `skills/design-workflow/references/figma-api-rules.md` (Standard Script Boilerplate section). Always copy them from there.
67
+
68
+ ## Design Workflow
69
+
70
+ The `/design-workflow` skill handles everything:
71
+
72
+ ```
73
+ /design-workflow setup → Extract DS + build knowledge base
74
+ /design-workflow spec → Write component or screen specification
75
+ /design-workflow design → Generate in Figma (atomic, verified)
76
+ /design-workflow review → Validate against spec + tokens
77
+ /design-workflow done → Archive and ship
78
+ /design-workflow drop → Abandon with preserved learnings
79
+ /design-workflow learn → Diff design vs corrections, extract learnings
80
+ /design-workflow sync → Incremental DS sync (no full re-setup)
81
+ /design-workflow status → Show current state, suggest next
82
+ ```
83
+
84
+ Read `skills/design-workflow/SKILL.md` for the full workflow definition.
package/README.md CHANGED
@@ -97,9 +97,11 @@ Claude consults the knowledge base, identifies the right pattern, components, an
97
97
  ## The Workflow
98
98
 
99
99
  ```
100
- setup (once) → spec → design → review done
101
- ↑ |
102
- └── iterate ─────────┘
100
+ setup (once) → spec → design → review ──→ done
101
+ ↑ | |
102
+ └── iterate ─────────┘ learn ←┘
103
+ (diff corrections,
104
+ extract preferences)
103
105
  ```
104
106
 
105
107
  ### Spec-first
@@ -140,6 +142,8 @@ knowledge-base/
140
142
  | `/design-workflow review` | Validate design against spec + tokens |
141
143
  | `/design-workflow done` | Archive spec and ship |
142
144
  | `/design-workflow drop` | Abandon with preserved learnings |
145
+ | `/design-workflow learn` | Diff corrections, extract learnings |
146
+ | `/design-workflow sync` | Incremental DS sync (no full re-setup) |
143
147
  | `/design-workflow status` | Show current state, suggest next action |
144
148
 
145
149
  ## License
package/lib/cli.js CHANGED
@@ -1,8 +1,10 @@
1
1
  const path = require('path');
2
+ const readline = require('readline');
3
+ const { execSync } = require('child_process');
2
4
  const { scaffold, update } = require('./scaffold');
3
- const { checkMcp, setupMcp } = require('./mcp-setup');
5
+ const { checkMcp } = require('./mcp-setup');
4
6
 
5
- // ── Branding ──────────────────────────────────────────────
7
+ // ── Formatting ───────────────────────────────────────────
6
8
  const C = {
7
9
  reset: '\x1b[0m',
8
10
  bold: '\x1b[1m',
@@ -12,162 +14,145 @@ const C = {
12
14
  red: '\x1b[38;2;244;67;54m',
13
15
  yellow: '\x1b[38;2;255;193;7m',
14
16
  gray: '\x1b[38;2;158;158;158m',
15
- white: '\x1b[38;2;255;255;255m',
16
17
  };
17
18
 
18
19
  function print(msg = '') { process.stdout.write(msg + '\n'); }
19
- function header(msg) { print(`\n${C.orange}${C.bold}🧱 ${msg}${C.reset}\n`); }
20
- function success(msg) { print(`${C.green} ${msg}${C.reset}`); }
21
- function info(msg) { print(`${C.white} ${msg}${C.reset}`); }
22
- function warn(msg) { print(`${C.yellow}${msg}${C.reset}`); }
23
- function error(msg) { print(`${C.red} ✗ ${msg}${C.reset}`); }
24
- function muted(msg) { print(`${C.gray} ${msg}${C.reset}`); }
25
- function step(n, total, msg) { print(`${C.orange} [${n}/${total}]${C.reset} ${C.bold}${msg}${C.reset}`); }
26
-
27
- // ── Spinner ───────────────────────────────────────────────
28
- const FRAMES = ['⠋','⠙','⠹','⠸','⠼','⠴','⠦','⠧','⠇','⠏'];
29
- class Spinner {
30
- constructor(msg) { this.msg = msg; this.i = 0; this.id = null; }
31
- start() {
32
- this.id = setInterval(() => {
33
- process.stdout.write(`\r${C.orange} ${FRAMES[this.i++ % FRAMES.length]}${C.reset} ${this.msg}`);
34
- }, 80);
35
- return this;
36
- }
37
- stop(result) {
38
- clearInterval(this.id);
39
- process.stdout.write('\r' + ' '.repeat(this.msg.length + 10) + '\r');
40
- if (result) success(result);
41
- }
20
+ function ok(msg) { print(` ${C.green}✓${C.reset} ${msg}`); }
21
+ function fail(msg) { print(` ${C.red}✗${C.reset} ${msg}`); }
22
+ function warn(msg) { print(` ${C.yellow}!${C.reset} ${msg}`); }
23
+ function dim(msg) { print(` ${C.dim}${msg}${C.reset}`); }
24
+
25
+ function brand() {
26
+ const pkg = require('../package.json');
27
+ print(`\n ${C.orange}${C.bold}Bridge DS${C.reset} ${C.dim}v${pkg.version}${C.reset}\n`);
42
28
  }
43
29
 
44
- // ── ASCII Art ─────────────────────────────────────────────
45
- function banner() {
46
- print('');
47
- print(`${C.orange}${C.bold} ┌──────────────────────────────────────┐${C.reset}`);
48
- print(`${C.orange}${C.bold} │ 🧱 Bridge DS │${C.reset}`);
49
- print(`${C.orange}${C.bold} │ AI-powered design in Figma │${C.reset}`);
50
- print(`${C.orange}${C.bold} │ 100% design system compliant │${C.reset}`);
51
- print(`${C.orange}${C.bold} └──────────────────────────────────────┘${C.reset}`);
52
- print('');
30
+ function ask(question) {
31
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
32
+ return new Promise((resolve) => {
33
+ rl.question(` ${question} `, (answer) => {
34
+ rl.close();
35
+ resolve(answer.trim());
36
+ });
37
+ });
53
38
  }
54
39
 
55
- // ── Commands ──────────────────────────────────────────────
40
+ // ── Commands ─────────────────────────────────────────────
56
41
 
57
42
  async function cmdInit() {
58
- banner();
59
- header('Initializing Bridge DS');
43
+ brand();
60
44
 
61
45
  const cwd = process.cwd();
62
- const totalSteps = 4;
63
46
 
64
- // Step 1: Check prerequisites
65
- step(1, totalSteps, 'Checking prerequisites');
47
+ // 1. Prerequisites
66
48
  const nodeVersion = process.version.replace('v', '').split('.').map(Number);
67
49
  if (nodeVersion[0] < 18) {
68
- error(`Node.js 18+ required (found ${process.version})`);
50
+ fail(`Node.js 18+ required (found ${process.version})`);
69
51
  process.exit(1);
70
52
  }
71
- success(`Node.js ${process.version}`);
53
+ ok(`Node.js ${process.version}`);
72
54
 
73
- // Step 2: Configure figma-console-mcp
74
- step(2, totalSteps, 'Checking figma-console-mcp');
75
- const mcpConfigured = checkMcp();
76
- if (mcpConfigured) {
77
- success('figma-console-mcp is configured');
78
- } else {
79
- warn('figma-console-mcp not found in Claude Code settings');
80
- info('Run this command to add it:');
55
+ // 2. Figma MCP transport
56
+ const mcp = checkMcp();
57
+ let mcpReady = mcp.console || mcp.official;
58
+
59
+ if (mcp.console) {
60
+ ok('figma-console-mcp detected (preferred transport)');
61
+ }
62
+ if (mcp.official) {
63
+ ok('Official Figma MCP detected' + (mcp.console ? ' (fallback)' : ''));
64
+ if (!mcp.console) {
65
+ dim('figma-console-mcp is recommended for full capabilities but official MCP works too');
66
+ }
67
+ }
68
+
69
+ if (!mcpReady) {
70
+ warn('No Figma MCP transport configured');
71
+ print('');
72
+ dim('Bridge supports two transports:');
73
+ dim(' A) figma-console-mcp (recommended, full Plugin API access)');
74
+ dim(' B) Official Figma MCP (cloud-based, cross-library search)');
81
75
  print('');
82
- print(`${C.dim} claude mcp add figma-console -s user \\${C.reset}`);
83
- print(`${C.dim} -e FIGMA_ACCESS_TOKEN=figd_YOUR_TOKEN \\${C.reset}`);
84
- print(`${C.dim} -- npx -y figma-console-mcp@latest${C.reset}`);
76
+ dim('For option A, you need a Personal Access Token from Figma:');
77
+ dim('https://www.figma.com/developers/api#access-tokens');
85
78
  print('');
86
- info('Then re-run: bridge-ds init');
87
- info('Continuing with file setup...');
79
+
80
+ const token = await ask(`${C.bold}Figma token${C.reset} (figd_...) for figma-console-mcp, or Enter to skip:`);
81
+
82
+ if (token && token.startsWith('figd_')) {
83
+ try {
84
+ execSync(
85
+ `claude mcp add figma-console -s user -e FIGMA_ACCESS_TOKEN=${token} -- npx -y figma-console-mcp@latest`,
86
+ { stdio: 'pipe' }
87
+ );
88
+ ok('figma-console-mcp configured');
89
+ mcpReady = true;
90
+ } catch (e) {
91
+ fail('Could not configure MCP automatically');
92
+ dim('Run manually:');
93
+ dim(`claude mcp add figma-console -s user -e FIGMA_ACCESS_TOKEN=${token} -- npx -y figma-console-mcp@latest`);
94
+ }
95
+ } else if (token) {
96
+ warn('Token should start with figd_ — skipping MCP setup');
97
+ dim('You can configure it later:');
98
+ dim('claude mcp add figma-console -s user -e FIGMA_ACCESS_TOKEN=<token> -- npx -y figma-console-mcp@latest');
99
+ } else {
100
+ dim('Skipped. You can configure either transport later.');
101
+ dim('Console: claude mcp add figma-console -s user -e FIGMA_ACCESS_TOKEN=<token> -- npx -y figma-console-mcp@latest');
102
+ dim('Official: Configure via Claude settings or Figma MCP integration.');
103
+ }
88
104
  }
89
105
 
90
- // Step 3: Scaffold project files
91
- step(3, totalSteps, 'Scaffolding project files');
92
- const spinner = new Spinner('Copying skills, commands, templates...').start();
93
- const result = scaffold(cwd);
94
- spinner.stop('Project files created');
106
+ print('');
95
107
 
96
- for (const f of result.created) {
97
- muted(f);
98
- }
108
+ // 3. Scaffold
109
+ const result = scaffold(cwd);
110
+ ok(`${result.created.length} files scaffolded`);
99
111
 
100
- // Step 4: Summary
101
- step(4, totalSteps, 'Done!');
112
+ // 4. Summary
102
113
  print('');
103
- print(`${C.orange}${C.bold} ┌──────────────────────────────────────┐${C.reset}`);
104
- print(`${C.orange}${C.bold} │ Setup complete! │${C.reset}`);
105
- print(`${C.orange}${C.bold} │ │${C.reset}`);
106
- print(`${C.orange}${C.bold} │ Next steps: │${C.reset}`);
107
- print(`${C.orange}${C.bold} │ 1. Open Claude Code in this project │${C.reset}`);
108
- print(`${C.orange}${C.bold} │ 2. Run: /design-workflow setup │${C.reset}`);
109
- print(`${C.orange}${C.bold} │ → Extracts & documents your DS │${C.reset}`);
110
- print(`${C.orange}${C.bold} │ 3. Run: /design-workflow spec ... │${C.reset}`);
111
- print(`${C.orange}${C.bold} │ → Start designing! │${C.reset}`);
112
- print(`${C.orange}${C.bold} └──────────────────────────────────────┘${C.reset}`);
114
+ if (mcpReady) {
115
+ ok(`${C.bold}Ready!${C.reset} Open Claude Code and run: ${C.orange}/design-workflow setup${C.reset}`);
116
+ } else {
117
+ warn(`${C.bold}Almost ready.${C.reset} Configure figma-console-mcp, then run: ${C.orange}/design-workflow setup${C.reset}`);
118
+ }
113
119
  print('');
114
120
  }
115
121
 
116
122
  async function cmdUpdate() {
117
- banner();
118
- header('Updating Bridge DS skill files');
123
+ brand();
119
124
 
120
125
  const cwd = process.cwd();
121
-
122
- step(1, 2, 'Updating skill files');
123
- const spinner = new Spinner('Updating SKILL.md, actions, rules, schemas, templates...').start();
124
126
  const result = update(cwd);
125
127
 
126
128
  if (result.error) {
127
- spinner.stop();
128
- error(result.error);
129
+ fail(result.error);
129
130
  process.exit(1);
130
131
  }
131
132
 
132
- spinner.stop(`${result.updated.length} files updated`);
133
-
134
- for (const f of result.updated) {
135
- muted(f);
136
- }
137
-
138
- step(2, 2, 'Done!');
139
- print('');
140
- success('Skill files updated. Your knowledge base (registries, guides) was preserved.');
141
- info('No need to re-run /design-workflow setup.');
133
+ ok(`${result.updated.length} files updated`);
134
+ dim('Knowledge base preserved (registries, guides, screenshots)');
142
135
  print('');
143
136
  }
144
137
 
145
138
  function cmdHelp() {
146
- banner();
147
- print(`${C.bold} Commands:${C.reset}`);
148
- print('');
149
- print(` ${C.orange}init${C.reset} Initialize Bridge DS in current project`);
150
- print(` Scaffolds skills, commands, and specs directories`);
151
- print('');
152
- print(` ${C.orange}update${C.reset} Update skill files to latest version`);
153
- print(` Preserves your knowledge base (registries, guides)`);
154
- print('');
155
- print(` ${C.orange}help${C.reset} Show this help message`);
139
+ brand();
140
+ print(` ${C.bold}Commands${C.reset}`);
141
+ print(` ${C.orange}init${C.reset} Set up Bridge DS in the current project`);
142
+ print(` ${C.orange}update${C.reset} Update skill files (preserves knowledge base)`);
143
+ print(` ${C.orange}help${C.reset} Show this help`);
156
144
  print(` ${C.orange}version${C.reset} Show version`);
157
145
  print('');
158
- print(`${C.bold} Usage:${C.reset}`);
159
- print('');
160
- print(` ${C.dim}npx @noemuch/bridge-ds init${C.reset} # Initialize in current project`);
161
- print(` ${C.dim}npx @noemuch/bridge-ds update${C.reset} # Update skill files only`);
162
- print(` ${C.dim}bridge-ds help${C.reset} # Show help`);
163
- print('');
164
- print(`${C.bold} After init:${C.reset}`);
165
- print('');
166
- print(` ${C.dim}/design-workflow setup${C.reset} # Extract & document your DS (in Claude Code)`);
167
- print(` ${C.dim}/design-workflow spec${C.reset} # Spec a component or screen`);
168
- print(` ${C.dim}/design-workflow design${C.reset} # Generate in Figma`);
169
- print(` ${C.dim}/design-workflow review${C.reset} # Validate against spec`);
170
- print(` ${C.dim}/design-workflow done${C.reset} # Archive & ship`);
146
+ print(` ${C.bold}After init${C.reset}`);
147
+ print(` ${C.dim}/design-workflow setup${C.reset} Extract your design system`);
148
+ print(` ${C.dim}/design-workflow spec${C.reset} Spec a component or screen`);
149
+ print(` ${C.dim}/design-workflow design${C.reset} Generate in Figma`);
150
+ print(` ${C.dim}/design-workflow review${C.reset} Validate against spec`);
151
+ print(` ${C.dim}/design-workflow done${C.reset} Archive & ship`);
152
+ print(` ${C.dim}/design-workflow drop${C.reset} Abandon with preserved learnings`);
153
+ print(` ${C.dim}/design-workflow learn${C.reset} Diff corrections, extract learnings`);
154
+ print(` ${C.dim}/design-workflow sync${C.reset} Incremental DS sync`);
155
+ print(` ${C.dim}/design-workflow status${C.reset} Show current state, suggest next`);
171
156
  print('');
172
157
  }
173
158
 
@@ -176,30 +161,18 @@ function cmdVersion() {
176
161
  print(`bridge-ds v${pkg.version}`);
177
162
  }
178
163
 
179
- // ── Router ────────────────────────────────────────────────
164
+ // ── Router ───────────────────────────────────────────────
180
165
 
181
166
  async function run(args) {
182
167
  const cmd = args[0] || 'help';
183
168
 
184
169
  switch (cmd) {
185
- case 'init':
186
- await cmdInit();
187
- break;
188
- case 'update':
189
- await cmdUpdate();
190
- break;
191
- case 'help':
192
- case '--help':
193
- case '-h':
194
- cmdHelp();
195
- break;
196
- case 'version':
197
- case '--version':
198
- case '-v':
199
- cmdVersion();
200
- break;
170
+ case 'init': return cmdInit();
171
+ case 'update': return cmdUpdate();
172
+ case 'help': case '--help': case '-h': return cmdHelp();
173
+ case 'version': case '--version': case '-v': return cmdVersion();
201
174
  default:
202
- error(`Unknown command: ${cmd}`);
175
+ fail(`Unknown command: ${cmd}`);
203
176
  cmdHelp();
204
177
  process.exit(1);
205
178
  }
package/lib/mcp-setup.js CHANGED
@@ -3,45 +3,49 @@ const path = require('path');
3
3
  const os = require('os');
4
4
 
5
5
  /**
6
- * Check if figma-console-mcp is configured in Claude Code settings.
7
- * Checks multiple possible locations.
6
+ * Check which Figma MCP transports are configured in Claude Code settings.
7
+ * Returns { console: boolean, official: boolean }
8
+ * - console: figma-console-mcp is configured
9
+ * - official: Official Figma MCP (mcp.figma.com or "figma"/"claude.ai Figma")
8
10
  */
9
11
  function checkMcp() {
12
+ const result = { console: false, official: false };
13
+
10
14
  const locations = [
11
- // User-level Claude Code settings
12
15
  path.join(os.homedir(), '.claude.json'),
13
- // Project-level settings
16
+ path.join(os.homedir(), '.claude', 'settings.json'),
14
17
  path.join(process.cwd(), '.claude', 'settings.local.json'),
15
18
  ];
16
19
 
17
20
  for (const loc of locations) {
18
- if (fs.existsSync(loc)) {
19
- try {
20
- const content = JSON.parse(fs.readFileSync(loc, 'utf8'));
21
- const servers = content.mcpServers || {};
22
- // Check for any figma-console-mcp configuration
23
- for (const [name, config] of Object.entries(servers)) {
24
- if (name.includes('figma') && config.command) {
25
- const args = (config.args || []).join(' ');
26
- if (args.includes('figma-console-mcp')) {
27
- return true;
28
- }
29
- }
21
+ if (!fs.existsSync(loc)) continue;
22
+ try {
23
+ const content = JSON.parse(fs.readFileSync(loc, 'utf8'));
24
+ const servers = content.mcpServers || {};
25
+ for (const [name, config] of Object.entries(servers)) {
26
+ const args = (config.args || []).join(' ');
27
+ const url = config.url || '';
28
+
29
+ // figma-console-mcp detection
30
+ if (name.includes('figma') && config.command && args.includes('figma-console-mcp')) {
31
+ result.console = true;
32
+ continue;
33
+ }
34
+
35
+ // Official Figma MCP detection (by URL or server name)
36
+ if (url.includes('mcp.figma.com')) {
37
+ result.official = true;
38
+ continue;
39
+ }
40
+ if ((name === 'figma' || name === 'claude.ai Figma') && !args.includes('figma-console-mcp')) {
41
+ result.official = true;
42
+ continue;
30
43
  }
31
- } catch (_) {
32
- // Ignore parse errors
33
44
  }
34
- }
45
+ } catch (_) {}
35
46
  }
36
47
 
37
- return false;
38
- }
39
-
40
- /**
41
- * Return the MCP add command for the user to run.
42
- */
43
- function getMcpAddCommand() {
44
- return 'claude mcp add figma-console -s user -e FIGMA_ACCESS_TOKEN=figd_YOUR_TOKEN -- npx -y figma-console-mcp@latest';
48
+ return result;
45
49
  }
46
50
 
47
- module.exports = { checkMcp, getMcpAddCommand };
51
+ module.exports = { checkMcp };