chrome-cdp-cli 1.2.2 → 1.2.4

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/README.md CHANGED
@@ -1,6 +1,44 @@
1
1
  # Chrome DevTools CLI
2
2
 
3
- A powerful command-line tool for controlling Chrome browser instances via the Chrome DevTools Protocol (CDP). This tool provides programmatic access to browser automation, debugging, and inspection capabilities without requiring a graphical interface.
3
+ **Built for LLMs - Eval-First Browser Automation**
4
+
5
+ A command-line tool designed specifically for Large Language Models (LLMs) and AI-assisted development. Controls Chrome browser via Chrome DevTools Protocol (CDP) with an **eval-first design philosophy** - most automation tasks use JavaScript execution because LLMs excel at writing and validating scripts quickly.
6
+
7
+ **Why eval-first?** LLMs are exceptional at writing JavaScript. This tool leverages that strength by using `eval` for most operations, enabling AI assistants (Claude, Cursor, etc.) to write automation scripts instantly and test them in real-time. Includes built-in IDE integrations: install Cursor commands and Claude skills directly.
8
+
9
+ ## 🚀 Built for LLMs - Eval-First Design Philosophy
10
+
11
+ **This tool is specifically designed for Large Language Models (LLMs) and AI-assisted development.**
12
+
13
+ ### Why Most Commands Use Eval
14
+
15
+ **The core design principle:** Most browser automation tasks are accomplished through the `eval` command rather than dedicated CLI commands. This is intentional and optimized for LLM workflows:
16
+
17
+ 1. **🧠 LLMs Excel at JavaScript**: Large Language Models are exceptionally good at writing JavaScript code. They can generate complex automation scripts, handle async operations, and adapt to different scenarios - all in JavaScript.
18
+
19
+ 2. **⚡ Rapid Script Validation**: LLMs can write a script, test it immediately with `eval`, see the results, and refine it in seconds. This iterative loop is where LLMs shine.
20
+
21
+ 3. **🔄 Maximum Flexibility**: Instead of waiting for specific commands to be implemented, LLMs can accomplish any browser task through JavaScript execution. Need to click an element? `document.querySelector('#btn').click()`. Need to wait for content? `await new Promise(...)`. Need complex data extraction? Just write the JavaScript.
22
+
23
+ 4. **🎯 Perfect for AI Workflows**: When you ask Claude or Cursor to automate a browser task, they can write the JavaScript directly - no need to learn complex CLI syntax or wait for feature implementations.
24
+
25
+ ### IDE Integration for LLM Workflows
26
+
27
+ **Built-in support for AI development environments:**
28
+
29
+ - **🖥️ Cursor Commands**: Install with `install-cursor-command` - brings browser automation directly into Cursor's command palette
30
+ - **🤖 Claude Skills**: Install with `install-claude-skill` - enables Claude to use browser automation in conversations
31
+ - **⚡ Seamless Integration**: AI assistants can generate automation scripts and execute them instantly through these integrations
32
+
33
+ **Why this matters:** When LLMs are integrated into your IDE, they can write browser automation scripts as part of your development workflow. The eval-first approach means they can accomplish any task without waiting for specific command implementations.
34
+
35
+ ### The LLM Advantage
36
+
37
+ - **🧠 Natural Language → JavaScript**: Ask an LLM "click the submit button" → it generates `document.querySelector('#submit').click()`
38
+ - **⚡ Instant Testing**: Write, execute, see results, refine - all in seconds
39
+ - **🔄 Iterative Refinement**: LLMs can adjust scripts based on results immediately
40
+ - **📚 Context-Aware**: AI understands your project and can write automation scripts that fit your specific needs
41
+ - **🎯 No Learning Curve**: LLMs already know JavaScript - no need to learn CLI-specific syntax
4
42
 
5
43
  ## Implementation Status
6
44
 
@@ -15,9 +53,9 @@ A powerful command-line tool for controlling Chrome browser instances via the Ch
15
53
  - 🛠️ **IDE Integration**: Install Cursor commands and Claude skills with directory validation and --force option
16
54
  - 📦 **Build System**: Complete TypeScript build pipeline with testing framework
17
55
 
18
- ### 🚧 Eval Workaround Available
56
+ ### 🚧 Eval-First Design - LLM-Optimized Features
19
57
 
20
- These features are not directly implemented but can be achieved using the `eval` command:
58
+ These features use the `eval` command by design (not as workarounds) - this is the intended approach for LLM-assisted development:
21
59
 
22
60
  - 📄 **Page Navigation**: `eval "window.location.href = 'https://example.com'"`
23
61
  - 🖱️ **Element Interaction**: `eval "document.querySelector('#btn').click()"`
@@ -27,6 +65,31 @@ These features are not directly implemented but can be achieved using the `eval`
27
65
  - 📱 **User Agent**: `eval "navigator.userAgent"`
28
66
  - 🌐 **Network Requests**: `eval "fetch('/api').then(r => r.json())"`
29
67
 
68
+ **Why this design is optimal for LLMs:**
69
+
70
+ 1. **LLMs are JavaScript experts**: They can write complex automation scripts instantly
71
+ 2. **Rapid validation**: Write → Execute → See Results → Refine - perfect for LLM workflows
72
+ 3. **No feature waiting**: LLMs can accomplish any task through JavaScript without waiting for CLI command implementations
73
+ 4. **Natural workflow**: When you ask an LLM to automate something, it writes JavaScript - exactly what `eval` executes
74
+ 5. **Maximum flexibility**: Any browser API, any complexity level, any scenario - all through JavaScript
75
+
76
+ **This is not a limitation - it's a feature designed specifically for AI-assisted development.**
77
+
78
+ ### 🎯 IDE Integration - Built for LLM Workflows
79
+
80
+ **Why we support Cursor Commands & Claude Skills:**
81
+
82
+ This tool is designed for LLM-assisted development. The IDE integrations (`install-cursor-command` and `install-claude-skill`) bring browser automation directly into AI-powered development environments:
83
+
84
+ - **🔄 Seamless LLM Workflow**: AI assistants can write and execute browser automation scripts directly in your IDE
85
+ - **🧠 AI-Native Design**: The eval-first approach means LLMs can accomplish any browser task through JavaScript
86
+ - **⚡ Instant Script Validation**: LLMs write JavaScript → execute via eval → see results → refine - all in real-time
87
+ - **📚 Context-Aware Automation**: AI understands your project context and can generate relevant automation scripts
88
+ - **🎯 Natural Language → Automation**: Ask "click the submit button" → AI generates `document.querySelector('#submit').click()` → executes instantly
89
+ - **🤖 Perfect for AI Assistants**: Claude and Cursor can use browser automation as part of their toolset
90
+
91
+ **The integration exists because this tool is built for LLMs - the eval-first design and IDE integrations work together to enable AI-powered browser automation.**
92
+
30
93
  ### ⏳ Not Yet Implemented
31
94
 
32
95
  - 📄 **Direct Page Management**: Native commands for creating, closing, listing, and selecting tabs
@@ -498,15 +561,25 @@ new Promise(resolve => {
498
561
  - Quiet and verbose modes
499
562
  - Custom output templates
500
563
 
501
- ### Why Use Eval Workarounds?
564
+ ### Why Eval-First Design? (Built for LLMs)
565
+
566
+ **This is not a workaround - it's the core design philosophy optimized for LLM workflows:**
567
+
568
+ 1. **🧠 LLMs are JavaScript Experts**: Large Language Models excel at writing JavaScript. They can generate complex automation scripts, handle async operations, and adapt to different scenarios - all naturally in JavaScript.
569
+
570
+ 2. **⚡ Rapid Script Validation**: The perfect workflow for LLMs: Write JavaScript → Execute via `eval` → See Results → Refine. This iterative loop is where LLMs shine.
571
+
572
+ 3. **🔄 Maximum Flexibility**: Any browser task, any complexity, any scenario - all through JavaScript. No waiting for specific command implementations.
573
+
574
+ 4. **🤖 AI-Native Workflow**: When you ask Claude or Cursor to automate something, they write JavaScript - exactly what `eval` executes. Perfect alignment.
575
+
576
+ 5. **📚 Natural Language → Automation**: "Click the submit button" → AI generates `document.querySelector('#submit').click()` → Executes instantly.
577
+
578
+ 6. **🎯 Context-Aware**: AI understands your project and can write automation scripts that fit your specific needs.
502
579
 
503
- The eval approach offers several advantages:
580
+ 7. **⚡ Instant Iteration**: LLMs can adjust scripts based on results immediately - no need to wait for feature releases.
504
581
 
505
- - **Immediate availability**: No waiting for feature implementation
506
- - **Maximum flexibility**: Any JavaScript operation is possible
507
- - **Learning opportunity**: Better understanding of browser APIs
508
- - **Custom solutions**: Tailor automation to specific needs
509
- - **Future-proof**: Works with any web technology
582
+ **This tool is built for LLM-assisted development. The eval-first approach, combined with IDE integrations (Cursor commands & Claude skills), creates a seamless workflow where AI assistants can automate browser tasks as part of your development process.**
510
583
 
511
584
  ## Configuration
512
585
 
@@ -87,7 +87,7 @@ class CommandRouter {
87
87
  case 'disconnect':
88
88
  return this.executeDisconnectCommand();
89
89
  case 'install_cursor_command':
90
- case 'install_claude_skill':
90
+ case 'install_claude_skill': {
91
91
  const handler = this.registry.get(command.name);
92
92
  if (!handler) {
93
93
  return {
@@ -97,6 +97,7 @@ class CommandRouter {
97
97
  };
98
98
  }
99
99
  return await handler.execute(null, command.args);
100
+ }
100
101
  default:
101
102
  return {
102
103
  success: false,
@@ -246,6 +247,10 @@ For more information about a specific command, use:
246
247
  'snapshot': 'Capture DOM snapshot with structure and styles',
247
248
  'console-messages': 'Get console messages',
248
249
  'network-requests': 'Get network requests',
250
+ 'get_console_message': 'Get the latest console message',
251
+ 'list_console_messages': 'List all console messages with filtering',
252
+ 'get_network_request': 'Get the latest network request',
253
+ 'list_network_requests': 'List all network requests with filtering',
249
254
  'install_cursor_command': 'Install Cursor IDE commands for Chrome automation',
250
255
  'install_claude_skill': 'Install Claude Code skill for Chrome automation',
251
256
  'help': 'Show help information'
@@ -69,7 +69,7 @@ Examples:
69
69
  }
70
70
  }
71
71
  }
72
- await this.ensureDirectory(skillDir);
72
+ await this.ensureSkillDirectoryPath(targetDir, skillDir);
73
73
  const skillConfig = this.generateClaudeSkill();
74
74
  const skillPath = path.join(skillDir, 'SKILL.md');
75
75
  await fs.writeFile(skillPath, this.generateSkillMarkdown(skillConfig), 'utf8');
@@ -123,6 +123,20 @@ Examples:
123
123
  logger_1.logger.info(`Created directory: ${dirPath}`);
124
124
  }
125
125
  }
126
+ async ensureSkillDirectoryPath(targetDir, skillDir) {
127
+ if (targetDir.includes('.claude/skills') || targetDir.endsWith('.claude/skills')) {
128
+ const claudeDir = targetDir.includes('.claude/skills')
129
+ ? targetDir.substring(0, targetDir.indexOf('.claude') + 7)
130
+ : path.dirname(targetDir);
131
+ await this.ensureDirectory(claudeDir);
132
+ const skillsDir = path.join(claudeDir, 'skills');
133
+ await this.ensureDirectory(skillsDir);
134
+ await this.ensureDirectory(skillDir);
135
+ }
136
+ else {
137
+ await this.ensureDirectory(skillDir);
138
+ }
139
+ }
126
140
  getDefaultSkillDirectory(skillType) {
127
141
  return skillType === 'personal'
128
142
  ? path.join(os.homedir(), '.claude', 'skills')
@@ -417,6 +431,65 @@ chrome-cdp-cli list_console_messages --type error > errors.log
417
431
  # Cleanup
418
432
  kill $CHROME_PID
419
433
  \`\`\`
434
+ `;
435
+ }
436
+ getHelp() {
437
+ return `
438
+ install-claude-skill - Install Claude Code skill for Chrome browser automation
439
+
440
+ Usage:
441
+ install-claude-skill
442
+ install-claude-skill --skill-type personal
443
+ install-claude-skill --target-directory /path/to/.claude/skills
444
+ install-claude-skill --include-examples --include-references
445
+
446
+ Arguments:
447
+ --skill-type <type> Installation type: 'project' or 'personal' (default: project)
448
+ --target-directory <path> Custom installation directory
449
+ --include-examples Include examples.md file with usage examples
450
+ --include-references Include reference.md file with detailed API documentation
451
+ --force Force installation without directory validation
452
+
453
+ Description:
454
+ Installs a Claude Code skill that provides Chrome browser automation capabilities
455
+ within Claude IDE. The skill enables Claude to help with:
456
+
457
+ • Browser automation and testing
458
+ • JavaScript execution and debugging
459
+ • Web scraping and data extraction
460
+ • UI testing and interaction
461
+ • Performance monitoring
462
+
463
+ Installation Types:
464
+ project - Install in current project (.claude/skills/cdp-cli/)
465
+ personal - Install in user home directory (~/.claude/skills/cdp-cli/)
466
+
467
+ Directory Validation:
468
+ For project installation, the command checks for a .claude directory to ensure
469
+ you're in a project root. Use --force to bypass this validation or
470
+ --target-directory to specify a custom location.
471
+
472
+ Examples:
473
+ # Install in current project (requires .claude directory)
474
+ install-claude-skill
475
+
476
+ # Install for personal use (in home directory)
477
+ install-claude-skill --skill-type personal
478
+
479
+ # Install with examples and references
480
+ install-claude-skill --include-examples --include-references
481
+
482
+ # Install with custom directory
483
+ install-claude-skill --target-directory /path/to/.claude/skills
484
+
485
+ # Force install without validation
486
+ install-claude-skill --force
487
+
488
+ Note:
489
+ The installed skill leverages the eval command approach, which is particularly
490
+ powerful for LLM-assisted development. Claude can write and test JavaScript
491
+ automation scripts dynamically, making it ideal for rapid prototyping and
492
+ complex browser automation tasks.
420
493
  `;
421
494
  }
422
495
  }
@@ -63,7 +63,7 @@ Examples:
63
63
  };
64
64
  }
65
65
  }
66
- await this.ensureDirectory(targetDir);
66
+ await this.ensureDirectoryPath(targetDir);
67
67
  const commands = this.generateCursorCommands();
68
68
  const createdFiles = [];
69
69
  for (const command of commands) {
@@ -109,6 +109,19 @@ Examples:
109
109
  logger_1.logger.info(`Created directory: ${dirPath}`);
110
110
  }
111
111
  }
112
+ async ensureDirectoryPath(targetPath) {
113
+ if (targetPath.includes('.cursor/commands') || targetPath.endsWith('.cursor/commands')) {
114
+ const cursorDir = targetPath.includes('.cursor/commands')
115
+ ? targetPath.substring(0, targetPath.indexOf('.cursor') + 7)
116
+ : path.dirname(targetPath);
117
+ await this.ensureDirectory(cursorDir);
118
+ const commandsDir = path.join(cursorDir, 'commands');
119
+ await this.ensureDirectory(commandsDir);
120
+ }
121
+ else {
122
+ await this.ensureDirectory(targetPath);
123
+ }
124
+ }
112
125
  generateCursorCommands() {
113
126
  return [
114
127
  {
@@ -274,6 +287,54 @@ chrome-cdp-cli snapshot --filename page-analysis.json
274
287
  # 3. 检查控制台错误
275
288
  chrome-cdp-cli list_console_messages --type error
276
289
  \`\`\`
290
+ `;
291
+ }
292
+ getHelp() {
293
+ return `
294
+ install-cursor-command - Install Cursor IDE commands for Chrome browser automation
295
+
296
+ Usage:
297
+ install-cursor-command
298
+ install-cursor-command --target-directory /path/to/.cursor/commands
299
+ install-cursor-command --force
300
+
301
+ Arguments:
302
+ --target-directory <path> Custom installation directory (default: .cursor/commands)
303
+ --include-examples Include example usage (default: true)
304
+ --force Force installation without directory validation
305
+
306
+ Description:
307
+ Installs a unified Cursor command file (cdp-cli.md) that provides Chrome browser
308
+ automation capabilities directly within Cursor IDE. The command includes:
309
+
310
+ • JavaScript execution in browser context
311
+ • Screenshot capture and DOM snapshots
312
+ • Console and network monitoring
313
+ • Complete automation workflows
314
+ • Comprehensive examples and documentation
315
+
316
+ Directory Validation:
317
+ By default, the command checks for a .cursor directory to ensure you're in a
318
+ Cursor project root. Use --force to bypass this validation or --target-directory
319
+ to specify a custom location.
320
+
321
+ Examples:
322
+ # Install in current project (requires .cursor directory)
323
+ install-cursor-command
324
+
325
+ # Install with custom directory
326
+ install-cursor-command --target-directory /path/to/.cursor/commands
327
+
328
+ # Force install without validation
329
+ install-cursor-command --force
330
+
331
+ # After installation, use in Cursor with:
332
+ /cdp-cli
333
+
334
+ Note:
335
+ The installed command provides powerful browser automation through the eval
336
+ approach, which is ideal for LLM-assisted development as it allows writing
337
+ and testing JavaScript automation scripts quickly and flexibly.
277
338
  `;
278
339
  }
279
340
  }
@@ -10,59 +10,131 @@ class TakeSnapshotHandler {
10
10
  async execute(client, args) {
11
11
  const snapshotArgs = args;
12
12
  try {
13
- await client.send('DOMSnapshot.enable');
14
13
  await client.send('DOM.enable');
15
14
  await client.send('CSS.enable');
16
- const params = this.buildSnapshotParams(snapshotArgs);
17
- const response = await client.send('DOMSnapshot.captureSnapshot', params);
18
- if (!response || !response.documents || response.documents.length === 0) {
19
- return {
20
- success: false,
21
- error: 'Failed to capture DOM snapshot: empty response'
22
- };
15
+ try {
16
+ return await this.captureWithDOMSnapshot(client, snapshotArgs);
23
17
  }
24
- const processedSnapshot = this.processSnapshot(response, snapshotArgs);
25
- if (snapshotArgs.filename) {
26
- await this.saveSnapshot(processedSnapshot, snapshotArgs.filename, snapshotArgs.format);
27
- return {
28
- success: true,
29
- data: {
30
- message: `DOM snapshot saved to ${snapshotArgs.filename}`,
31
- filename: snapshotArgs.filename,
32
- format: snapshotArgs.format || 'json',
33
- documentsCount: response.documents.length,
34
- nodesCount: response.documents[0]?.nodes?.nodeName?.length || 0
35
- }
36
- };
18
+ catch (domSnapshotError) {
19
+ return await this.captureWithDOM(client, snapshotArgs);
37
20
  }
21
+ }
22
+ catch (error) {
23
+ return {
24
+ success: false,
25
+ error: error instanceof Error ? error.message : String(error)
26
+ };
27
+ }
28
+ }
29
+ async captureWithDOMSnapshot(client, snapshotArgs) {
30
+ await client.send('DOMSnapshot.enable');
31
+ const params = this.buildSnapshotParams(snapshotArgs);
32
+ const response = await client.send('DOMSnapshot.captureSnapshot', params);
33
+ if (!response || !response.documents || response.documents.length === 0) {
34
+ throw new Error('Failed to capture DOM snapshot: empty response');
35
+ }
36
+ const processedSnapshot = this.processSnapshot(response, snapshotArgs);
37
+ if (snapshotArgs.filename) {
38
+ await this.saveSnapshot(processedSnapshot, snapshotArgs.filename, snapshotArgs.format);
38
39
  return {
39
40
  success: true,
40
41
  data: {
41
- snapshot: processedSnapshot,
42
+ message: `DOM snapshot saved to ${snapshotArgs.filename}`,
43
+ filename: snapshotArgs.filename,
42
44
  format: snapshotArgs.format || 'json',
43
45
  documentsCount: response.documents.length,
44
46
  nodesCount: response.documents[0]?.nodes?.nodeName?.length || 0
45
47
  }
46
48
  };
47
49
  }
48
- catch (error) {
50
+ return {
51
+ success: true,
52
+ data: {
53
+ snapshot: processedSnapshot,
54
+ format: snapshotArgs.format || 'json',
55
+ documentsCount: response.documents.length,
56
+ nodesCount: response.documents[0]?.nodes?.nodeName?.length || 0
57
+ }
58
+ };
59
+ }
60
+ async captureWithDOM(client, snapshotArgs) {
61
+ const docResponse = await client.send('DOM.getDocument', { depth: -1 });
62
+ if (!docResponse || !docResponse.root) {
63
+ throw new Error('Failed to get document root');
64
+ }
65
+ const htmlResponse = await client.send('DOM.getOuterHTML', {
66
+ nodeId: docResponse.root.nodeId
67
+ });
68
+ if (!htmlResponse || !htmlResponse.outerHTML) {
69
+ throw new Error('Failed to get document HTML');
70
+ }
71
+ let processedSnapshot;
72
+ if (snapshotArgs.format === 'html') {
73
+ processedSnapshot = htmlResponse.outerHTML;
74
+ }
75
+ else {
76
+ processedSnapshot = {
77
+ metadata: {
78
+ captureTime: new Date().toISOString(),
79
+ method: 'DOM.getOuterHTML',
80
+ documentsCount: 1
81
+ },
82
+ documents: [{
83
+ url: await this.getCurrentURL(client),
84
+ title: await this.getCurrentTitle(client),
85
+ html: htmlResponse.outerHTML,
86
+ domTree: docResponse.root
87
+ }]
88
+ };
89
+ }
90
+ if (snapshotArgs.filename) {
91
+ await this.saveSnapshot(processedSnapshot, snapshotArgs.filename, snapshotArgs.format);
49
92
  return {
50
- success: false,
51
- error: error instanceof Error ? error.message : String(error)
93
+ success: true,
94
+ data: {
95
+ message: `DOM snapshot saved to ${snapshotArgs.filename}`,
96
+ filename: snapshotArgs.filename,
97
+ format: snapshotArgs.format || 'json'
98
+ }
52
99
  };
53
100
  }
101
+ return {
102
+ success: true,
103
+ data: {
104
+ snapshot: processedSnapshot,
105
+ format: snapshotArgs.format || 'json'
106
+ }
107
+ };
108
+ }
109
+ async getCurrentURL(client) {
110
+ try {
111
+ const result = await client.send('Runtime.evaluate', {
112
+ expression: 'window.location.href',
113
+ returnByValue: true
114
+ });
115
+ return result.result?.value || 'unknown';
116
+ }
117
+ catch {
118
+ return 'unknown';
119
+ }
120
+ }
121
+ async getCurrentTitle(client) {
122
+ try {
123
+ const result = await client.send('Runtime.evaluate', {
124
+ expression: 'document.title',
125
+ returnByValue: true
126
+ });
127
+ return result.result?.value || 'unknown';
128
+ }
129
+ catch {
130
+ return 'unknown';
131
+ }
54
132
  }
55
133
  buildSnapshotParams(args) {
56
134
  const params = {};
57
- params.computedStyles = args.includeStyles !== false;
58
- params.includeDOMRects = args.includeAttributes !== false;
59
135
  if (args.includePaintOrder) {
60
- params.includePaintOrder = true;
61
- }
62
- if (args.includeTextIndex) {
63
- params.includeTextIndex = true;
136
+ console.log('Paint order requested but not yet supported');
64
137
  }
65
- params.computedStyleWhitelist = [];
66
138
  return params;
67
139
  }
68
140
  processSnapshot(response, args) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "chrome-cdp-cli",
3
- "version": "1.2.2",
4
- "description": "Command-line tool for controlling Chrome browser via Chrome DevTools Protocol. Features: JavaScript execution, screenshots, DOM snapshots, console/network monitoring, IDE integration (Cursor commands & Claude skills). Install IDE tools with --force option for directory validation bypass.",
3
+ "version": "1.2.4",
4
+ "description": "LLM-first browser automation CLI via Chrome DevTools Protocol. Designed specifically for AI assistants (LLMs) - most commands use eval because LLMs excel at writing JavaScript for rapid script validation. Features: JavaScript execution, screenshots, DOM snapshots, console/network monitoring. Built-in IDE integration: install Cursor commands and Claude skills directly. Perfect for LLM-assisted development workflows where AI writes and tests automation scripts instantly.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "bin": {