@noemuch/bridge-ds 2.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Noe Chague
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,147 @@
1
+ # Bridge DS
2
+
3
+ AI-powered design generation in Figma — 100% design system compliant.
4
+
5
+ Bridge turns [Claude Code](https://claude.ai/download) into a designer that knows your design system inside out. It extracts, documents, and uses your real Figma components, tokens, and text styles to generate production-ready designs.
6
+
7
+ ```
8
+ You describe what you want
9
+ → Claude consults the knowledge base (your DS, documented)
10
+ → Claude writes the spec (exact components, tokens, layout)
11
+ → Claude generates in Figma via figma_execute (real DS components, bound variables)
12
+ → You review in Figma
13
+ ```
14
+
15
+ ## How it works
16
+
17
+ Bridge is two things:
18
+
19
+ 1. **A CLI** (`bridge-ds init`) that scaffolds your project with the design workflow skill
20
+ 2. **A Claude Code skill** (`/design-workflow`) that handles the intelligence — spec writing, DS knowledge, Figma generation
21
+
22
+ The transport layer is [figma-console-mcp](https://github.com/southleft/figma-console-mcp), an MCP server that gives Claude native access to Figma (57+ tools).
23
+
24
+ ```
25
+ Claude Code ──MCP──> figma-console-mcp ──WebSocket──> Figma Desktop
26
+ (your DS library,
27
+ real components,
28
+ bound variables)
29
+ ```
30
+
31
+ ## Prerequisites
32
+
33
+ - [Claude Code](https://claude.ai/download) installed
34
+ - [Node.js 18+](https://nodejs.org)
35
+ - [Figma Desktop](https://www.figma.com/downloads/) (not the web app)
36
+ - A Figma file with a published design system library
37
+
38
+ ## Quick Start
39
+
40
+ ### 1. Install figma-console-mcp
41
+
42
+ ```bash
43
+ claude mcp add figma-console -s user \
44
+ -e FIGMA_ACCESS_TOKEN=figd_YOUR_TOKEN \
45
+ -- npx -y figma-console-mcp@latest
46
+ ```
47
+
48
+ Get your token from [Figma Settings → Personal access tokens](https://help.figma.com/hc/en-us/articles/8085703771159-Manage-personal-access-tokens).
49
+
50
+ ### 2. Connect Figma Desktop
51
+
52
+ 1. Run `npx figma-console-mcp@latest --print-path` to find the plugin directory
53
+ 2. In Figma Desktop: **Plugins → Development → Import plugin from manifest...**
54
+ 3. Select `figma-desktop-bridge/manifest.json`
55
+ 4. Run the plugin in your Figma file
56
+
57
+ ### 3. Initialize your project
58
+
59
+ ```bash
60
+ cd your-project
61
+ npx @noemuch/bridge-ds init
62
+ ```
63
+
64
+ This scaffolds:
65
+ - `.claude/skills/design-workflow/` — the workflow skill + references
66
+ - `.claude/commands/design-workflow.md` — the `/design-workflow` slash command
67
+ - `specs/` — directory for active, shipped, and dropped specs
68
+
69
+ ### 4. Build your knowledge base
70
+
71
+ Open Claude Code in your project:
72
+
73
+ ```
74
+ /design-workflow setup
75
+ ```
76
+
77
+ Claude will:
78
+ 1. Extract your entire DS from Figma (`figma_get_design_system_kit`)
79
+ 2. Analyze every component, token, and style
80
+ 3. Generate intelligent guides (when to use what, decision trees, pattern catalog)
81
+ 4. Ask for product screenshots to document layout patterns
82
+
83
+ ### 5. Start designing
84
+
85
+ ```
86
+ /design-workflow spec a settings page for account information
87
+ ```
88
+
89
+ Claude consults the knowledge base, identifies the right pattern, components, and tokens, and writes a complete spec. Then:
90
+
91
+ ```
92
+ /design-workflow design # Generate in Figma (atomic, verified)
93
+ /design-workflow review # Validate against spec
94
+ /design-workflow done # Archive and ship
95
+ ```
96
+
97
+ ## The Workflow
98
+
99
+ ```
100
+ setup (once) → spec → design → review → done
101
+ ↑ |
102
+ └── iterate ─────────┘
103
+ ```
104
+
105
+ ### Spec-first
106
+ No design without a validated specification. Claude knows exactly which components, tokens, and layout patterns to use because it has your DS documented.
107
+
108
+ ### Atomic generation
109
+ Designs are generated in 4-6 small sequential scripts (~30-80 lines each). After each step, Claude takes a screenshot and verifies before continuing. Bug in step 3? Fix and re-run step 3 only.
110
+
111
+ ### DS-native
112
+ Zero hardcoded hex colors. Zero recreated components. Everything imported from your library via `importComponentByKeyAsync`, bound to variables via `setBoundVariableForPaint`.
113
+
114
+ ### Quality gates
115
+ Blocking checks at every phase transition: spec validation, pattern matching, pre-script element audit, visual fidelity review, DS component reuse audit.
116
+
117
+ ## Knowledge Base
118
+
119
+ The knowledge base is what makes Bridge different from "just executing Figma scripts". During setup, Claude builds a complete understanding of your DS:
120
+
121
+ ```
122
+ knowledge-base/
123
+ registries/ ← Raw DS data (components, variables, text styles)
124
+ guides/
125
+ design-patterns.md ← Layout patterns from your product screenshots
126
+ tokens/ ← When to use which color, spacing, typography
127
+ components/ ← Decision tree: "I need X" → use component Y
128
+ patterns/ ← Form, navigation, feedback, multi-step patterns
129
+ assets/ ← Icons, logos, illustrations catalog
130
+ ui-references/ ← Product screenshots for pattern extraction
131
+ ```
132
+
133
+ ## Commands
134
+
135
+ | Command | What it does |
136
+ |---------|-------------|
137
+ | `/design-workflow setup` | Extract DS + build knowledge base |
138
+ | `/design-workflow spec {name}` | Write a component or screen spec |
139
+ | `/design-workflow design` | Generate in Figma from active spec |
140
+ | `/design-workflow review` | Validate design against spec + tokens |
141
+ | `/design-workflow done` | Archive spec and ship |
142
+ | `/design-workflow drop` | Abandon with preserved learnings |
143
+ | `/design-workflow status` | Show current state, suggest next action |
144
+
145
+ ## License
146
+
147
+ MIT
package/bin/bridge.js ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { run } = require('../lib/cli');
4
+ run(process.argv.slice(2));
@@ -0,0 +1 @@
1
+ Read and follow the skill defined in `.claude/skills/design-workflow/SKILL.md`.
package/lib/cli.js ADDED
@@ -0,0 +1,172 @@
1
+ const path = require('path');
2
+ const { scaffold } = require('./scaffold');
3
+ const { checkMcp, setupMcp } = require('./mcp-setup');
4
+
5
+ // ── Branding ──────────────────────────────────────────────
6
+ const C = {
7
+ reset: '\x1b[0m',
8
+ bold: '\x1b[1m',
9
+ dim: '\x1b[2m',
10
+ orange: '\x1b[38;2;237;112;46m',
11
+ green: '\x1b[38;2;76;175;80m',
12
+ red: '\x1b[38;2;244;67;54m',
13
+ yellow: '\x1b[38;2;255;193;7m',
14
+ gray: '\x1b[38;2;158;158;158m',
15
+ white: '\x1b[38;2;255;255;255m',
16
+ };
17
+
18
+ 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
+ }
42
+ }
43
+
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('');
53
+ }
54
+
55
+ // ── Commands ──────────────────────────────────────────────
56
+
57
+ async function cmdInit() {
58
+ banner();
59
+ header('Initializing Bridge DS');
60
+
61
+ const cwd = process.cwd();
62
+ const totalSteps = 4;
63
+
64
+ // Step 1: Check prerequisites
65
+ step(1, totalSteps, 'Checking prerequisites');
66
+ const nodeVersion = process.version.replace('v', '').split('.').map(Number);
67
+ if (nodeVersion[0] < 18) {
68
+ error(`Node.js 18+ required (found ${process.version})`);
69
+ process.exit(1);
70
+ }
71
+ success(`Node.js ${process.version}`);
72
+
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:');
81
+ 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}`);
85
+ print('');
86
+ info('Then re-run: bridge-ds init');
87
+ info('Continuing with file setup...');
88
+ }
89
+
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');
95
+
96
+ for (const f of result.created) {
97
+ muted(f);
98
+ }
99
+
100
+ // Step 4: Summary
101
+ step(4, totalSteps, 'Done!');
102
+ 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}`);
113
+ print('');
114
+ }
115
+
116
+ function cmdHelp() {
117
+ banner();
118
+ print(`${C.bold} Commands:${C.reset}`);
119
+ print('');
120
+ print(` ${C.orange}init${C.reset} Initialize Bridge DS in current project`);
121
+ print(` Scaffolds skills, commands, and specs directories`);
122
+ print('');
123
+ print(` ${C.orange}help${C.reset} Show this help message`);
124
+ print(` ${C.orange}version${C.reset} Show version`);
125
+ print('');
126
+ print(`${C.bold} Usage:${C.reset}`);
127
+ print('');
128
+ print(` ${C.dim}npx bridge-ds init${C.reset} # Initialize in current project`);
129
+ print(` ${C.dim}bridge-ds help${C.reset} # Show help`);
130
+ print('');
131
+ print(`${C.bold} After init:${C.reset}`);
132
+ print('');
133
+ print(` ${C.dim}/design-workflow setup${C.reset} # Extract & document your DS (in Claude Code)`);
134
+ print(` ${C.dim}/design-workflow spec${C.reset} # Spec a component or screen`);
135
+ print(` ${C.dim}/design-workflow design${C.reset} # Generate in Figma`);
136
+ print(` ${C.dim}/design-workflow review${C.reset} # Validate against spec`);
137
+ print(` ${C.dim}/design-workflow done${C.reset} # Archive & ship`);
138
+ print('');
139
+ }
140
+
141
+ function cmdVersion() {
142
+ const pkg = require('../package.json');
143
+ print(`bridge-ds v${pkg.version}`);
144
+ }
145
+
146
+ // ── Router ────────────────────────────────────────────────
147
+
148
+ async function run(args) {
149
+ const cmd = args[0] || 'help';
150
+
151
+ switch (cmd) {
152
+ case 'init':
153
+ await cmdInit();
154
+ break;
155
+ case 'help':
156
+ case '--help':
157
+ case '-h':
158
+ cmdHelp();
159
+ break;
160
+ case 'version':
161
+ case '--version':
162
+ case '-v':
163
+ cmdVersion();
164
+ break;
165
+ default:
166
+ error(`Unknown command: ${cmd}`);
167
+ cmdHelp();
168
+ process.exit(1);
169
+ }
170
+ }
171
+
172
+ module.exports = { run };
@@ -0,0 +1,47 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const os = require('os');
4
+
5
+ /**
6
+ * Check if figma-console-mcp is configured in Claude Code settings.
7
+ * Checks multiple possible locations.
8
+ */
9
+ function checkMcp() {
10
+ const locations = [
11
+ // User-level Claude Code settings
12
+ path.join(os.homedir(), '.claude.json'),
13
+ // Project-level settings
14
+ path.join(process.cwd(), '.claude', 'settings.local.json'),
15
+ ];
16
+
17
+ 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
+ }
30
+ }
31
+ } catch (_) {
32
+ // Ignore parse errors
33
+ }
34
+ }
35
+ }
36
+
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';
45
+ }
46
+
47
+ module.exports = { checkMcp, getMcpAddCommand };
@@ -0,0 +1,120 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ /**
5
+ * Recursively copy a directory, preserving structure.
6
+ */
7
+ function copyDir(src, dest) {
8
+ const created = [];
9
+ if (!fs.existsSync(dest)) {
10
+ fs.mkdirSync(dest, { recursive: true });
11
+ }
12
+ for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
13
+ const srcPath = path.join(src, entry.name);
14
+ const destPath = path.join(dest, entry.name);
15
+ if (entry.isDirectory()) {
16
+ created.push(...copyDir(srcPath, destPath));
17
+ } else {
18
+ fs.copyFileSync(srcPath, destPath);
19
+ created.push(destPath);
20
+ }
21
+ }
22
+ return created;
23
+ }
24
+
25
+ /**
26
+ * Scaffold Bridge DS into the target project directory.
27
+ * Returns { created: string[] } with relative paths of created files.
28
+ */
29
+ function scaffold(projectDir) {
30
+ const created = [];
31
+ const pkgRoot = path.resolve(__dirname, '..');
32
+
33
+ // 1. Copy skills/design-workflow → .claude/skills/design-workflow
34
+ const skillsSrc = path.join(pkgRoot, 'skills', 'design-workflow');
35
+ const skillsDest = path.join(projectDir, '.claude', 'skills', 'design-workflow');
36
+ if (fs.existsSync(skillsSrc)) {
37
+ const files = copyDir(skillsSrc, skillsDest);
38
+ created.push(...files.map(f => path.relative(projectDir, f)));
39
+ }
40
+
41
+ // 2. Copy commands/design-workflow.md → .claude/commands/design-workflow.md
42
+ const cmdSrc = path.join(pkgRoot, 'commands', 'design-workflow.md');
43
+ const cmdDest = path.join(projectDir, '.claude', 'commands', 'design-workflow.md');
44
+ if (fs.existsSync(cmdSrc)) {
45
+ fs.mkdirSync(path.dirname(cmdDest), { recursive: true });
46
+ fs.copyFileSync(cmdSrc, cmdDest);
47
+ created.push(path.relative(projectDir, cmdDest));
48
+ }
49
+
50
+ // 3. Create specs/ directory structure
51
+ const specsDirs = [
52
+ 'specs/active',
53
+ 'specs/backlog',
54
+ 'specs/shipped',
55
+ 'specs/dropped',
56
+ ];
57
+ for (const dir of specsDirs) {
58
+ const fullPath = path.join(projectDir, dir);
59
+ if (!fs.existsSync(fullPath)) {
60
+ fs.mkdirSync(fullPath, { recursive: true });
61
+ // Add .gitkeep
62
+ const gitkeep = path.join(fullPath, '.gitkeep');
63
+ fs.writeFileSync(gitkeep, '');
64
+ created.push(path.relative(projectDir, gitkeep));
65
+ }
66
+ }
67
+
68
+ // Create history.log if not exists
69
+ const historyLog = path.join(projectDir, 'specs', 'history.log');
70
+ if (!fs.existsSync(historyLog)) {
71
+ fs.writeFileSync(historyLog, '# Design History\n# date | name | type | figma_url | author\n');
72
+ created.push(path.relative(projectDir, historyLog));
73
+ }
74
+
75
+ // 4. Create empty knowledge-base directories
76
+ const kbDirs = [
77
+ '.claude/skills/design-workflow/references/knowledge-base/registries',
78
+ '.claude/skills/design-workflow/references/knowledge-base/guides/tokens',
79
+ '.claude/skills/design-workflow/references/knowledge-base/guides/components',
80
+ '.claude/skills/design-workflow/references/knowledge-base/guides/patterns',
81
+ '.claude/skills/design-workflow/references/knowledge-base/guides/assets',
82
+ '.claude/skills/design-workflow/references/knowledge-base/ui-references/screenshots',
83
+ ];
84
+ for (const dir of kbDirs) {
85
+ const fullPath = path.join(projectDir, dir);
86
+ if (!fs.existsSync(fullPath)) {
87
+ fs.mkdirSync(fullPath, { recursive: true });
88
+ const gitkeep = path.join(fullPath, '.gitkeep');
89
+ if (!fs.existsSync(gitkeep)) {
90
+ fs.writeFileSync(gitkeep, '');
91
+ }
92
+ }
93
+ }
94
+
95
+ // 5. Update .gitignore
96
+ const gitignorePath = path.join(projectDir, '.gitignore');
97
+ const gitignoreEntries = [
98
+ '',
99
+ '# Bridge DS — knowledge base data (regenerated via /design-workflow setup)',
100
+ '.claude/skills/design-workflow/references/knowledge-base/registries/*.json',
101
+ '.claude/skills/design-workflow/references/knowledge-base/ui-references/screenshots/*.png',
102
+ '.claude/skills/design-workflow/references/knowledge-base/ui-references/screenshots/*.jpg',
103
+ ];
104
+ const gitignoreBlock = gitignoreEntries.join('\n') + '\n';
105
+
106
+ if (fs.existsSync(gitignorePath)) {
107
+ const content = fs.readFileSync(gitignorePath, 'utf8');
108
+ if (!content.includes('Bridge DS')) {
109
+ fs.appendFileSync(gitignorePath, gitignoreBlock);
110
+ created.push('.gitignore (updated)');
111
+ }
112
+ } else {
113
+ fs.writeFileSync(gitignorePath, 'node_modules/\n.DS_Store\n' + gitignoreBlock);
114
+ created.push('.gitignore');
115
+ }
116
+
117
+ return { created };
118
+ }
119
+
120
+ module.exports = { scaffold };
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@noemuch/bridge-ds",
3
+ "version": "2.0.0",
4
+ "description": "AI-powered design generation in Figma — 100% design system compliant. Connects Claude Code to Figma via MCP for spec-first, token-bound, component-native design.",
5
+ "main": "lib/cli.js",
6
+ "bin": {
7
+ "bridge-ds": "./bin/bridge.js"
8
+ },
9
+ "files": [
10
+ "bin/",
11
+ "lib/",
12
+ "skills/",
13
+ "commands/",
14
+ "README.md",
15
+ "LICENSE"
16
+ ],
17
+ "engines": {
18
+ "node": ">=18"
19
+ },
20
+ "scripts": {
21
+ "test": "node bin/bridge.js help"
22
+ },
23
+ "keywords": [
24
+ "claude-code",
25
+ "figma",
26
+ "design-system",
27
+ "mcp",
28
+ "design-tokens",
29
+ "ai-design",
30
+ "figma-plugin-api"
31
+ ],
32
+ "author": "noemuch",
33
+ "license": "MIT",
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "https://github.com/noemuch/bridge.git"
37
+ },
38
+ "homepage": "https://github.com/noemuch/bridge"
39
+ }