myaidev-method 0.3.3 → 0.3.5

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 (132) hide show
  1. package/.claude-plugin/plugin.json +0 -1
  2. package/.env.example +5 -4
  3. package/CHANGELOG.md +2 -2
  4. package/CONTENT_CREATION_GUIDE.md +489 -3211
  5. package/DEVELOPER_USE_CASES.md +1 -1
  6. package/MODULAR_INSTALLATION.md +2 -2
  7. package/README.md +39 -33
  8. package/TECHNICAL_ARCHITECTURE.md +1 -1
  9. package/USER_GUIDE.md +242 -190
  10. package/agents/content-editor-agent.md +90 -0
  11. package/agents/content-planner-agent.md +97 -0
  12. package/agents/content-research-agent.md +62 -0
  13. package/agents/content-seo-agent.md +101 -0
  14. package/agents/content-writer-agent.md +69 -0
  15. package/agents/infographic-analyzer-agent.md +63 -0
  16. package/agents/infographic-designer-agent.md +72 -0
  17. package/bin/cli.js +777 -535
  18. package/{content-rules.example.md → content-rules-example.md} +2 -2
  19. package/dist/mcp/health-check.js +82 -68
  20. package/dist/mcp/mcp-config.json +8 -0
  21. package/dist/mcp/openstack-server.js +1746 -1262
  22. package/dist/server/.tsbuildinfo +1 -1
  23. package/extension.json +21 -4
  24. package/package.json +181 -184
  25. package/skills/company-config/SKILL.md +133 -0
  26. package/skills/configure/SKILL.md +1 -1
  27. package/skills/myai-configurator/SKILL.md +77 -0
  28. package/skills/myai-configurator/content-creation-configurator/SKILL.md +516 -0
  29. package/skills/myai-configurator/content-maintenance-configurator/SKILL.md +397 -0
  30. package/skills/myai-content-enrichment/SKILL.md +114 -0
  31. package/skills/myai-content-ideation/SKILL.md +288 -0
  32. package/skills/myai-content-ideation/evals/evals.json +182 -0
  33. package/skills/myai-content-production-coordinator/SKILL.md +946 -0
  34. package/skills/{content-rules-setup → myai-content-rules-setup}/SKILL.md +1 -1
  35. package/skills/{content-verifier → myai-content-verifier}/SKILL.md +1 -1
  36. package/skills/myai-content-writer/SKILL.md +333 -0
  37. package/skills/myai-content-writer/agents/editor-agent.md +138 -0
  38. package/skills/myai-content-writer/agents/planner-agent.md +121 -0
  39. package/skills/myai-content-writer/agents/research-agent.md +83 -0
  40. package/skills/myai-content-writer/agents/seo-agent.md +139 -0
  41. package/skills/myai-content-writer/agents/visual-planner-agent.md +110 -0
  42. package/skills/myai-content-writer/agents/writer-agent.md +85 -0
  43. package/skills/{infographic → myai-infographic}/SKILL.md +1 -1
  44. package/skills/myai-proprietary-content-verifier/SKILL.md +175 -0
  45. package/skills/myai-proprietary-content-verifier/evals/evals.json +36 -0
  46. package/skills/myai-skill-builder/SKILL.md +699 -0
  47. package/skills/myai-skill-builder/agents/analyzer-agent.md +137 -0
  48. package/skills/myai-skill-builder/agents/comparator-agent.md +77 -0
  49. package/skills/myai-skill-builder/agents/grader-agent.md +103 -0
  50. package/skills/myai-skill-builder/assets/eval_review.html +131 -0
  51. package/skills/myai-skill-builder/references/schemas.md +211 -0
  52. package/skills/myai-skill-builder/scripts/aggregate_benchmark.py +190 -0
  53. package/skills/myai-skill-builder/scripts/generate_review.py +381 -0
  54. package/skills/myai-skill-builder/scripts/package_skill.py +91 -0
  55. package/skills/myai-skill-builder/scripts/run_eval.py +105 -0
  56. package/skills/myai-skill-builder/scripts/run_loop.py +211 -0
  57. package/skills/myai-skill-builder/scripts/utils.py +123 -0
  58. package/skills/myai-visual-generator/SKILL.md +125 -0
  59. package/skills/myai-visual-generator/evals/evals.json +155 -0
  60. package/skills/myai-visual-generator/references/infographic-pipeline.md +73 -0
  61. package/skills/myai-visual-generator/references/research-visuals.md +57 -0
  62. package/skills/myai-visual-generator/references/services.md +89 -0
  63. package/skills/myai-visual-generator/scripts/visual-generation-utils.js +1272 -0
  64. package/skills/myaidev-analyze/agents/dependency-mapper-agent.md +236 -0
  65. package/skills/myaidev-analyze/agents/pattern-detector-agent.md +240 -0
  66. package/skills/myaidev-analyze/agents/structure-scanner-agent.md +171 -0
  67. package/skills/myaidev-analyze/agents/tech-profiler-agent.md +291 -0
  68. package/skills/myaidev-architect/agents/compliance-checker-agent.md +287 -0
  69. package/skills/myaidev-architect/agents/requirements-analyst-agent.md +194 -0
  70. package/skills/myaidev-architect/agents/system-designer-agent.md +315 -0
  71. package/skills/myaidev-coder/agents/implementer-agent.md +185 -0
  72. package/skills/myaidev-coder/agents/integration-agent.md +168 -0
  73. package/skills/myaidev-coder/agents/pattern-scanner-agent.md +161 -0
  74. package/skills/myaidev-coder/agents/self-reviewer-agent.md +168 -0
  75. package/skills/myaidev-debug/agents/fix-agent-debug.md +317 -0
  76. package/skills/myaidev-debug/agents/hypothesis-agent.md +226 -0
  77. package/skills/myaidev-debug/agents/investigator-agent.md +250 -0
  78. package/skills/myaidev-debug/agents/symptom-collector-agent.md +231 -0
  79. package/skills/myaidev-documenter/agents/code-reader-agent.md +172 -0
  80. package/skills/myaidev-documenter/agents/doc-validator-agent.md +174 -0
  81. package/skills/myaidev-documenter/agents/doc-writer-agent.md +379 -0
  82. package/skills/myaidev-figma/SKILL.md +212 -0
  83. package/skills/myaidev-figma/capture.js +133 -0
  84. package/skills/myaidev-figma/crawl.js +130 -0
  85. package/skills/myaidev-figma-configure/SKILL.md +130 -0
  86. package/skills/myaidev-migrate/agents/migration-planner-agent.md +237 -0
  87. package/skills/myaidev-migrate/agents/migration-writer-agent.md +248 -0
  88. package/skills/myaidev-migrate/agents/schema-analyzer-agent.md +190 -0
  89. package/skills/myaidev-performance/agents/benchmark-agent.md +281 -0
  90. package/skills/myaidev-performance/agents/optimizer-agent.md +277 -0
  91. package/skills/myaidev-performance/agents/profiler-agent.md +252 -0
  92. package/skills/myaidev-refactor/agents/refactor-executor-agent.md +221 -0
  93. package/skills/myaidev-refactor/agents/refactor-planner-agent.md +213 -0
  94. package/skills/myaidev-refactor/agents/regression-guard-agent.md +242 -0
  95. package/skills/myaidev-refactor/agents/smell-detector-agent.md +233 -0
  96. package/skills/myaidev-reviewer/agents/auto-fixer-agent.md +238 -0
  97. package/skills/myaidev-reviewer/agents/code-analyst-agent.md +220 -0
  98. package/skills/myaidev-reviewer/agents/security-scanner-agent.md +262 -0
  99. package/skills/myaidev-tester/agents/coverage-analyst-agent.md +163 -0
  100. package/skills/myaidev-tester/agents/tdd-driver-agent.md +242 -0
  101. package/skills/myaidev-tester/agents/test-runner-agent.md +176 -0
  102. package/skills/myaidev-tester/agents/test-strategist-agent.md +154 -0
  103. package/skills/myaidev-tester/agents/test-writer-agent.md +242 -0
  104. package/skills/myaidev-workflow/agents/analyzer-agent.md +317 -0
  105. package/skills/myaidev-workflow/agents/coordinator-agent.md +253 -0
  106. package/skills/openstack-manager/SKILL.md +1 -1
  107. package/skills/payloadcms-publisher/SKILL.md +141 -77
  108. package/skills/payloadcms-publisher/references/field-mapping.md +142 -0
  109. package/skills/payloadcms-publisher/references/lexical-format.md +97 -0
  110. package/skills/security-auditor/SKILL.md +1 -1
  111. package/src/cli/commands/addon.js +184 -123
  112. package/src/config/workflows.js +172 -228
  113. package/src/lib/ascii-banner.js +197 -182
  114. package/src/lib/{content-coordinator.js → content-production-coordinator.js} +649 -459
  115. package/src/lib/installation-detector.js +93 -59
  116. package/src/lib/payloadcms-utils.js +285 -510
  117. package/src/lib/update-manager.js +120 -61
  118. package/src/lib/workflow-installer.js +55 -0
  119. package/src/mcp/health-check.js +82 -68
  120. package/src/mcp/openstack-server.js +1746 -1262
  121. package/src/scripts/configure-visual-apis.js +224 -173
  122. package/src/scripts/configure-wordpress-mcp.js +96 -66
  123. package/src/scripts/init/install.js +109 -85
  124. package/src/scripts/init-project.js +138 -67
  125. package/src/scripts/utils/write-content.js +67 -52
  126. package/src/scripts/wordpress/publish-to-wordpress.js +128 -128
  127. package/src/templates/claude/CLAUDE.md +131 -0
  128. package/hooks/hooks.json +0 -26
  129. package/skills/content-coordinator/SKILL.md +0 -130
  130. package/skills/content-enrichment/SKILL.md +0 -80
  131. package/skills/content-writer/SKILL.md +0 -285
  132. package/skills/visual-generator/SKILL.md +0 -140
@@ -0,0 +1,212 @@
1
+ ---
2
+ name: myaidev-figma
3
+ description: Capture any website (all pages or selected sub-pages) and push the designs directly into a Figma file. Invoke this when the user wants to import, capture, screenshot, or convert a website into Figma designs.
4
+ user-invocable: true
5
+ allowed-tools: Bash, Read, Write, Edit, mcp__figma-remote-mcp__generate_figma_design
6
+ ---
7
+
8
+ # /myaidev-figma — Website → Figma Design Capture
9
+
10
+ You are now running the **myaidev-figma** skill. Your job is to capture a live website (homepage + sub-pages) and push every selected page into a Figma file as a pixel-faithful design. Follow every step precisely.
11
+
12
+ ---
13
+
14
+ ## STEP 0 — Greet & Collect Inputs
15
+
16
+ Tell the user:
17
+ > "**myaidev-figma** — Website to Figma Capture
18
+ > I'll crawl your site, let you pick which pages to capture, and push them all into Figma."
19
+
20
+ Then ask these three questions **together in one message**:
21
+
22
+ 1. **Website URL** — what is the root URL to capture? (e.g. `https://example.com`)
23
+ 2. **Figma destination** — should I:
24
+ - (a) Create a **new** Figma file — if so, what should it be named?
25
+ - (b) Add to an **existing** Figma file — if so, paste the Figma file URL or key.
26
+ 3. **Crawl depth** — how deep should I go finding sub-pages? (`1` = direct links from homepage, `2` = two levels deep). Default is `1`.
27
+
28
+ Wait for the user's answers before continuing.
29
+
30
+ ---
31
+
32
+ ## STEP 1 — Ensure Playwright is Available
33
+
34
+ Run this shell check:
35
+
36
+ ```bash
37
+ npx playwright --version 2>/dev/null || echo "NOT_INSTALLED"
38
+ ```
39
+
40
+ **If playwright is missing** (output contains `NOT_INSTALLED`):
41
+ - Tell the user: "Installing Playwright MCP server and browser dependencies — this may take a minute..."
42
+ - Run: `npm install -g @playwright/mcp playwright 2>&1 | tail -5`
43
+ - Then install the Chromium browser: `npx playwright install chromium 2>&1 | tail -10`
44
+ - After install, verify: `npx playwright --version`
45
+
46
+ **Also ensure the Playwright MCP server is registered with Claude:**
47
+ ```bash
48
+ claude mcp get playwright 2>/dev/null || claude mcp add playwright -- npx @playwright/mcp 2>&1
49
+ ```
50
+
51
+ If the `mcp add` succeeded, tell the user:
52
+ > "Playwright MCP server registered. **Please restart Claude Code** once to activate MCP, then run `/myaidev-figma` again."
53
+ > Then **stop** — do not continue until the user restarts.
54
+
55
+ If playwright was already installed and the MCP was already registered, continue to STEP 2.
56
+
57
+ ---
58
+
59
+ ## STEP 2 — Find the Playwright + Chromium Paths
60
+
61
+ Run these to discover the environment:
62
+
63
+ ```bash
64
+ # Find playwright package
65
+ PLAYWRIGHT_PKG=$(find ~/.npm/_npx -name "playwright" -type d -maxdepth 8 2>/dev/null | sort -r | head -1)
66
+ echo "PLAYWRIGHT_PKG=$PLAYWRIGHT_PKG"
67
+
68
+ # Find Chromium executable (macOS)
69
+ CHROMIUM=$(find ~/Library/Caches/ms-playwright -name "chrome-headless-shell" -o -name "Chromium" -type f 2>/dev/null | grep -v ".pak" | sort -r | head -1)
70
+ # Try Linux if macOS yields nothing
71
+ if [ -z "$CHROMIUM" ]; then
72
+ CHROMIUM=$(find ~/.cache/ms-playwright -name "chrome" -type f 2>/dev/null | sort -r | head -1)
73
+ fi
74
+ echo "CHROMIUM=$CHROMIUM"
75
+ ```
76
+
77
+ Save these values — you will use them in the Node.js scripts below. If `PLAYWRIGHT_PKG` is empty, the package may be installed globally; try:
78
+ ```bash
79
+ PLAYWRIGHT_PKG=$(node -e "console.log(require.resolve('playwright').replace('/index.js',''))" 2>/dev/null || echo "")
80
+ ```
81
+
82
+ ---
83
+
84
+ ## STEP 3 — Crawl the Website to Discover Pages
85
+
86
+ Use the crawl.js script located at `~/.claude/skills/myaidev-figma/crawl.js`.
87
+
88
+ Run it like this (replace paths with what you found in STEP 2):
89
+ ```bash
90
+ NODE_PATH="<PLAYWRIGHT_PKG>/.." node ~/.claude/skills/myaidev-figma/crawl.js "<USER_URL>" <CRAWL_DEPTH> 2>/tmp/dev-f-crawl-err.log
91
+ ```
92
+
93
+ If crawl.js fails (bad NODE_PATH, etc.), fall back to using `mcp__playwright__browser_navigate` to navigate to the URL and extract links from the page snapshot. Extract all `<a href>` links that share the same origin as the root URL.
94
+
95
+ Parse the JSON output. You now have a list of pages like:
96
+ ```json
97
+ [
98
+ { "url": "https://example.com/", "title": "Home", "depth": 0 },
99
+ { "url": "https://example.com/pricing", "title": "Pricing", "depth": 1 },
100
+ ...
101
+ ]
102
+ ```
103
+
104
+ **Present the discovered pages to the user** in a numbered list:
105
+ ```
106
+ Found N pages:
107
+ 1. / — Home
108
+ 2. /pricing — Pricing
109
+ 3. /about — About Us
110
+ ...
111
+
112
+ Which pages would you like to capture?
113
+ Enter numbers (e.g. "1 3 5"), "all", or "1-5" for a range.
114
+ (Tip: capturing many pages takes longer — start with a few to test)
115
+ ```
116
+
117
+ Wait for the user's selection. Parse it into the final list of URLs to capture.
118
+
119
+ ---
120
+
121
+ ## STEP 4 — Set Up Figma Destination
122
+
123
+ Call `mcp__figma-remote-mcp__generate_figma_design` **without any parameters** first to get the current options/plans list.
124
+
125
+ Based on the user's answer from STEP 0:
126
+
127
+ **If new file:**
128
+ - Use `outputMode: "newFile"` with the user's chosen `fileName` and the appropriate `planKey` from the options list.
129
+
130
+ **If existing file:**
131
+ - Extract `fileKey` from the URL they pasted (format: `figma.com/design/<fileKey>/...`).
132
+ - Use `outputMode: "existingFile"` with that `fileKey`.
133
+
134
+ Generate **one capture ID per page** by calling `mcp__figma-remote-mcp__generate_figma_design` with the chosen outputMode once per page. Store each `captureId` and `endpoint` from the responses.
135
+
136
+ > Important: call generate_figma_design once per page to get separate captureIds. For `existingFile`, use the same `fileKey` for all calls.
137
+
138
+ ---
139
+
140
+ ## STEP 5 — Capture Each Page
141
+
142
+ For each page in the user's selection, run `capture.js`:
143
+
144
+ ```bash
145
+ NODE_PATH="<PLAYWRIGHT_PKG>/.." node ~/.claude/skills/myaidev-figma/capture.js \
146
+ "<PAGE_URL>" \
147
+ "<CAPTURE_ID>" \
148
+ "<ENDPOINT_URL>" \
149
+ "body" \
150
+ 2>/tmp/dev-f-capture-<slug>.log
151
+ ```
152
+
153
+ **Run captures sequentially** (one at a time) to avoid overloading the browser.
154
+
155
+ After each capture starts, immediately begin polling:
156
+
157
+ ```
158
+ Poll loop (up to 10 times, every 5 seconds):
159
+ Call mcp__figma-remote-mcp__generate_figma_design with captureId: "<CAPTURE_ID>"
160
+ If status == "completed" → move to next page
161
+ If status == "pending" or "processing" → wait 5s and retry
162
+ If still pending after 10 polls → log error and move on
163
+ ```
164
+
165
+ Show the user a live status line per page:
166
+ ```
167
+ [1/5] Capturing https://example.com/ ... ✓ Done
168
+ [2/5] Capturing https://example.com/pricing ... ⏳ Processing...
169
+ ```
170
+
171
+ ---
172
+
173
+ ## STEP 6 — Report Results
174
+
175
+ Once all captures are done, tell the user:
176
+
177
+ ```
178
+ ✓ myaidev-figma complete! X of Y pages captured.
179
+
180
+ Figma file: <FIGMA_FILE_URL>
181
+
182
+ Pages captured:
183
+ ✓ / — Home
184
+ ✓ /pricing — Pricing
185
+ ✗ /blog — Failed (timeout)
186
+
187
+ To capture more pages or re-capture a page, just run /myaidev-figma again.
188
+ The Figma capture toolbar (visible in the browser) also lets you manually re-capture pages at any time.
189
+ ```
190
+
191
+ Open the Figma file:
192
+ ```bash
193
+ open "<FIGMA_FILE_URL>"
194
+ ```
195
+
196
+ ---
197
+
198
+ ## Error Handling
199
+
200
+ - **Capture returns `success: false`**: The captureId may have expired. Generate a new one and retry that page once.
201
+ - **Node.js script not found**: Use the absolute path `~/.claude/skills/myaidev-figma/capture.js`.
202
+ - **`window.figma` not defined after injection**: The CSP stripping may have failed. Try navigating to the page with hash params approach or report the issue to the user.
203
+ - **Browser not found**: Run `npx playwright install chromium` and retry.
204
+ - **Rate limits or network errors**: Wait 10 seconds and retry up to 3 times.
205
+
206
+ ---
207
+
208
+ ## Notes
209
+
210
+ - The `$ARGUMENTS` variable contains anything the user typed after `/myaidev-figma`. If they passed a URL directly (e.g. `/myaidev-figma https://example.com`), skip asking for the URL in STEP 0 and use `$ARGUMENTS` as the URL.
211
+ - Always be transparent about what you're doing — show the Bash commands you run and their outputs.
212
+ - If the user already has Playwright MCP tools available (`mcp__playwright__browser_navigate` etc.), prefer using those for navigation in STEP 3 instead of the Node.js crawl script.
@@ -0,0 +1,133 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * dev-f capture script
4
+ * Usage: node capture.js <url> <captureId> <endpoint> [selector]
5
+ * Captures a webpage and submits it to the Figma MCP capture endpoint.
6
+ */
7
+
8
+ const { chromium } = require('playwright');
9
+
10
+ const [,, targetUrl, captureId, endpoint, selector = 'body'] = process.argv;
11
+
12
+ if (!targetUrl || !captureId || !endpoint) {
13
+ console.error('Usage: node capture.js <url> <captureId> <endpoint> [selector]');
14
+ process.exit(1);
15
+ }
16
+
17
+ // Find an available Chromium executable
18
+ const fs = require('fs');
19
+ const path = require('path');
20
+ const os = require('os');
21
+
22
+ function findChromium() {
23
+ const base = path.join(os.homedir(), 'Library', 'Caches', 'ms-playwright');
24
+ if (!fs.existsSync(base)) return null;
25
+
26
+ const dirs = fs.readdirSync(base)
27
+ .filter(d => d.startsWith('chromium'))
28
+ .sort()
29
+ .reverse(); // prefer newer
30
+
31
+ for (const dir of dirs) {
32
+ // arm64
33
+ const arm = path.join(base, dir, 'chrome-mac-arm64', 'Chromium.app', 'Contents', 'MacOS', 'Chromium');
34
+ if (fs.existsSync(arm)) return arm;
35
+ // headless shell arm64
36
+ const shell_arm = path.join(base, dir, 'chrome-headless-shell-mac-arm64', 'chrome-headless-shell');
37
+ if (fs.existsSync(shell_arm)) return shell_arm;
38
+ // x64
39
+ const x64 = path.join(base, dir, 'chrome-mac-x64', 'Chromium.app', 'Contents', 'MacOS', 'Chromium');
40
+ if (fs.existsSync(x64)) return x64;
41
+ const shell_x64 = path.join(base, dir, 'chrome-headless-shell-mac-x64', 'chrome-headless-shell');
42
+ if (fs.existsSync(shell_x64)) return shell_x64;
43
+ }
44
+
45
+ // Linux paths
46
+ const linuxBase = path.join(os.homedir(), '.cache', 'ms-playwright');
47
+ if (fs.existsSync(linuxBase)) {
48
+ const ldirs = fs.readdirSync(linuxBase).filter(d => d.startsWith('chromium')).sort().reverse();
49
+ for (const dir of ldirs) {
50
+ const lp = path.join(linuxBase, dir, 'chrome-linux', 'chrome');
51
+ if (fs.existsSync(lp)) return lp;
52
+ const ls = path.join(linuxBase, dir, 'chrome-linux', 'chrome-headless-shell');
53
+ if (fs.existsSync(ls)) return ls;
54
+ }
55
+ }
56
+
57
+ return null;
58
+ }
59
+
60
+ (async () => {
61
+ const executablePath = findChromium();
62
+
63
+ const launchOptions = { headless: true };
64
+ if (executablePath) {
65
+ launchOptions.executablePath = executablePath;
66
+ process.stderr.write(`Using Chromium: ${executablePath}\n`);
67
+ } else {
68
+ process.stderr.write('No cached Chromium found, using Playwright default (may need install)\n');
69
+ }
70
+
71
+ const browser = await chromium.launch(launchOptions);
72
+ const context = await browser.newContext({ viewport: { width: 1440, height: 900 } });
73
+ const page = await context.newPage();
74
+
75
+ // Strip CSP headers so the injected capture script can run
76
+ await page.route('**/*', async (route) => {
77
+ try {
78
+ const response = await route.fetch();
79
+ const headers = { ...response.headers() };
80
+ delete headers['content-security-policy'];
81
+ delete headers['content-security-policy-report-only'];
82
+ await route.fulfill({ response, headers });
83
+ } catch (e) {
84
+ await route.continue();
85
+ }
86
+ });
87
+
88
+ process.stderr.write(`Navigating to: ${targetUrl}\n`);
89
+ await page.goto(targetUrl, { waitUntil: 'load', timeout: 60000 });
90
+ await page.waitForTimeout(2000);
91
+ process.stderr.write(`Title: ${await page.title()}\n`);
92
+
93
+ // Fetch and inject the Figma capture script
94
+ const r = await context.request.get('https://mcp.figma.com/mcp/html-to-design/capture.js');
95
+ const scriptText = await r.text();
96
+ process.stderr.write(`Capture script fetched (${scriptText.length} bytes)\n`);
97
+
98
+ await page.evaluate((s) => {
99
+ const el = document.createElement('script');
100
+ el.textContent = s;
101
+ document.head.appendChild(el);
102
+ }, scriptText);
103
+
104
+ await page.waitForTimeout(1000);
105
+
106
+ const hasFigma = await page.evaluate(() => typeof window.figma !== 'undefined');
107
+ if (!hasFigma) {
108
+ process.stderr.write('ERROR: window.figma not available after script injection\n');
109
+ await browser.close();
110
+ process.exit(1);
111
+ }
112
+
113
+ process.stderr.write('Submitting capture...\n');
114
+ const result = await page.evaluate(
115
+ async ({ captureId, endpoint, selector }) => {
116
+ return await window.figma.captureForDesign({ captureId, endpoint, selector });
117
+ },
118
+ { captureId, endpoint, selector }
119
+ );
120
+
121
+ process.stderr.write(`Result: ${JSON.stringify(result)}\n`);
122
+ await browser.close();
123
+
124
+ if (result && result.success === false) {
125
+ process.stderr.write(`Capture failed: ${result.error}\n`);
126
+ process.exit(1);
127
+ }
128
+
129
+ console.log(JSON.stringify(result));
130
+ })().catch(e => {
131
+ process.stderr.write(`Fatal: ${e.message}\n`);
132
+ process.exit(1);
133
+ });
@@ -0,0 +1,130 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * dev-f crawl script
4
+ * Usage: node crawl.js <url> [maxDepth]
5
+ * Crawls a website and outputs a JSON array of discovered internal page URLs.
6
+ */
7
+
8
+ const { chromium } = require('playwright');
9
+
10
+ const [,, rootUrl, maxDepthArg = '1'] = process.argv;
11
+ const maxDepth = parseInt(maxDepthArg, 10);
12
+
13
+ if (!rootUrl) {
14
+ console.error('Usage: node crawl.js <url> [maxDepth]');
15
+ process.exit(1);
16
+ }
17
+
18
+ const fs = require('fs');
19
+ const path = require('path');
20
+ const os = require('os');
21
+
22
+ function findChromium() {
23
+ const base = path.join(os.homedir(), 'Library', 'Caches', 'ms-playwright');
24
+ if (!fs.existsSync(base)) return null;
25
+ const dirs = fs.readdirSync(base).filter(d => d.startsWith('chromium')).sort().reverse();
26
+ for (const dir of dirs) {
27
+ const shell_arm = path.join(base, dir, 'chrome-headless-shell-mac-arm64', 'chrome-headless-shell');
28
+ if (fs.existsSync(shell_arm)) return shell_arm;
29
+ const arm = path.join(base, dir, 'chrome-mac-arm64', 'Chromium.app', 'Contents', 'MacOS', 'Chromium');
30
+ if (fs.existsSync(arm)) return arm;
31
+ const x64 = path.join(base, dir, 'chrome-mac-x64', 'Chromium.app', 'Contents', 'MacOS', 'Chromium');
32
+ if (fs.existsSync(x64)) return x64;
33
+ const shell_x64 = path.join(base, dir, 'chrome-headless-shell-mac-x64', 'chrome-headless-shell');
34
+ if (fs.existsSync(shell_x64)) return shell_x64;
35
+ }
36
+ const linuxBase = path.join(os.homedir(), '.cache', 'ms-playwright');
37
+ if (fs.existsSync(linuxBase)) {
38
+ const ldirs = fs.readdirSync(linuxBase).filter(d => d.startsWith('chromium')).sort().reverse();
39
+ for (const dir of ldirs) {
40
+ const lp = path.join(linuxBase, dir, 'chrome-linux', 'chrome');
41
+ if (fs.existsSync(lp)) return lp;
42
+ }
43
+ }
44
+ return null;
45
+ }
46
+
47
+ function normalizeUrl(href, base) {
48
+ try {
49
+ const u = new URL(href, base);
50
+ u.hash = '';
51
+ if (u.pathname !== '/' && u.pathname.endsWith('/')) {
52
+ u.pathname = u.pathname.slice(0, -1);
53
+ }
54
+ return u.toString();
55
+ } catch {
56
+ return null;
57
+ }
58
+ }
59
+
60
+ (async () => {
61
+ const rootParsed = new URL(rootUrl);
62
+ const origin = rootParsed.origin;
63
+
64
+ const executablePath = findChromium();
65
+ const launchOptions = { headless: true };
66
+ if (executablePath) launchOptions.executablePath = executablePath;
67
+
68
+ const browser = await chromium.launch(launchOptions);
69
+ const context = await browser.newContext({ viewport: { width: 1440, height: 900 } });
70
+
71
+ const visited = new Set();
72
+ const queue = [{ url: normalizeUrl(rootUrl, rootUrl), depth: 0 }];
73
+ const pages = [];
74
+
75
+ // Always include the root
76
+ const rootNorm = normalizeUrl(rootUrl, rootUrl);
77
+ visited.add(rootNorm);
78
+ pages.push({ url: rootNorm, title: '', depth: 0 });
79
+
80
+ while (queue.length > 0) {
81
+ const { url, depth } = queue.shift();
82
+ if (depth > maxDepth) continue;
83
+
84
+ process.stderr.write(`Crawling (depth ${depth}): ${url}\n`);
85
+ const page = await context.newPage();
86
+
87
+ try {
88
+ await page.goto(url, { waitUntil: 'load', timeout: 30000 });
89
+ await page.waitForTimeout(500);
90
+
91
+ // Update title for this page
92
+ const title = await page.title();
93
+ const existing = pages.find(p => p.url === url);
94
+ if (existing) existing.title = title;
95
+
96
+ if (depth < maxDepth) {
97
+ // Extract all internal links
98
+ const links = await page.evaluate((origin) => {
99
+ return Array.from(document.querySelectorAll('a[href]'))
100
+ .map(a => a.href)
101
+ .filter(h => h.startsWith(origin));
102
+ }, origin);
103
+
104
+ for (const link of links) {
105
+ const norm = normalizeUrl(link, url);
106
+ if (!norm) continue;
107
+ if (!norm.startsWith(origin)) continue;
108
+ // Skip non-page URLs
109
+ if (/\.(pdf|zip|png|jpg|jpeg|gif|svg|ico|css|js|xml|json|woff|woff2|ttf|eot)(\?|$)/i.test(norm)) continue;
110
+ if (!visited.has(norm)) {
111
+ visited.add(norm);
112
+ const pg = { url: norm, title: '', depth: depth + 1 };
113
+ pages.push(pg);
114
+ queue.push({ url: norm, depth: depth + 1 });
115
+ }
116
+ }
117
+ }
118
+ } catch (e) {
119
+ process.stderr.write(`Failed to crawl ${url}: ${e.message}\n`);
120
+ } finally {
121
+ await page.close();
122
+ }
123
+ }
124
+
125
+ await browser.close();
126
+ console.log(JSON.stringify(pages, null, 2));
127
+ })().catch(e => {
128
+ process.stderr.write(`Fatal: ${e.message}\n`);
129
+ process.exit(1);
130
+ });
@@ -0,0 +1,130 @@
1
+ ---
2
+ name: myaidev-figma-configure
3
+ description: One-time setup for myaidev-figma. Registers Playwright MCP and Figma Remote MCP, installs the Figma plugin, and walks the user through Figma authentication. Run this before using /myaidev-figma for the first time.
4
+ user-invocable: true
5
+ allowed-tools: Bash, mcp__figma-remote-mcp__whoami
6
+ ---
7
+
8
+ # /myaidev-figma-configure — One-time Setup
9
+
10
+ You are running **myaidev-figma-configure**. Your job is to get the user's environment ready for `/myaidev-figma` in as few steps as possible.
11
+
12
+ Greet the user:
13
+
14
+ > "**myaidev-figma-configure** — One-time Setup
15
+ > I'll register Playwright MCP, Figma Remote MCP, install the Figma plugin, and verify your Figma authentication. This only needs to be done once."
16
+
17
+ Track two flags as you proceed:
18
+ - `NEEDS_RESTART` — set to true if any MCP was newly registered
19
+ - `AUTH_NEEDED` — set to true if Figma authentication still needs to happen
20
+
21
+ ---
22
+
23
+ ## STEP 1 — Register Playwright MCP
24
+
25
+ Check if already registered:
26
+ ```bash
27
+ claude mcp get playwright 2>/dev/null && echo "ALREADY_REGISTERED" || echo "NOT_REGISTERED"
28
+ ```
29
+
30
+ **If NOT_REGISTERED:**
31
+ ```bash
32
+ claude mcp add playwright -- npx @playwright/mcp 2>&1
33
+ ```
34
+ - On success: tell user "✓ Playwright MCP registered." Set `NEEDS_RESTART=true`.
35
+ - On failure: tell user the exact error and stop — they may need to update Claude Code (`npm install -g @anthropic-ai/claude-code`).
36
+
37
+ **If ALREADY_REGISTERED:**
38
+ - Tell user: "✓ Playwright MCP already registered."
39
+
40
+ ---
41
+
42
+ ## STEP 2 — Register Figma Remote MCP
43
+
44
+ ```bash
45
+ claude mcp get figma-remote-mcp 2>/dev/null && echo "ALREADY_REGISTERED" || echo "NOT_REGISTERED"
46
+ ```
47
+
48
+ **If NOT_REGISTERED:**
49
+ ```bash
50
+ claude mcp add --transport http figma-remote-mcp https://mcp.figma.com/mcp 2>&1
51
+ ```
52
+ - On success: tell user "✓ Figma Remote MCP registered." Set `NEEDS_RESTART=true`.
53
+ - On failure: tell user the exact error and stop.
54
+
55
+ **If ALREADY_REGISTERED:**
56
+ - Tell user: "✓ Figma Remote MCP already registered."
57
+
58
+ ---
59
+
60
+ ## STEP 3 — Install Figma Plugin
61
+
62
+ ```bash
63
+ claude plugin install figma@claude-plugin-directory 2>&1
64
+ echo "EXIT:$?"
65
+ ```
66
+
67
+ - If exit code is 0: tell user "✓ Figma plugin installed."
68
+ - If exit code is non-zero or command not found: tell the user:
69
+ > "After restarting, run this slash command to install the Figma plugin: `/plugin install figma@claude-plugin-directory`"
70
+
71
+ ---
72
+
73
+ ## STEP 4 — Authenticate with Figma
74
+
75
+ **If `NEEDS_RESTART=true`:** Skip this step. Jump to STEP 5.
76
+
77
+ **If everything was already registered (no restart needed):**
78
+
79
+ Tell user: "Verifying your Figma authentication..."
80
+
81
+ Call `mcp__figma-remote-mcp__whoami`.
82
+
83
+ **Case A — returns user details (name/email):**
84
+ - Tell user: "✓ Authenticated with Figma as **[name]**."
85
+ - No further action needed.
86
+
87
+ **Case B — returns an auth URL or login prompt:**
88
+ - Open it automatically:
89
+ ```bash
90
+ open "<AUTH_URL>"
91
+ ```
92
+ - Tell user:
93
+ > "A Figma login page has opened in your browser. Sign in and authorize access, then let me know when done."
94
+ - Wait for user confirmation.
95
+ - Call `mcp__figma-remote-mcp__whoami` again.
96
+ - If user details returned: "✓ Authenticated as **[name]**. All done!"
97
+ - If still failing: tell user to try opening the URL manually or re-run `/myaidev-figma-configure`.
98
+
99
+ ---
100
+
101
+ ## STEP 5 — Summary
102
+
103
+ **If `NEEDS_RESTART=true`:**
104
+
105
+ Print:
106
+ ```
107
+ ✓ Setup complete!
108
+
109
+ ✓ Playwright MCP — registered
110
+ ✓ Figma Remote MCP — registered
111
+ ✓ Figma plugin — installed
112
+
113
+ Next steps:
114
+ 1. Restart Claude Code ← MCPs only activate after a restart
115
+ 2. Run /myaidev-figma-configure again to complete Figma authentication
116
+ 3. Then run /myaidev-figma to start capturing
117
+ ```
118
+
119
+ **If everything was already set up and authentication passed:**
120
+
121
+ Print:
122
+ ```
123
+ ✓ All set!
124
+
125
+ ✓ Playwright MCP — ready
126
+ ✓ Figma Remote MCP — ready
127
+ ✓ Figma — authenticated as [name]
128
+
129
+ Run /myaidev-figma to start capturing websites into Figma.
130
+ ```