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
|
-
|
|
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
|
|
56
|
+
### 🚧 Eval-First Design - LLM-Optimized Features
|
|
19
57
|
|
|
20
|
-
These features
|
|
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
|
|
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
|
-
|
|
580
|
+
7. **⚡ Instant Iteration**: LLMs can adjust scripts based on results immediately - no need to wait for feature releases.
|
|
504
581
|
|
|
505
|
-
|
|
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.
|
|
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.
|
|
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
|
-
|
|
17
|
-
|
|
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
|
-
|
|
25
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
51
|
-
|
|
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
|
-
|
|
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.
|
|
4
|
-
"description": "
|
|
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": {
|