@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.
- package/.claude-plugin/plugin.json +31 -0
- package/.cursor-plugin/plugin.json +26 -0
- package/.mcp.json +12 -0
- package/CHANGELOG.md +66 -0
- package/CLAUDE.md +84 -0
- package/README.md +7 -3
- package/lib/cli.js +107 -134
- package/lib/mcp-setup.js +32 -28
- package/lib/scaffold.js +6 -3
- package/package.json +10 -3
- package/skills/design-workflow/SKILL.md +70 -17
- package/skills/design-workflow/references/actions/design.md +108 -11
- package/skills/design-workflow/references/actions/done.md +21 -3
- package/skills/design-workflow/references/actions/learn.md +147 -0
- package/skills/design-workflow/references/actions/quick.md +78 -0
- package/skills/design-workflow/references/actions/review.md +14 -3
- package/skills/design-workflow/references/actions/spec.md +58 -0
- package/skills/design-workflow/references/actions/sync.md +176 -0
- package/skills/design-workflow/references/figma-api-rules.md +116 -0
- package/skills/design-workflow/references/knowledge-base/README.md +18 -1
- package/skills/design-workflow/references/knowledge-base/schemas/assets.md +6 -0
- package/skills/design-workflow/references/knowledge-base/schemas/components.md +6 -0
- package/skills/design-workflow/references/knowledge-base/schemas/learnings.md +250 -0
- package/skills/design-workflow/references/knowledge-base/schemas/text-styles.md +6 -0
- package/skills/design-workflow/references/knowledge-base/schemas/validation.md +6 -0
- package/skills/design-workflow/references/knowledge-base/schemas/variables.md +6 -0
- package/skills/design-workflow/references/onboarding.md +51 -9
- package/skills/design-workflow/references/quality-gates.md +51 -2
- package/skills/design-workflow/references/templates/screen-template.md +37 -3
- package/skills/design-workflow/references/templates/spec-template.md +12 -0
- 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
|
|
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
|
|
5
|
+
const { checkMcp } = require('./mcp-setup');
|
|
4
6
|
|
|
5
|
-
// ──
|
|
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
|
|
20
|
-
function
|
|
21
|
-
function
|
|
22
|
-
function
|
|
23
|
-
|
|
24
|
-
function
|
|
25
|
-
|
|
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
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
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
|
-
|
|
59
|
-
header('Initializing Bridge DS');
|
|
43
|
+
brand();
|
|
60
44
|
|
|
61
45
|
const cwd = process.cwd();
|
|
62
|
-
const totalSteps = 4;
|
|
63
46
|
|
|
64
|
-
//
|
|
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
|
-
|
|
50
|
+
fail(`Node.js 18+ required (found ${process.version})`);
|
|
69
51
|
process.exit(1);
|
|
70
52
|
}
|
|
71
|
-
|
|
53
|
+
ok(`Node.js ${process.version}`);
|
|
72
54
|
|
|
73
|
-
//
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
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
|
-
|
|
83
|
-
|
|
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
|
-
|
|
87
|
-
|
|
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
|
-
|
|
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
|
-
|
|
97
|
-
|
|
98
|
-
}
|
|
108
|
+
// 3. Scaffold
|
|
109
|
+
const result = scaffold(cwd);
|
|
110
|
+
ok(`${result.created.length} files scaffolded`);
|
|
99
111
|
|
|
100
|
-
//
|
|
101
|
-
step(4, totalSteps, 'Done!');
|
|
112
|
+
// 4. Summary
|
|
102
113
|
print('');
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
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
|
-
|
|
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
|
-
|
|
128
|
-
error(result.error);
|
|
129
|
+
fail(result.error);
|
|
129
130
|
process.exit(1);
|
|
130
131
|
}
|
|
131
132
|
|
|
132
|
-
|
|
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
|
-
|
|
147
|
-
print(
|
|
148
|
-
print(
|
|
149
|
-
print(` ${C.orange}
|
|
150
|
-
print(`
|
|
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(
|
|
159
|
-
print(
|
|
160
|
-
print(` ${C.dim}
|
|
161
|
-
print(` ${C.dim}
|
|
162
|
-
print(` ${C.dim}
|
|
163
|
-
print(
|
|
164
|
-
print(
|
|
165
|
-
print(
|
|
166
|
-
print(` ${C.dim}/design-workflow
|
|
167
|
-
print(` ${C.dim}/design-workflow
|
|
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
|
-
|
|
187
|
-
|
|
188
|
-
case '
|
|
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
|
-
|
|
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
|
|
7
|
-
*
|
|
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
|
-
|
|
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
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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
|
|
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
|
|
51
|
+
module.exports = { checkMcp };
|