opencodekit 0.14.0 → 0.14.2

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 (54) hide show
  1. package/dist/index.js +53 -18
  2. package/dist/template/.opencode/.background-tasks.json +96 -0
  3. package/dist/template/.opencode/.ralph-state.json +12 -0
  4. package/dist/template/.opencode/AGENTS.md +112 -6
  5. package/dist/template/.opencode/agent/build.md +60 -8
  6. package/dist/template/.opencode/agent/explore.md +1 -0
  7. package/dist/template/.opencode/agent/looker.md +124 -0
  8. package/dist/template/.opencode/agent/planner.md +40 -1
  9. package/dist/template/.opencode/agent/review.md +1 -0
  10. package/dist/template/.opencode/agent/rush.md +53 -6
  11. package/dist/template/.opencode/agent/scout.md +1 -1
  12. package/dist/template/.opencode/agent/vision.md +0 -1
  13. package/dist/template/.opencode/command/brainstorm.md +58 -3
  14. package/dist/template/.opencode/command/finish.md +18 -8
  15. package/dist/template/.opencode/command/fix.md +24 -15
  16. package/dist/template/.opencode/command/implement.md +95 -29
  17. package/dist/template/.opencode/command/import-plan.md +30 -8
  18. package/dist/template/.opencode/command/new-feature.md +105 -14
  19. package/dist/template/.opencode/command/plan.md +78 -11
  20. package/dist/template/.opencode/command/pr.md +25 -15
  21. package/dist/template/.opencode/command/ralph-loop.md +97 -0
  22. package/dist/template/.opencode/command/revert-feature.md +15 -3
  23. package/dist/template/.opencode/command/skill-optimize.md +71 -7
  24. package/dist/template/.opencode/command/start.md +63 -15
  25. package/dist/template/.opencode/dcp.jsonc +11 -7
  26. package/dist/template/.opencode/memory/{project/beads-workflow.md → beads-workflow.md} +53 -0
  27. package/dist/template/.opencode/memory/observations/2026-01-09-pattern-ampcode-mcp-json-includetools-pattern.md +42 -0
  28. package/dist/template/.opencode/memory/project/conventions.md +53 -3
  29. package/dist/template/.opencode/memory/project/gotchas.md +52 -5
  30. package/dist/template/.opencode/memory/vector_db/memories.lance/_transactions/{0-8d00d272-cb80-463b-9774-7120a1c994e7.txn → 0-0d25ba80-ba3b-4209-9046-b45d6093b4da.txn} +0 -0
  31. package/dist/template/.opencode/memory/vector_db/memories.lance/_versions/1.manifest +0 -0
  32. package/dist/template/.opencode/memory/vector_db/memories.lance/data/{001010101000000101110001f998d04b63936ff83f9a34152d.lance → 1111100101010101011010004a9ef34df6b29f36a9a53a2892.lance} +0 -0
  33. package/dist/template/.opencode/opencode.json +529 -587
  34. package/dist/template/.opencode/package.json +2 -1
  35. package/dist/template/.opencode/plugin/lsp.ts +299 -0
  36. package/dist/template/.opencode/plugin/memory.ts +77 -1
  37. package/dist/template/.opencode/plugin/package.json +1 -1
  38. package/dist/template/.opencode/plugin/ralph-wiggum.ts +182 -0
  39. package/dist/template/.opencode/plugin/skill-mcp.ts +155 -36
  40. package/dist/template/.opencode/skill/chrome-devtools/SKILL.md +43 -65
  41. package/dist/template/.opencode/skill/chrome-devtools/mcp.json +19 -0
  42. package/dist/template/.opencode/skill/executing-plans/SKILL.md +32 -2
  43. package/dist/template/.opencode/skill/finishing-a-development-branch/SKILL.md +42 -17
  44. package/dist/template/.opencode/skill/playwright/SKILL.md +58 -133
  45. package/dist/template/.opencode/skill/playwright/mcp.json +16 -0
  46. package/dist/template/.opencode/tool/background.ts +461 -0
  47. package/dist/template/.opencode/tool/memory-search.ts +2 -2
  48. package/dist/template/.opencode/tool/ralph.ts +203 -0
  49. package/package.json +4 -16
  50. package/dist/template/.opencode/memory/vector_db/memories.lance/_transactions/1-a3bea825-dad3-47dd-a6d6-ff41b76ff7b0.txn +0 -0
  51. package/dist/template/.opencode/memory/vector_db/memories.lance/_versions/2.manifest +0 -0
  52. package/dist/template/.opencode/memory/vector_db/memories.lance/data/010000101010000000010010701b3840d38c2b5f275da99978.lance +0 -0
  53. /package/dist/template/.opencode/memory/{project/README.md → README.md} +0 -0
  54. /package/dist/template/.opencode/plugin/{notification.ts → notification.ts.bak} +0 -0
@@ -1,7 +1,7 @@
1
1
  import { type ChildProcess, spawn } from "node:child_process";
2
2
  import { existsSync, readFileSync } from "node:fs";
3
3
  import { homedir } from "node:os";
4
- import { join } from "node:path";
4
+ import { dirname, join } from "node:path";
5
5
  import type { Plugin } from "@opencode-ai/plugin";
6
6
  import { tool } from "@opencode-ai/plugin/tool";
7
7
 
@@ -9,6 +9,7 @@ interface McpServerConfig {
9
9
  command: string;
10
10
  args?: string[];
11
11
  env?: Record<string, string>;
12
+ includeTools?: string[]; // Ampcode-style tool filtering with glob patterns
12
13
  }
13
14
 
14
15
  interface McpClient {
@@ -24,6 +25,7 @@ interface McpClient {
24
25
  resources?: any[];
25
26
  prompts?: any[];
26
27
  };
28
+ filteredTools?: any[]; // Tools after includeTools filtering
27
29
  }
28
30
 
29
31
  interface SkillMcpState {
@@ -31,6 +33,37 @@ interface SkillMcpState {
31
33
  loadedSkills: Map<string, Record<string, McpServerConfig>>; // skillName -> mcp configs
32
34
  }
33
35
 
36
+ /**
37
+ * Match a tool name against a glob pattern
38
+ * Supports: exact match, * (any chars), ? (single char)
39
+ */
40
+ function matchGlobPattern(pattern: string, toolName: string): boolean {
41
+ // Exact match
42
+ if (pattern === toolName) return true;
43
+
44
+ // Convert glob to regex
45
+ const regexPattern = pattern
46
+ .replace(/[.+^${}()|[\]\\]/g, "\\$&") // Escape special regex chars
47
+ .replace(/\*/g, ".*") // * -> .*
48
+ .replace(/\?/g, "."); // ? -> .
49
+
50
+ const regex = new RegExp(`^${regexPattern}$`);
51
+ return regex.test(toolName);
52
+ }
53
+
54
+ /**
55
+ * Filter tools based on includeTools patterns
56
+ */
57
+ function filterTools(allTools: any[], includePatterns?: string[]): any[] {
58
+ if (!includePatterns || includePatterns.length === 0) {
59
+ return allTools; // No filtering, return all
60
+ }
61
+
62
+ return allTools.filter((tool) =>
63
+ includePatterns.some((pattern) => matchGlobPattern(pattern, tool.name)),
64
+ );
65
+ }
66
+
34
67
  function parseYamlFrontmatter(content: string): {
35
68
  frontmatter: any;
36
69
  body: string;
@@ -43,11 +76,10 @@ function parseYamlFrontmatter(content: string): {
43
76
 
44
77
  // Simple YAML parser for our use case
45
78
  const frontmatter: any = {};
46
- let currentKey = "";
47
- let currentIndent = 0;
48
79
  let mcpConfig: any = null;
49
80
  let serverName = "";
50
81
  let serverConfig: any = {};
82
+ let currentArrayKey = "";
51
83
 
52
84
  for (const line of yamlStr.split("\n")) {
53
85
  const trimmed = line.trim();
@@ -67,40 +99,80 @@ function parseYamlFrontmatter(content: string): {
67
99
  } else {
68
100
  frontmatter[key] = value || undefined;
69
101
  }
70
- currentKey = key;
71
- currentIndent = indent;
102
+ currentArrayKey = "";
72
103
  } else if (mcpConfig !== null && indent === 2) {
73
104
  // Server name under mcp
74
105
  serverName = key;
75
106
  serverConfig = {};
76
107
  mcpConfig[serverName] = serverConfig;
108
+ currentArrayKey = "";
77
109
  } else if (serverConfig && indent === 4) {
78
110
  // Server config property
79
111
  if (key === "command") {
80
112
  serverConfig.command = value;
81
- } else if (key === "args") {
113
+ currentArrayKey = "";
114
+ } else if (key === "args" || key === "includeTools") {
82
115
  // Parse inline array or set up for multi-line
83
116
  if (value.startsWith("[")) {
84
117
  try {
85
- serverConfig.args = JSON.parse(value);
118
+ serverConfig[key] = JSON.parse(value);
86
119
  } catch {
87
- serverConfig.args = [];
120
+ serverConfig[key] = [];
88
121
  }
122
+ currentArrayKey = "";
89
123
  } else {
90
- serverConfig.args = [];
124
+ serverConfig[key] = [];
125
+ currentArrayKey = key;
91
126
  }
127
+ } else {
128
+ currentArrayKey = "";
92
129
  }
93
130
  }
94
- } else if (trimmed.startsWith("- ") && serverConfig?.args) {
95
- // Array item for args
131
+ } else if (
132
+ trimmed.startsWith("- ") &&
133
+ serverConfig &&
134
+ currentArrayKey &&
135
+ serverConfig[currentArrayKey]
136
+ ) {
137
+ // Array item for args or includeTools
96
138
  const item = trimmed.slice(2).replace(/^["']|["']$/g, "");
97
- serverConfig.args.push(item);
139
+ serverConfig[currentArrayKey].push(item);
98
140
  }
99
141
  }
100
142
 
101
143
  return { frontmatter, body };
102
144
  }
103
145
 
146
+ /**
147
+ * Load MCP config from either mcp.json or YAML frontmatter
148
+ * Priority: mcp.json > YAML frontmatter (Ampcode pattern)
149
+ */
150
+ function loadMcpConfig(
151
+ skillDir: string,
152
+ skillPath: string,
153
+ ): Record<string, McpServerConfig> | null {
154
+ // Try mcp.json first (Ampcode pattern)
155
+ const mcpJsonPath = join(skillDir, "mcp.json");
156
+ if (existsSync(mcpJsonPath)) {
157
+ try {
158
+ const mcpJson = JSON.parse(readFileSync(mcpJsonPath, "utf-8"));
159
+ return mcpJson;
160
+ } catch {
161
+ // Fall through to YAML
162
+ }
163
+ }
164
+
165
+ // Fall back to YAML frontmatter
166
+ const content = readFileSync(skillPath, "utf-8");
167
+ const { frontmatter } = parseYamlFrontmatter(content);
168
+
169
+ if (frontmatter.mcp && Object.keys(frontmatter.mcp).length > 0) {
170
+ return frontmatter.mcp;
171
+ }
172
+
173
+ return null;
174
+ }
175
+
104
176
  function findSkillPath(skillName: string, projectDir: string): string | null {
105
177
  const locations = [
106
178
  join(projectDir, ".opencode", "skill", skillName, "SKILL.md"),
@@ -216,7 +288,7 @@ export const SkillMcpPlugin: Plugin = async ({ directory }) => {
216
288
  console.error(`MCP server error [${key}]:`, err.message);
217
289
  });
218
290
 
219
- proc.on("exit", (code) => {
291
+ proc.on("exit", () => {
220
292
  state.clients.delete(key);
221
293
  });
222
294
 
@@ -227,7 +299,7 @@ export const SkillMcpPlugin: Plugin = async ({ directory }) => {
227
299
  await sendRequest(client, "initialize", {
228
300
  protocolVersion: "2024-11-05",
229
301
  capabilities: {},
230
- clientInfo: { name: "opencode-skill-mcp", version: "1.0.0" },
302
+ clientInfo: { name: "opencode-skill-mcp", version: "1.1.0" },
231
303
  });
232
304
 
233
305
  // Send initialized notification
@@ -241,9 +313,14 @@ export const SkillMcpPlugin: Plugin = async ({ directory }) => {
241
313
  // Discover capabilities
242
314
  try {
243
315
  const toolsResult = await sendRequest(client, "tools/list", {});
244
- client.capabilities = { tools: toolsResult.tools || [] };
316
+ const allTools = toolsResult.tools || [];
317
+ client.capabilities = { tools: allTools };
318
+
319
+ // Apply includeTools filtering (Ampcode pattern)
320
+ client.filteredTools = filterTools(allTools, config.includeTools);
245
321
  } catch {
246
322
  client.capabilities = { tools: [] };
323
+ client.filteredTools = [];
247
324
  }
248
325
  } catch (e: any) {
249
326
  proc.kill();
@@ -255,7 +332,7 @@ export const SkillMcpPlugin: Plugin = async ({ directory }) => {
255
332
  }
256
333
 
257
334
  function disconnectAll() {
258
- for (const [key, client] of state.clients) {
335
+ for (const [, client] of state.clients) {
259
336
  client.process.kill();
260
337
  }
261
338
  state.clients.clear();
@@ -266,10 +343,11 @@ export const SkillMcpPlugin: Plugin = async ({ directory }) => {
266
343
  skill_mcp: tool({
267
344
  description: `Invoke MCP tools from skill-embedded MCP servers.
268
345
 
269
- When a skill declares MCP servers in its YAML frontmatter, use this tool to:
346
+ When a skill declares MCP servers (via mcp.json or YAML frontmatter), use this tool to:
270
347
  - List available tools: skill_mcp(skill_name="playwright", list_tools=true)
271
348
  - Call a tool: skill_mcp(skill_name="playwright", tool_name="browser_navigate", arguments='{"url": "..."}')
272
349
 
350
+ Skills can use "includeTools" to filter which MCP tools are exposed (reduces token usage).
273
351
  The skill must be loaded first via the skill() tool to register its MCP config.`,
274
352
  args: {
275
353
  skill_name: tool.schema
@@ -305,34 +383,34 @@ The skill must be loaded first via the skill() tool to register its MCP config.`
305
383
  return JSON.stringify({ error: "skill_name required" });
306
384
  }
307
385
 
308
- // Find skill and parse its MCP config
386
+ // Find skill path
309
387
  const skillPath = findSkillPath(skill_name, directory);
310
388
  if (!skillPath) {
311
389
  return JSON.stringify({ error: `Skill '${skill_name}' not found` });
312
390
  }
313
391
 
314
- const content = readFileSync(skillPath, "utf-8");
315
- const { frontmatter } = parseYamlFrontmatter(content);
392
+ // Load MCP config from mcp.json or YAML frontmatter
393
+ const skillDir = dirname(skillPath);
394
+ const mcpConfig = loadMcpConfig(skillDir, skillPath);
316
395
 
317
- if (!frontmatter.mcp || Object.keys(frontmatter.mcp).length === 0) {
396
+ if (!mcpConfig) {
318
397
  return JSON.stringify({
319
- error: `Skill '${skill_name}' has no MCP config`,
398
+ error: `Skill '${skill_name}' has no MCP config (check mcp.json or YAML frontmatter)`,
320
399
  });
321
400
  }
322
401
 
323
402
  // Determine which MCP server to use
324
- const mcpServers = frontmatter.mcp as Record<string, McpServerConfig>;
325
- const serverNames = Object.keys(mcpServers);
403
+ const serverNames = Object.keys(mcpConfig);
326
404
  const targetServer = mcp_name || serverNames[0];
327
405
 
328
- if (!mcpServers[targetServer]) {
406
+ if (!mcpConfig[targetServer]) {
329
407
  return JSON.stringify({
330
408
  error: `MCP server '${targetServer}' not found in skill`,
331
409
  available: serverNames,
332
410
  });
333
411
  }
334
412
 
335
- const serverConfig = mcpServers[targetServer];
413
+ const serverConfig = mcpConfig[targetServer];
336
414
 
337
415
  // Connect to MCP server
338
416
  let client: McpClient;
@@ -346,17 +424,29 @@ The skill must be loaded first via the skill() tool to register its MCP config.`
346
424
  return JSON.stringify({ error: `Failed to connect: ${e.message}` });
347
425
  }
348
426
 
349
- // List tools
427
+ // List tools (filtered by includeTools if configured)
350
428
  if (list_tools) {
429
+ const totalTools = client.capabilities?.tools?.length || 0;
430
+ const filteredTools = client.filteredTools || [];
431
+ const isFiltered =
432
+ serverConfig.includeTools && serverConfig.includeTools.length > 0;
433
+
351
434
  return JSON.stringify(
352
435
  {
353
436
  mcp: targetServer,
354
- tools:
355
- client.capabilities?.tools?.map((t: any) => ({
356
- name: t.name,
357
- description: t.description,
358
- schema: t.inputSchema,
359
- })) || [],
437
+ tools: filteredTools.map((t: any) => ({
438
+ name: t.name,
439
+ description: t.description,
440
+ schema: t.inputSchema,
441
+ })),
442
+ ...(isFiltered && {
443
+ filtering: {
444
+ patterns: serverConfig.includeTools,
445
+ showing: filteredTools.length,
446
+ total: totalTools,
447
+ tokenSavings: `~${Math.round((1 - filteredTools.length / totalTools) * 100)}%`,
448
+ },
449
+ }),
360
450
  },
361
451
  null,
362
452
  2,
@@ -365,11 +455,28 @@ The skill must be loaded first via the skill() tool to register its MCP config.`
365
455
 
366
456
  // Call tool
367
457
  if (tool_name) {
458
+ // Validate tool is in filtered list (if filtering is enabled)
459
+ if (
460
+ serverConfig.includeTools &&
461
+ serverConfig.includeTools.length > 0
462
+ ) {
463
+ const isAllowed = client.filteredTools?.some(
464
+ (t: any) => t.name === tool_name,
465
+ );
466
+ if (!isAllowed) {
467
+ return JSON.stringify({
468
+ error: `Tool '${tool_name}' is not in includeTools filter`,
469
+ allowed: client.filteredTools?.map((t: any) => t.name) || [],
470
+ hint: "Add this tool to includeTools in mcp.json or YAML frontmatter",
471
+ });
472
+ }
473
+ }
474
+
368
475
  let toolArgs = {};
369
476
  if (argsJson) {
370
477
  try {
371
478
  toolArgs = JSON.parse(argsJson);
372
- } catch (e) {
479
+ } catch {
373
480
  return JSON.stringify({ error: "Invalid JSON in arguments" });
374
481
  }
375
482
  }
@@ -391,7 +498,7 @@ The skill must be loaded first via the skill() tool to register its MCP config.`
391
498
  error: "Specify either list_tools=true or tool_name to call",
392
499
  mcp: targetServer,
393
500
  available_tools:
394
- client.capabilities?.tools?.map((t: any) => t.name) || [],
501
+ client.filteredTools?.map((t: any) => t.name) || [],
395
502
  });
396
503
  },
397
504
  }),
@@ -403,11 +510,23 @@ The skill must be loaded first via the skill() tool to register its MCP config.`
403
510
  const servers: any[] = [];
404
511
  for (const [key, client] of state.clients) {
405
512
  const [skillName, serverName] = key.split(":");
513
+ const totalTools = client.capabilities?.tools?.length || 0;
514
+ const filteredTools = client.filteredTools?.length || 0;
515
+ const isFiltered =
516
+ client.config.includeTools &&
517
+ client.config.includeTools.length > 0;
518
+
406
519
  servers.push({
407
520
  skill: skillName,
408
521
  server: serverName,
409
522
  connected: !client.process.killed,
410
- tools: client.capabilities?.tools?.length || 0,
523
+ tools: filteredTools,
524
+ ...(isFiltered && {
525
+ filtering: {
526
+ total: totalTools,
527
+ filtered: filteredTools,
528
+ },
529
+ }),
411
530
  });
412
531
  }
413
532
  return JSON.stringify({
@@ -1,88 +1,66 @@
1
1
  ---
2
2
  name: chrome-devtools
3
3
  description: Chrome DevTools for debugging, performance analysis, and browser automation. Use when debugging web apps, analyzing performance, inspecting network requests, or automating browser interactions.
4
- mcp:
5
- chrome-devtools:
6
- command: npx
7
- args: ["-y", "chrome-devtools-mcp@latest", "--stdio"]
8
4
  ---
9
5
 
10
6
  # Chrome DevTools (MCP)
11
7
 
12
- Control and inspect a live Chrome browser via Chrome DevTools Protocol. Debug, analyze performance, inspect network, and automate browser interactions.
8
+ Control and inspect a live Chrome browser via Chrome DevTools Protocol.
13
9
 
14
- ## Quick Start
15
-
16
- ```
17
- skill_mcp(skill_name="chrome-devtools", tool_name="take_snapshot")
18
- skill_mcp(skill_name="chrome-devtools", tool_name="navigate_page", arguments='{"type": "url", "url": "https://example.com"}')
19
- ```
20
-
21
- ## Tools
22
-
23
- ### Input
10
+ ## Available Tools
24
11
 
25
- | Tool | Description | Parameters |
26
- | --------------- | -------------------- | ---------------------------- |
27
- | `click` | Click element | `uid` |
28
- | `fill` | Type text | `uid`, `value` |
29
- | `fill_form` | Fill multiple fields | `elements` array |
30
- | `hover` | Hover element | `uid` |
31
- | `press_key` | Press key | `key` (e.g., "Enter") |
32
- | `drag` | Drag element | `from_uid`, `to_uid` |
33
- | `upload_file` | Upload file | `uid`, `filePath` |
34
- | `handle_dialog` | Handle dialog | `action`: "accept"/"dismiss" |
12
+ - `take_snapshot` - Get accessibility tree snapshot with element UIDs
13
+ - `take_screenshot` - Capture screenshot of page or element
14
+ - `navigate_page` - Navigate to URL, back, forward, or reload
15
+ - `new_page` - Open a new browser tab
16
+ - `list_pages` - List all open pages/tabs
17
+ - `click` - Click element by UID
18
+ - `fill` - Type text into element
19
+ - `hover` - Hover over element
20
+ - `press_key` - Press keyboard key (Enter, Tab, etc.)
21
+ - `evaluate_script` - Run JavaScript in page context
22
+ - `wait_for` - Wait for text to appear
35
23
 
36
- ### Navigation
24
+ ## Workflow
37
25
 
38
- | Tool | Description | Parameters |
39
- | --------------- | ------------- | ---------------------------------------------- |
40
- | `navigate_page` | Navigate | `type`: "url"/"back"/"forward"/"reload", `url` |
41
- | `new_page` | Open new page | `url` |
42
- | `list_pages` | List pages | - |
43
- | `select_page` | Switch page | `pageIdx` |
44
- | `close_page` | Close page | `pageIdx` |
45
- | `wait_for` | Wait for text | `text`, `timeout` |
26
+ 1. **Snapshot** the page using `take_snapshot` to get element UIDs
27
+ 2. **Navigate** to target URL using `navigate_page`
28
+ 3. **Interact** using `click`, `fill`, `hover` with UIDs from snapshot
29
+ 4. **Screenshot** to capture results using `take_screenshot`
46
30
 
47
- ### Debugging
48
-
49
- | Tool | Description | Parameters |
50
- | ----------------------- | ------------------ | --------------------------- |
51
- | `take_snapshot` | A11y tree snapshot | `verbose` |
52
- | `take_screenshot` | Screenshot | `uid`, `fullPage`, `format` |
53
- | `evaluate_script` | Run JS | `function`, `args` |
54
- | `list_console_messages` | Console logs | `types` filter |
55
- | `get_console_message` | Get message | `msgid` |
56
-
57
- ### Network
31
+ ## Quick Start
58
32
 
59
- | Tool | Description | Parameters |
60
- | ----------------------- | --------------- | --------------------------- |
61
- | `list_network_requests` | List requests | `resourceTypes`, `pageSize` |
62
- | `get_network_request` | Request details | `reqid` |
33
+ ```
34
+ # Get page structure with element UIDs
35
+ skill_mcp(skill_name="chrome-devtools", tool_name="take_snapshot")
63
36
 
64
- ### Performance
37
+ # Navigate to URL
38
+ skill_mcp(skill_name="chrome-devtools", tool_name="navigate_page", arguments='{"type": "url", "url": "https://example.com"}')
65
39
 
66
- | Tool | Description | Parameters |
67
- | ----------------------------- | ----------- | ----------------------------- |
68
- | `performance_start_trace` | Start trace | `reload`, `autoStop` |
69
- | `performance_stop_trace` | Stop trace | - |
70
- | `performance_analyze_insight` | Analyze | `insightSetId`, `insightName` |
40
+ # Click element (use UID from snapshot)
41
+ skill_mcp(skill_name="chrome-devtools", tool_name="click", arguments='{"uid": "e123"}')
71
42
 
72
- ### Emulation
43
+ # Fill input field
44
+ skill_mcp(skill_name="chrome-devtools", tool_name="fill", arguments='{"uid": "e456", "value": "hello"}')
73
45
 
74
- | Tool | Description | Parameters |
75
- | ------------- | ------------------ | ---------------------------------------- |
76
- | `emulate` | Emulate conditions | `networkConditions`, `cpuThrottlingRate` |
77
- | `resize_page` | Resize viewport | `width`, `height` |
46
+ # Take screenshot
47
+ skill_mcp(skill_name="chrome-devtools", tool_name="take_screenshot")
48
+ ```
78
49
 
79
50
  ## Tips
80
51
 
81
- - **Always `take_snapshot` first** to get element `uid`s
82
- - **Element uids change** after navigation - take fresh snapshot
83
- - **Network conditions**: "Slow 3G", "Fast 3G", "Offline"
52
+ - **Always `take_snapshot` first** to get element UIDs
53
+ - **Element UIDs change** after navigation - take fresh snapshot
54
+ - **Use `wait_for`** after actions that trigger page changes
55
+ - **Use `evaluate_script`** for custom JS when tools don't cover your need
84
56
 
85
57
  ## vs Playwright
86
58
 
87
- - **chrome-devtools**: Performance profiling, network inspection, console - Chrome only
88
- - **playwright**: Cross-browser testing - Chrome, Firefox, WebKit
59
+ | Feature | chrome-devtools | playwright |
60
+ | ------------------- | -------------------- | ------------------ |
61
+ | Browser support | Chrome only | Chrome, FF, WebKit |
62
+ | Performance tracing | ✅ (full MCP has it) | ❌ |
63
+ | Network inspection | ✅ (full MCP has it) | ❌ |
64
+ | Cross-browser | ❌ | ✅ |
65
+
66
+ > **Note**: This skill loads 11 essential tools. For full 26+ tools (performance, network, console), modify `mcp.json` to remove `includeTools` filter.
@@ -0,0 +1,19 @@
1
+ {
2
+ "chrome-devtools": {
3
+ "command": "npx",
4
+ "args": ["-y", "chrome-devtools-mcp@latest", "--stdio"],
5
+ "includeTools": [
6
+ "take_snapshot",
7
+ "take_screenshot",
8
+ "navigate_page",
9
+ "new_page",
10
+ "list_pages",
11
+ "click",
12
+ "fill",
13
+ "hover",
14
+ "press_key",
15
+ "evaluate_script",
16
+ "wait_for"
17
+ ]
18
+ }
19
+ }
@@ -19,8 +19,38 @@ Load plan, review critically, execute tasks in batches, report for review betwee
19
19
 
20
20
  1. Read plan file
21
21
  2. Review critically - identify any questions or concerns about the plan
22
- 3. If concerns: Raise them with your human partner before starting
23
- 4. If no concerns: Create TodoWrite and proceed
22
+ 3. If concerns: Use question tool to raise them:
23
+
24
+ ```typescript
25
+ question({
26
+ questions: [
27
+ {
28
+ header: "Concerns",
29
+ question: "Plan review complete. Any concerns before proceeding?",
30
+ options: [
31
+ {
32
+ label: "No concerns (Recommended)",
33
+ description: "Plan looks good, execute batches",
34
+ },
35
+ {
36
+ label: "Has concerns",
37
+ description: "Need clarification before starting",
38
+ },
39
+ ],
40
+ },
41
+ ],
42
+ });
43
+ ```
44
+
45
+ 4. Read plan and identify:
46
+ - What is the goal?
47
+ - What are the deliverables?
48
+ - What are the risks?
49
+ - Does the approach make sense?
50
+ - Are there missing pieces?
51
+
52
+ If no concerns: Create TodoWrite and proceed
53
+ If concerns: Wait for human to decide and resubmit
24
54
 
25
55
  ### Step 2: Execute Batch
26
56