chrome-cdp-cli 1.7.5 → 1.7.7

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,41 +1,16 @@
1
1
  # Chrome DevTools CLI
2
2
 
3
+ A command-line tool for browser automation via Chrome DevTools Protocol (CDP). Designed for developers who need reliable, scriptable browser control with both dedicated commands and flexible JavaScript execution.
3
4
 
4
- 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.
5
+ ## šŸ¤” Why This Tool Exists
5
6
 
6
- ## šŸš€ Built for LLMs - Eval-First Design Philosophy
7
+ **The honest story:** I started using `chrome-devtools-mcp` like everyone else. It worked great... until it didn't. One day it just stopped working - Cursor showed 26 tools available, everything looked normal, but every single tool call threw errors. Classic black box problem: you can't debug what you can't see inside.
7
8
 
8
- **This tool is specifically designed for Large Language Models (LLMs) and AI-assisted development.**
9
+ **The MCP reality check:** Model Context Protocol sounded promising, but let's be real - it's not exactly taking the world by storm. Meanwhile, Anthropic introduced the SKILL concept, which actually makes sense for how LLMs work. And what pairs perfectly with Skills? Good old-fashioned command-line tools. They're debuggable, efficient, and you can actually see what's happening when things go wrong.
9
10
 
10
- ### Why Most Commands Use Eval
11
+ **The pragmatic solution:** Instead of wrestling with mysterious MCP failures, why not build a CLI that just works? One that you can debug, extend, and actually understand. Plus, when your AI assistant needs to automate a browser, it can just write the command and execute it - no black boxes, no mysterious failures, just straightforward automation.
11
12
 
12
- **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:
13
-
14
- 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.
15
-
16
- 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.
17
-
18
- 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.
19
-
20
- 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.
21
-
22
- ### IDE Integration for LLM Workflows
23
-
24
- **Built-in support for AI development environments:**
25
-
26
- - **šŸ–„ļø Cursor Commands**: Install with `install-cursor-command` - brings browser automation directly into Cursor's command palette
27
- - **šŸ¤– Claude Skills**: Install with `install-claude-skill` - enables Claude to use browser automation in conversations
28
- - **⚔ Seamless Integration**: AI assistants can generate automation scripts and execute them instantly through these integrations
29
-
30
- **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.
31
-
32
- ### The LLM Advantage
33
-
34
- - **🧠 Natural Language → JavaScript**: Ask an LLM "click the submit button" → it generates `document.querySelector('#submit').click()`
35
- - **⚔ Instant Testing**: Write, execute, see results, refine - all in seconds
36
- - **šŸ”„ Iterative Refinement**: LLMs can adjust scripts based on results immediately
37
- - **šŸ“š Context-Aware**: AI understands your project and can write automation scripts that fit your specific needs
38
- - **šŸŽÆ No Learning Curve**: LLMs already know JavaScript - no need to learn CLI-specific syntax
13
+ **The result:** A tool that's both powerful enough for complex automation and simple enough that you (and your AI assistant) can actually use it without pulling your hair out.
39
14
 
40
15
  ## Implementation Status
41
16
 
@@ -51,39 +26,39 @@ A command-line tool designed specifically for Large Language Models (LLMs) and A
51
26
  - šŸ› ļø **IDE Integration**: Install Cursor commands and Claude skills with directory validation and --force option
52
27
  - šŸ“¦ **Build System**: Complete TypeScript build pipeline with testing framework
53
28
 
54
- ### 🚧 Eval-First Design - LLM-Optimized Features
29
+ ### 🚧 Available via JavaScript Execution
55
30
 
56
- These features use the `eval` command by design (not as workarounds) - this is the intended approach for LLM-assisted development:
31
+ For maximum flexibility, many advanced features are available through the `eval` command. This approach is particularly powerful for AI assistants and complex automation scenarios:
57
32
 
58
33
  - šŸ“„ **Page Navigation**: `eval "window.location.href = 'https://example.com'"`
59
34
  - šŸš€ **Performance Data**: `eval "performance.now()"` or `eval "performance.getEntriesByType('navigation')"`
60
35
  - šŸ“± **User Agent**: `eval "navigator.userAgent"`
61
36
  - 🌐 **Network Requests**: `eval "fetch('/api').then(r => r.json())"`
62
37
 
63
- **Why this design is optimal for LLMs:**
38
+ **Why JavaScript execution is powerful:**
64
39
 
65
- 1. **LLMs are JavaScript experts**: They can write complex automation scripts instantly
66
- 2. **Rapid validation**: Write → Execute → See Results → Refine - perfect for LLM workflows
67
- 3. **No feature waiting**: LLMs can accomplish any task through JavaScript without waiting for CLI command implementations
68
- 4. **Natural workflow**: When you ask an LLM to automate something, it writes JavaScript - exactly what `eval` executes
69
- 5. **Maximum flexibility**: Any browser API, any complexity level, any scenario - all through JavaScript
40
+ 1. **Universal capability**: Any browser API, any complexity level, any scenario
41
+ 2. **Rapid prototyping**: Write → Execute → See Results → Refine
42
+ 3. **AI-friendly**: Perfect for AI assistants that excel at JavaScript
43
+ 4. **No waiting**: Accomplish tasks immediately without waiting for feature implementations
44
+ 5. **Maximum flexibility**: Handle edge cases and custom scenarios easily
70
45
 
71
- **This is not a limitation - it's a feature designed specifically for AI-assisted development.**
46
+ **This provides both dedicated commands for common tasks and unlimited flexibility through JavaScript execution.**
72
47
 
73
- ### šŸŽÆ IDE Integration - Built for LLM Workflows
48
+ ### šŸŽÆ IDE Integration - Built for Modern Development
74
49
 
75
50
  **Why we support Cursor Commands & Claude Skills:**
76
51
 
77
- 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:
52
+ This tool integrates seamlessly with modern AI-powered development environments. The IDE integrations (`install-cursor-command` and `install-claude-skill`) bring browser automation directly into your workflow:
78
53
 
79
- - **šŸ”„ Seamless LLM Workflow**: AI assistants can write and execute browser automation scripts directly in your IDE
80
- - **🧠 AI-Native Design**: The eval-first approach means LLMs can accomplish any browser task through JavaScript
81
- - **⚔ Instant Script Validation**: LLMs write JavaScript → execute via eval → see results → refine - all in real-time
82
- - **šŸ“š Context-Aware Automation**: AI understands your project context and can generate relevant automation scripts
83
- - **šŸŽÆ Natural Language → Automation**: Ask "click the submit button" → AI generates `document.querySelector('#submit').click()` → executes instantly
54
+ - **šŸ”„ Seamless Workflow**: AI assistants can write and execute browser automation scripts directly in your IDE
55
+ - **🧠 Natural Integration**: JavaScript execution means AI can accomplish any browser task
56
+ - **⚔ Instant Execution**: Write scripts → execute via commands → see results → refine in real-time
57
+ - **šŸ“š Context-Aware**: AI understands your project context and generates relevant automation
58
+ - **šŸŽÆ Natural Language → Automation**: Ask "click the submit button" → AI generates and executes the solution
84
59
  - **šŸ¤– Perfect for AI Assistants**: Claude and Cursor can use browser automation as part of their toolset
85
60
 
86
- **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.**
61
+ **The integration exists because modern development is AI-assisted - these tools work together to enable efficient browser automation.**
87
62
 
88
63
  ### ā³ Not Yet Implemented
89
64
 
@@ -144,19 +119,29 @@ npm link
144
119
  Before using the CLI, start Chrome with remote debugging enabled:
145
120
 
146
121
  ```bash
147
- # Default port (9222)
148
- chrome --remote-debugging-port=9222
122
+ # Default port (9222) - IMPORTANT: Include --user-data-dir to avoid conflicts
123
+ chrome --remote-debugging-port=9222 --user-data-dir=/tmp/chrome-debug-profile
149
124
 
150
125
  # Custom port
151
- chrome --remote-debugging-port=9223
126
+ chrome --remote-debugging-port=9223 --user-data-dir=/tmp/chrome-debug-profile
152
127
 
153
128
  # Headless mode
154
- chrome --headless --remote-debugging-port=9222
129
+ chrome --headless --remote-debugging-port=9222 --user-data-dir=/tmp/chrome-debug-profile
155
130
 
156
131
  # With additional flags for automation
157
- chrome --remote-debugging-port=9222 --no-first-run --no-default-browser-check
132
+ chrome --remote-debugging-port=9222 --user-data-dir=/tmp/chrome-debug-profile --no-first-run --no-default-browser-check
133
+
134
+ # macOS example with full path and logging
135
+ /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222 --user-data-dir=/Users/$USER/chrome-profile-debug > /tmp/chrome.log 2>&1 &
158
136
  ```
159
137
 
138
+ **Important Notes:**
139
+ - **Always use `--user-data-dir`**: This creates a separate Chrome profile for debugging and prevents conflicts with your regular Chrome instance
140
+ - **Choose a dedicated directory**: Use a path like `/tmp/chrome-debug-profile` or `/Users/$USER/chrome-profile-debug`
141
+ - **Avoid profile conflicts**: Without `--user-data-dir`, Chrome may fail to open the debugging port if another instance is running
142
+
143
+ For more details, see the [Chrome Remote Debugging documentation](https://developer.chrome.com/blog/remote-debugging-port).
144
+
160
145
  ## Quick Start
161
146
 
162
147
  ```bash
@@ -437,7 +422,7 @@ chrome-cdp-cli install_cursor_command --force
437
422
  chrome-cdp-cli install_claude_skill --force
438
423
  ```
439
424
 
440
- ### 🚧 Available via Eval Workarounds
425
+ ### 🚧 Available via JavaScript Execution
441
426
 
442
427
  #### Page Management
443
428
  ```bash
@@ -464,7 +449,7 @@ chrome-cdp-cli click "#button"
464
449
  chrome-cdp-cli hover ".menu-item"
465
450
  chrome-cdp-cli fill "#email" "user@example.com"
466
451
 
467
- # Via eval (still available for complex scenarios)
452
+ # Via JavaScript execution (flexible for complex scenarios)
468
453
  chrome-cdp-cli eval "document.querySelector('#button').click()"
469
454
  chrome-cdp-cli eval "document.querySelector('.menu-item').dispatchEvent(new MouseEvent('mouseover'))"
470
455
  chrome-cdp-cli eval "document.querySelector('#email').value = 'user@example.com'"
@@ -492,7 +477,7 @@ chrome-cdp-cli fill_form --fields '[
492
477
  chrome-cdp-cli fill "#name" "John Doe"
493
478
  chrome-cdp-cli fill "#email" "john@example.com"
494
479
 
495
- # Via eval (for complex form operations)
480
+ # Via JavaScript execution (for complex form operations)
496
481
  chrome-cdp-cli eval "
497
482
  document.querySelector('#name').value = 'John Doe';
498
483
  document.querySelector('#email').value = 'john@example.com';
@@ -505,7 +490,7 @@ chrome-cdp-cli eval "document.querySelector('#myform').submit()"
505
490
  # Select dropdown option (native)
506
491
  chrome-cdp-cli fill "#dropdown" "option1"
507
492
 
508
- # Select dropdown option (via eval)
493
+ # Select dropdown option (via JavaScript execution)
509
494
  chrome-cdp-cli eval "document.querySelector('#dropdown').value = 'option1'"
510
495
 
511
496
  # Check checkbox
@@ -690,25 +675,25 @@ new Promise(resolve => {
690
675
  - Quiet and verbose modes
691
676
  - Custom output templates
692
677
 
693
- ### Why Eval-First Design? (Built for LLMs)
678
+ ### Why JavaScript Execution? (Built for Modern Development)
694
679
 
695
- **This is not a workaround - it's the core design philosophy optimized for LLM workflows:**
680
+ **This is not a workaround - it's a core design philosophy optimized for modern development workflows:**
696
681
 
697
- 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.
682
+ 1. **🧠 Universal Language**: JavaScript is the language of the web. Developers and AI assistants alike excel at writing JavaScript for browser automation.
698
683
 
699
- 2. **⚔ Rapid Script Validation**: The perfect workflow for LLMs: Write JavaScript → Execute via `eval` → See Results → Refine. This iterative loop is where LLMs shine.
684
+ 2. **⚔ Rapid Prototyping**: The perfect workflow: Write JavaScript → Execute → See Results → Refine. This iterative loop is ideal for both human developers and AI assistants.
700
685
 
701
686
  3. **šŸ”„ Maximum Flexibility**: Any browser task, any complexity, any scenario - all through JavaScript. No waiting for specific command implementations.
702
687
 
703
- 4. **šŸ¤– AI-Native Workflow**: When you ask Claude or Cursor to automate something, they write JavaScript - exactly what `eval` executes. Perfect alignment.
688
+ 4. **šŸ¤– AI-Native Workflow**: When you ask Claude or Cursor to automate something, they naturally write JavaScript - exactly what the `eval` command executes.
704
689
 
705
690
  5. **šŸ“š Natural Language → Automation**: "Click the submit button" → AI generates `document.querySelector('#submit').click()` → Executes instantly.
706
691
 
707
692
  6. **šŸŽÆ Context-Aware**: AI understands your project and can write automation scripts that fit your specific needs.
708
693
 
709
- 7. **⚔ Instant Iteration**: LLMs can adjust scripts based on results immediately - no need to wait for feature releases.
694
+ 7. **⚔ Instant Iteration**: Both developers and AI can adjust scripts based on results immediately - no need to wait for feature releases.
710
695
 
711
- **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.**
696
+ **This tool bridges the gap between dedicated commands for common tasks and unlimited flexibility through JavaScript execution, making it perfect for both traditional development and AI-assisted workflows.**
712
697
 
713
698
  ## Form Filling & Element Interaction
714
699
 
@@ -1044,18 +1029,26 @@ console.log(result);
1044
1029
  ### Common Issues
1045
1030
 
1046
1031
  1. **Connection Refused**
1047
- - Ensure Chrome is running with `--remote-debugging-port=9222`
1032
+ - Ensure Chrome is running with `--remote-debugging-port=9222 --user-data-dir=/tmp/chrome-debug`
1033
+ - **Always include `--user-data-dir`** to avoid profile conflicts
1048
1034
  - Check if the port is correct and not blocked by firewall
1035
+ - Verify no other Chrome instances are using the same debugging port
1036
+
1037
+ 2. **Chrome Won't Start Debugging Port**
1038
+ - **Most common cause**: Missing `--user-data-dir` parameter
1039
+ - **Solution**: Use a dedicated profile directory: `--user-data-dir=/tmp/chrome-debug-profile`
1040
+ - **Why needed**: Prevents conflicts with existing Chrome instances
1041
+ - See [Chrome Remote Debugging documentation](https://developer.chrome.com/blog/remote-debugging-port) for details
1049
1042
 
1050
- 2. **Command Timeout**
1043
+ 3. **Command Timeout**
1051
1044
  - Increase timeout with `--timeout` option
1052
1045
  - Check if the page is responsive
1053
1046
 
1054
- 3. **Element Not Found**
1047
+ 4. **Element Not Found**
1055
1048
  - Verify CSS selectors are correct
1056
1049
  - Use `wait_for` command to wait for dynamic elements
1057
1050
 
1058
- 4. **Permission Denied**
1051
+ 5. **Permission Denied**
1059
1052
  - Ensure Chrome has necessary permissions
1060
1053
  - Check file system permissions for screenshot output
1061
1054
 
@@ -1077,31 +1070,6 @@ npm run package
1077
1070
  npm run prepublishOnly
1078
1071
  ```
1079
1072
 
1080
- ## Publishing to npm
1081
-
1082
- To make this tool available via `npx`, you need to publish it to npm:
1083
-
1084
- ```bash
1085
- # 1. Login to npm (one time setup)
1086
- npm login
1087
-
1088
- # 2. Publish the package
1089
- npm publish
1090
-
1091
- # 3. Users can then use it with npx
1092
- npx chrome-cdp-cli eval "document.title"
1093
- ```
1094
-
1095
- **Note**: The package name `chrome-cdp-cli` uses a clean, descriptive approach. This approach:
1096
-
1097
- - āœ… **Professional naming** that clearly indicates Chrome DevTools Protocol CLI
1098
- - āœ… **Works with npx**: `npx chrome-cdp-cli eval "document.title"`
1099
- - āœ… **Simple installation**: `npm install -g chrome-cdp-cli`
1100
- - āœ… **Short and memorable** compared to longer alternatives
1101
-
1102
- Alternative naming examples:
1103
- 1. **Scoped name**: `@nickxiao42/chrome-devtools-cli`
1104
- 2. **Longer descriptive**: `chrome-automation-cli`
1105
1073
 
1106
1074
  ## Contributing
1107
1075
 
@@ -35,28 +35,45 @@ class CLIApplication {
35
35
  this.cli.registerHandler(new handlers_1.WaitForHandler());
36
36
  this.cli.registerHandler(new handlers_1.HandleDialogHandler());
37
37
  }
38
+ configureDebugMode(debug) {
39
+ const registry = this.cli.getRegistry();
40
+ const handlerNames = registry.getCommandNames();
41
+ for (const handlerName of handlerNames) {
42
+ const handler = registry.get(handlerName);
43
+ if (handler && typeof handler.setDebug === 'function') {
44
+ handler.setDebug(debug);
45
+ }
46
+ }
47
+ }
38
48
  async run(argv) {
39
49
  try {
40
- console.log('[DEBUG] CLIApplication.run called with argv:', argv);
41
50
  const command = this.cli.parseArgs(argv);
42
- console.log('[DEBUG] Parsed command:', command);
51
+ if (command.config.debug) {
52
+ this.logger.setLevel(3);
53
+ }
54
+ else {
55
+ this.logger.setLevel(2);
56
+ }
57
+ this.configureDebugMode(command.config.debug);
58
+ this.logger.debug('CLIApplication.run called with argv:', argv);
59
+ this.logger.debug('Parsed command:', command);
43
60
  if (command.config.verbose) {
44
61
  this.proxyManager.setLogging(true);
45
62
  }
46
- console.log('[DEBUG] Ensuring proxy is ready...');
63
+ this.logger.debug('Ensuring proxy is ready...');
47
64
  await this.ensureProxyReady();
48
65
  if (this.needsConnection(command.name)) {
49
- console.log('[DEBUG] Command needs connection, ensuring connection...');
66
+ this.logger.debug('Command needs connection, ensuring connection...');
50
67
  await this.ensureConnection(command);
51
68
  }
52
- console.log('[DEBUG] Executing command via CLI interface...');
69
+ this.logger.debug('Executing command via CLI interface...');
53
70
  const result = await this.cli.execute(command);
54
- console.log('[DEBUG] Command execution result:', result);
71
+ this.logger.debug('Command execution result:', result);
55
72
  this.outputResult(result, command);
56
73
  return result.exitCode || (result.success ? CommandRouter_1.ExitCode.SUCCESS : CommandRouter_1.ExitCode.GENERAL_ERROR);
57
74
  }
58
75
  catch (error) {
59
- console.log('[DEBUG] Error in CLIApplication.run:', error);
76
+ this.logger.debug('Error in CLIApplication.run:', error);
60
77
  const errorMessage = error instanceof Error ? error.message : String(error);
61
78
  console.error(`Error: ${errorMessage}`);
62
79
  return CommandRouter_1.ExitCode.GENERAL_ERROR;
@@ -61,6 +61,7 @@ class CLIInterface {
61
61
  .option('-v, --verbose', 'Enable verbose logging', CLIInterface_1.DEFAULT_CLI_CONFIG.verbose)
62
62
  .option('-q, --quiet', 'Enable quiet mode', CLIInterface_1.DEFAULT_CLI_CONFIG.quiet)
63
63
  .option('-t, --timeout <timeout>', 'Command timeout in milliseconds', (value) => parseInt(value, 10), CLIInterface_1.DEFAULT_CLI_CONFIG.timeout)
64
+ .option('-d, --debug', 'Enable debug logging', CLIInterface_1.DEFAULT_CLI_CONFIG.debug)
64
65
  .option('-c, --config <config>', 'Configuration file path');
65
66
  }
66
67
  parseArgs(argv) {
@@ -77,7 +78,12 @@ class CLIInterface {
77
78
  const arg = args[i];
78
79
  if (arg.startsWith('--')) {
79
80
  const optionName = arg.substring(2);
80
- if (i + 1 < args.length && !args[i + 1].startsWith('-')) {
81
+ const booleanFlags = ['verbose', 'quiet', 'debug'];
82
+ if (booleanFlags.includes(optionName)) {
83
+ options[optionName] = true;
84
+ i++;
85
+ }
86
+ else if (i + 1 < args.length && !args[i + 1].startsWith('-')) {
81
87
  options[optionName] = args[i + 1];
82
88
  i += 2;
83
89
  }
@@ -88,7 +94,12 @@ class CLIInterface {
88
94
  }
89
95
  else if (arg.startsWith('-') && arg.length > 1) {
90
96
  const shortOption = arg.substring(1);
91
- if (i + 1 < args.length && !args[i + 1].startsWith('-')) {
97
+ const booleanShortFlags = ['v', 'q', 'd'];
98
+ if (booleanShortFlags.includes(shortOption)) {
99
+ options[shortOption] = true;
100
+ i++;
101
+ }
102
+ else if (i + 1 < args.length && !args[i + 1].startsWith('-')) {
92
103
  options[shortOption] = args[i + 1];
93
104
  i += 2;
94
105
  }
@@ -114,6 +125,8 @@ class CLIInterface {
114
125
  options.quiet = true;
115
126
  if (options.t)
116
127
  options.timeout = parseInt(options.t, 10);
128
+ if (options.d)
129
+ options.debug = true;
117
130
  if (options.c)
118
131
  options.config = options.c;
119
132
  if (options.port && typeof options.port === 'string') {
@@ -163,7 +176,8 @@ class CLIInterface {
163
176
  outputFormat: cliOptions.format || fileConfig.outputFormat || CLIInterface_1.DEFAULT_CLI_CONFIG.outputFormat,
164
177
  verbose: cliOptions.verbose || fileConfig.verbose || CLIInterface_1.DEFAULT_CLI_CONFIG.verbose,
165
178
  quiet: cliOptions.quiet || fileConfig.quiet || CLIInterface_1.DEFAULT_CLI_CONFIG.quiet,
166
- timeout: cliOptions.timeout || fileConfig.timeout || CLIInterface_1.DEFAULT_CLI_CONFIG.timeout
179
+ timeout: cliOptions.timeout || fileConfig.timeout || CLIInterface_1.DEFAULT_CLI_CONFIG.timeout,
180
+ debug: cliOptions.debug || fileConfig.debug || CLIInterface_1.DEFAULT_CLI_CONFIG.debug
167
181
  };
168
182
  }
169
183
  loadConfigFile(configPath) {
@@ -199,6 +213,9 @@ class CLIInterface {
199
213
  if (config.timeout !== undefined && (typeof config.timeout !== 'number' || config.timeout < 1)) {
200
214
  throw new Error('Configuration "timeout" must be a positive number');
201
215
  }
216
+ if (config.debug !== undefined && typeof config.debug !== 'boolean') {
217
+ throw new Error('Configuration "debug" must be a boolean');
218
+ }
202
219
  }
203
220
  extractCommandArgs(command, args, options) {
204
221
  const commandArgs = {};
@@ -169,18 +169,24 @@ class CommandRouter {
169
169
  }
170
170
  async executeWithTimeout(handler, command) {
171
171
  const timeout = command.config.timeout;
172
- console.log(`[DEBUG] CommandRouter.executeWithTimeout called for command: ${command.name}, timeout: ${timeout}ms`);
172
+ if (command.config.debug) {
173
+ this.logger.setLevel(3);
174
+ }
175
+ else {
176
+ this.logger.setLevel(2);
177
+ }
178
+ this.logger.debug(`CommandRouter.executeWithTimeout called for command: ${command.name}, timeout: ${timeout}ms`);
173
179
  const timeoutPromise = new Promise((_, reject) => {
174
180
  setTimeout(() => {
175
- console.log(`[DEBUG] Command timeout reached for: ${command.name} after ${timeout}ms`);
181
+ this.logger.debug(`Command timeout reached for: ${command.name} after ${timeout}ms`);
176
182
  reject(new Error(`Command timeout after ${timeout}ms`));
177
183
  }, timeout);
178
184
  });
179
- console.log(`[DEBUG] Starting handler execution for: ${command.name}`);
185
+ this.logger.debug(`Starting handler execution for: ${command.name}`);
180
186
  const executionPromise = handler.execute(this.client, command.args);
181
187
  try {
182
188
  const result = await Promise.race([executionPromise, timeoutPromise]);
183
- console.log(`[DEBUG] Command completed successfully for: ${command.name}`);
189
+ this.logger.debug(`Command completed successfully for: ${command.name}`);
184
190
  if (!result || typeof result !== 'object') {
185
191
  return {
186
192
  success: false,
@@ -194,7 +200,7 @@ class CommandRouter {
194
200
  return result;
195
201
  }
196
202
  catch (error) {
197
- console.log(`[DEBUG] Command execution error for: ${command.name}:`, error);
203
+ this.logger.debug(`Command execution error for: ${command.name}:`, error);
198
204
  if (error instanceof Error && error.message.includes('timeout')) {
199
205
  return {
200
206
  success: false,
@@ -218,6 +224,7 @@ Global Options:
218
224
  -v, --verbose Enable verbose logging
219
225
  -q, --quiet Enable quiet mode
220
226
  -t, --timeout <ms> Command timeout in milliseconds (default: 30000)
227
+ -d, --debug Enable debug logging
221
228
  -c, --config <path> Configuration file path
222
229
  -V, --version Show version number
223
230
 
@@ -5,16 +5,32 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.EvaluateScriptHandler = void 0;
7
7
  const ProxyClient_1 = require("../client/ProxyClient");
8
+ const logger_1 = require("../utils/logger");
8
9
  const fs_1 = require("fs");
9
10
  const node_fetch_1 = __importDefault(require("node-fetch"));
10
11
  class EvaluateScriptHandler {
11
- constructor(useProxy = false) {
12
+ constructor(useProxy = false, debug = false) {
12
13
  this.name = 'eval';
13
14
  this.proxyClient = new ProxyClient_1.ProxyClient();
14
15
  this.useProxy = useProxy;
16
+ this.logger = new logger_1.Logger();
17
+ if (debug) {
18
+ this.logger.setLevel(3);
19
+ }
20
+ else {
21
+ this.logger.setLevel(2);
22
+ }
23
+ }
24
+ setDebug(debug) {
25
+ if (debug) {
26
+ this.logger.setLevel(3);
27
+ }
28
+ else {
29
+ this.logger.setLevel(2);
30
+ }
15
31
  }
16
32
  async execute(client, args) {
17
- console.log('[DEBUG] EvaluateScriptHandler.execute called with args:', args);
33
+ this.logger.debug('EvaluateScriptHandler.execute called with args:', args);
18
34
  const scriptArgs = args;
19
35
  if (!scriptArgs.expression && !scriptArgs.file) {
20
36
  return {
@@ -28,17 +44,17 @@ class EvaluateScriptHandler {
28
44
  error: 'Cannot specify both "expression" and "file" arguments'
29
45
  };
30
46
  }
31
- console.log('[DEBUG] Arguments validated, useProxy:', this.useProxy);
47
+ this.logger.debug('Arguments validated, useProxy:', this.useProxy);
32
48
  try {
33
49
  if (this.useProxy) {
34
- console.log('[DEBUG] Checking proxy availability...');
50
+ this.logger.debug('Checking proxy availability...');
35
51
  const proxyAvailable = await this.proxyClient.isProxyAvailable();
36
- console.log('[DEBUG] Proxy available:', proxyAvailable);
52
+ this.logger.debug('Proxy available:', proxyAvailable);
37
53
  if (proxyAvailable) {
38
54
  console.log('[INFO] Using proxy connection for script evaluation');
39
- console.log('[DEBUG] About to call executeWithProxy...');
55
+ this.logger.debug('About to call executeWithProxy...');
40
56
  const result = await this.executeWithProxy(scriptArgs);
41
- console.log('[DEBUG] executeWithProxy returned:', result);
57
+ this.logger.debug('executeWithProxy returned:', result);
42
58
  return result;
43
59
  }
44
60
  else {
@@ -49,12 +65,12 @@ class EvaluateScriptHandler {
49
65
  catch (error) {
50
66
  console.warn('[WARN] Proxy execution failed, falling back to direct CDP:', error instanceof Error ? error.message : error);
51
67
  }
52
- console.log('[DEBUG] Falling back to direct CDP');
68
+ this.logger.debug('Falling back to direct CDP');
53
69
  return await this.executeWithDirectCDP(client, scriptArgs);
54
70
  }
55
71
  async executeWithProxy(scriptArgs) {
56
72
  try {
57
- console.log('[DEBUG] Starting executeWithProxy');
73
+ this.logger.debug('Starting executeWithProxy');
58
74
  let expression;
59
75
  if (scriptArgs.file) {
60
76
  expression = await this.readScriptFile(scriptArgs.file);
@@ -62,10 +78,10 @@ class EvaluateScriptHandler {
62
78
  else {
63
79
  expression = scriptArgs.expression;
64
80
  }
65
- console.log('[DEBUG] Expression to execute:', expression.substring(0, 100));
66
- console.log('[DEBUG] Creating new proxy connection...');
81
+ this.logger.debug('Expression to execute:', expression.substring(0, 100));
82
+ this.logger.debug('Creating new proxy connection...');
67
83
  const connectionId = await this.proxyClient.connect('localhost', 9222);
68
- console.log(`[DEBUG] Created new proxy connection: ${connectionId}`);
84
+ this.logger.debug(`Created new proxy connection: ${connectionId}`);
69
85
  try {
70
86
  const result = await this.executeScriptThroughHTTP(connectionId, expression, scriptArgs);
71
87
  return {
@@ -78,7 +94,7 @@ class EvaluateScriptHandler {
78
94
  }
79
95
  }
80
96
  catch (error) {
81
- console.log('[DEBUG] Error in executeWithProxy:', error);
97
+ this.logger.debug('Error in executeWithProxy:', error);
82
98
  return {
83
99
  success: false,
84
100
  error: error instanceof Error ? error.message : String(error)
@@ -7,5 +7,6 @@ exports.DEFAULT_CLI_CONFIG = {
7
7
  outputFormat: 'text',
8
8
  verbose: false,
9
9
  quiet: false,
10
- timeout: 30000
10
+ timeout: 30000,
11
+ debug: false
11
12
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chrome-cdp-cli",
3
- "version": "1.7.5",
3
+ "version": "1.7.7",
4
4
  "description": "Browser automation CLI via Chrome DevTools Protocol. Designed for developers and AI assistants - combines dedicated commands for common tasks with flexible JavaScript execution for complex scenarios. Features: element interaction, screenshots, DOM snapshots, console/network monitoring. Built-in IDE integration for Cursor and Claude.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -35,7 +35,7 @@
35
35
  "prepublishOnly": "npm run test:ci && npm run build:prod",
36
36
  "prepack": "npm run build:prod",
37
37
  "verify": "npm run lint && npm run test:ci && npm run build:prod",
38
- "postinstall": "node -e \"console.log('\\nšŸŽ‰ chrome-cdp-cli installed successfully!\\n\\nšŸ“‹ Quick Start:\\n 1. Start Chrome with debugging: chrome --remote-debugging-port=9222\\n 2. Try: chrome-cdp-cli eval \\\"document.title\\\"\\n 3. Get help: chrome-cdp-cli --help\\n\\nšŸ”— More info: https://github.com/nicoster/chrome-devtools-cli\\n')\""
38
+ "postinstall": "node -e \"console.log('\\nšŸŽ‰ chrome-cdp-cli installed successfully!\\n\\nšŸ“‹ Quick Start:\\n 1. Start Chrome with debugging: chrome --remote-debugging-port=9222 --user-data-dir=/tmp/chrome-debug\\n 2. Try: chrome-cdp-cli eval \\\"document.title\\\"\\n 3. Get help: chrome-cdp-cli --help\\n\\nšŸ”— More info: https://github.com/nicoster/chrome-devtools-cli\\n')\""
39
39
  },
40
40
  "keywords": [
41
41
  "chrome",