electron-debug-skill 1.0.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 electron-debug
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,392 @@
1
+ # electron-debug
2
+
3
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4
+ [![Node.js 18+](https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen)](https://nodejs.org/)
5
+ [![skills.sh](https://img.shields.io/badge/skills.sh-electron--debug-33aadd)](https://skills.sh)
6
+
7
+ > Claude Code Skill for debugging Electron applications using Chrome DevTools Protocol (CDP)
8
+
9
+ [**中文文档**](README_zh.md) | [English](README.md)
10
+
11
+ ## Features
12
+
13
+ - **Daemon Mode** - Background process maintains CDP connection for continuous testing
14
+ - **Full CDP Support** - Console, Network, DOM, Screenshot, Element Click, etc.
15
+ - **AI-Assisted Diagnosis** - Auto-collect debugging info when describing issues
16
+ - **Flexible Port Configuration** - Custom debugging port support
17
+
18
+ ## Requirements
19
+
20
+ - Node.js 18+
21
+ - Claude Code
22
+
23
+ ## Installation
24
+
25
+ ### Option 1: via skills.sh (Recommended)
26
+
27
+ ```bash
28
+ npx skills add kvenLin/electron-debug@electron-debug
29
+ ```
30
+
31
+ ### Option 2: Manual Install
32
+
33
+ ```bash
34
+ # Clone the repo
35
+ git clone https://github.com/kvenLin/electron-debug.git
36
+ cd electron-debug
37
+
38
+ # Install dependencies
39
+ npm install
40
+ ```
41
+
42
+ ### Option 3: Development (Symlink)
43
+
44
+ ```bash
45
+ ln -s ~/path/to/electron-debug ~/.claude/skills/electron-debug
46
+ /reload-plugins
47
+ ```
48
+
49
+ ## Quick Start
50
+
51
+ ### 1. Start Electron App with Debug Port
52
+
53
+ ```bash
54
+ cd your-electron-app
55
+ electron . --remote-debugging-port=9333
56
+ ```
57
+
58
+ Or add to `package.json`:
59
+
60
+ ```json
61
+ {
62
+ "scripts": {
63
+ "debug": "electron . --remote-debugging-port=9333"
64
+ }
65
+ }
66
+ ```
67
+
68
+ ```bash
69
+ npm run debug
70
+ ```
71
+
72
+ ### 2. Connect
73
+
74
+ ```
75
+ /electron-debug connect --electron-port 9333
76
+ ```
77
+
78
+ ### 3. Debug
79
+
80
+ ```bash
81
+ # List pages
82
+ /electron-debug list-pages
83
+
84
+ # Screenshot
85
+ /electron-debug screenshot
86
+
87
+ # Click element
88
+ /electron-debug click "#my-button"
89
+
90
+ # Execute JavaScript
91
+ /electron-debug eval "document.title"
92
+
93
+ # View console
94
+ /electron-debug console
95
+
96
+ # AI diagnosis
97
+ /electron-debug diagnose "button click not working"
98
+ ```
99
+
100
+ ### 4. Disconnect
101
+
102
+ ```
103
+ /electron-debug disconnect
104
+ ```
105
+
106
+ ## Command Reference
107
+
108
+ ### Connection Management
109
+
110
+ | Command | Description |
111
+ |---------|-------------|
112
+ | `connect --electron-port <port>` | Start daemon and connect |
113
+ | `disconnect` | Disconnect and stop daemon |
114
+ | `status` | View connection status |
115
+
116
+ ### Daemon Management
117
+
118
+ | Command | Description |
119
+ |---------|-------------|
120
+ | `daemon start --electron-port <port>` | Start daemon |
121
+ | `daemon stop` | Stop daemon |
122
+ | `daemon status` | View daemon status |
123
+
124
+ ### Page Operations
125
+
126
+ | Command | Description |
127
+ |---------|-------------|
128
+ | `list-pages` | List all debuggable pages |
129
+ | `switch-page --id <id>` | Switch to another page |
130
+ | `screenshot` | Take screenshot (base64) |
131
+ | `screenshot --path ./screenshot.png` | Save screenshot to file |
132
+
133
+ ### Element Interaction
134
+
135
+ | Command | Description |
136
+ |---------|-------------|
137
+ | `click "#selector"` | Click element |
138
+ | `eval "javascript"` | Execute JavaScript expression |
139
+ | `dom --selector "#selector"` | Query DOM element |
140
+
141
+ ### Monitoring
142
+
143
+ | Command | Description |
144
+ |---------|-------------|
145
+ | `console` | View console logs |
146
+ | `console --watch` | Watch console messages |
147
+ | `network --watch` | Watch network requests |
148
+
149
+ ### Diagnosis
150
+
151
+ | Command | Description |
152
+ |---------|-------------|
153
+ | `diagnose "<problem>"` | AI-assisted diagnosis |
154
+
155
+ ## Daemon Mode
156
+
157
+ electron-debug uses a background daemon process to maintain CDP connection.
158
+
159
+ ### Architecture
160
+
161
+ ```
162
+ ┌─────────────────────────────────────────────────────────────┐
163
+ │ electron-debug-daemon (background, localhost:9229) │
164
+ │ - Maintains WebSocket CDP connection to Electron │
165
+ │ - Manages current active target/page │
166
+ └─────────────────────────────────────────────────────────────┘
167
+ ↑ HTTP (localhost:9229)
168
+
169
+ ┌─────────────────────────────────────────────────────────────┐
170
+ │ electron-debug CLI / Skill │
171
+ │ - Command line client, sends HTTP requests to daemon │
172
+ └─────────────────────────────────────────────────────────────┘
173
+ ```
174
+
175
+ ### Port Reference
176
+
177
+ | Port | Purpose |
178
+ |------|---------|
179
+ | 9229 | Daemon HTTP server (default) |
180
+ | 9333 | Electron CDP port (configurable) |
181
+
182
+ ## CLI Direct Usage
183
+
184
+ ```bash
185
+ # Start daemon
186
+ node bin/daemon.js --electron-port 9333
187
+
188
+ # API calls
189
+ curl http://127.0.0.1:9229/status
190
+ curl -X POST http://127.0.0.1:9229/eval -d '{"expression":"document.title"}'
191
+ curl -X POST http://127.0.0.1:9229/click -d '{"selector":"#btn1"}'
192
+ curl http://127.0.0.1:9229/screenshot -o screenshot.png
193
+
194
+ # Stop daemon
195
+ curl -X DELETE http://127.0.0.1:9229/
196
+ ```
197
+
198
+ ## HTTP API
199
+
200
+ | Method | Path | Description |
201
+ |--------|------|-------------|
202
+ | GET | `/status` | Get connection status |
203
+ | GET | `/targets` | List all pages |
204
+ | POST | `/connect` | Connect to Electron |
205
+ | POST | `/switch-target` | Switch page |
206
+ | POST | `/eval` | Execute JavaScript |
207
+ | GET | `/screenshot` | Get screenshot (PNG) |
208
+ | POST | `/screenshot` | Get screenshot (JSON) |
209
+ | POST | `/click` | Click element |
210
+ | GET | `/console` | Get console messages |
211
+ | POST | `/disconnect` | Disconnect |
212
+ | DELETE | `/` | Stop daemon |
213
+
214
+ ## Comparison with chrome-devtools-mcp
215
+
216
+ | Feature | chrome-devtools-mcp | electron-debug |
217
+ |---------|---------------------|----------------|
218
+ | Type | MCP Server | Claude Code Skill |
219
+ | Stateful Connection | Not supported | Daemon mode supported |
220
+ | Port Configuration | Fixed 9222 | Configurable |
221
+ | Element Click | Not supported | Supported |
222
+ | Main Process Debugging | Not supported | Supported |
223
+ | AI Diagnosis | None | AI-assisted |
224
+
225
+ ## Project Structure
226
+
227
+ ```
228
+ electron-debug/
229
+ ├── bin/
230
+ │ ├── cli.js # CLI client entry
231
+ │ └── daemon.js # Daemon service entry
232
+ ├── dist/ # Compiled JavaScript
233
+ ├── skills/
234
+ │ └── electron-debug/
235
+ │ └── SKILL.md # Claude Code Skill definition
236
+ ├── node_modules/ # Dependencies
237
+ ├── package.json
238
+ ├── README.md # English documentation
239
+ └── README_zh.md # Chinese documentation
240
+ ```
241
+
242
+ ## Troubleshooting
243
+
244
+ ### Connection Failed?
245
+
246
+ Make sure Electron is started with remote debugging:
247
+
248
+ ```bash
249
+ electron . --remote-debugging-port=9333
250
+ ```
251
+
252
+ ### Daemon Port Occupied?
253
+
254
+ ```bash
255
+ # Check port
256
+ lsof -i :9229
257
+
258
+ # Kill process
259
+ kill <PID>
260
+ ```
261
+
262
+ ### Screenshot Returns JSON Instead of Image?
263
+
264
+ Use `GET /screenshot` instead of `POST /screenshot`.
265
+
266
+ ### Cannot Find Skill After Install?
267
+
268
+ ```bash
269
+ # Check installed skills
270
+ npx skills list
271
+
272
+ # Reload plugins
273
+ /reload-plugins
274
+ ```
275
+
276
+ ### Permission Denied (npm install)?
277
+
278
+ ```bash
279
+ sudo npm install
280
+ # or
281
+ npm install --prefix ~/.local
282
+ ```
283
+
284
+ ## Quick Reference
285
+
286
+ | Task | Command |
287
+ |------|---------|
288
+ | Connect | `/electron-debug connect --electron-port 9333` |
289
+ | Screenshot | `/electron-debug screenshot` |
290
+ | Click | `/electron-debug click "#btn"` |
291
+ | Console | `/electron-debug console` |
292
+ | Diagnose | `/electron-debug diagnose "issue description"` |
293
+ | Disconnect | `/electron-debug disconnect` |
294
+
295
+ ## Everyday Examples (Colloquial)
296
+
297
+ ### Scenario 1: Debug button click not working
298
+
299
+ **User asks Claude:**
300
+ > "I clicked the submit button in my Electron app but nothing happened. Can you help me figure out why?"
301
+
302
+ **Claude dispatches skill tools automatically:**
303
+ 1. Connect to Electron: `/electron-debug connect --electron-port 9333`
304
+ 2. Take screenshot to see page state
305
+ 3. Click that button
306
+ 4. Take screenshot to compare before/after
307
+ 5. Check console for errors
308
+ 6. Inspect DOM to see button state
309
+ 7. AI diagnose possible causes
310
+
311
+ ---
312
+
313
+ ### Scenario 2: Troubleshoot white screen
314
+
315
+ **User asks Claude:**
316
+ > "My Electron app shows a white screen when it opens. Can you help me troubleshoot?"
317
+
318
+ **Claude dispatches skill tools automatically:**
319
+ 1. Connect to Electron
320
+ 2. Take screenshot to confirm white screen
321
+ 3. Execute JS to check `document.body.innerHTML` and see DOM tree
322
+ 4. Check console errors
323
+ 5. Check if network requests succeeded
324
+ 6. Provide diagnosis
325
+
326
+ ---
327
+
328
+ ### Scenario 3: Analyze page load performance
329
+
330
+ **User asks Claude:**
331
+ > "This Electron page loads really slowly. Can you help me figure out where it's getting stuck?"
332
+
333
+ **Claude dispatches skill tools automatically:**
334
+ 1. Connect to Electron
335
+ 2. Enable network monitoring: `/electron-debug network --watch`
336
+ 3. Refresh the page
337
+ 4. Analyze each request's duration
338
+ 5. Find the slowest request
339
+ 6. Provide optimization suggestions
340
+
341
+ ---
342
+
343
+ ### Scenario 4: Check form validation issues
344
+
345
+ **User asks Claude:**
346
+ > "I filled out the form but clicking submit does nothing. Is there a validation issue? Can you check?"
347
+
348
+ **Claude dispatches skill tools automatically:**
349
+ 1. Connect to Electron
350
+ 2. Execute `form.checkValidity()` to check form validation state
351
+ 3. Check each input's validity details
352
+ 4. Look for validation error logs in console
353
+ 5. Tell you which field is failing validation
354
+
355
+ ---
356
+
357
+ ### Scenario 5: Capture login requests
358
+
359
+ **User asks Claude:**
360
+ > "I want to see what requests are sent when this Electron app logs in. Can you capture the network traffic?"
361
+
362
+ **Claude dispatches skill tools automatically:**
363
+ 1. Connect to Electron
364
+ 2. Enable network monitoring
365
+ 3. User performs login operation on the page
366
+ 4. Analyze captured requests
367
+ 5. Display the login API's request parameters and response
368
+
369
+ ---
370
+
371
+ ### Scenario 6: Automated UI testing
372
+
373
+ **User asks Claude:**
374
+ > "Help me test the shopping cart: add the first 5 products to cart, then take a screenshot of the cart page"
375
+
376
+ **Claude dispatches skill tools automatically:**
377
+ 1. Connect to Electron
378
+ 2. Click "add to cart" for first product
379
+ 3. Take screenshot
380
+ 4. Click second product...
381
+ 5. Until fifth
382
+ 6. Screenshot the cart page
383
+ 7. Check cart badge count
384
+ 8. Disconnect
385
+
386
+ ## Contributing
387
+
388
+ Contributions are welcome! Please feel free to submit issues or pull requests.
389
+
390
+ ## License
391
+
392
+ MIT
package/bin/cli.js ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import '../dist/index.js';
package/bin/daemon.js ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import '../dist/daemon.js';
@@ -0,0 +1,258 @@
1
+ import WebSocket from 'ws';
2
+ export class CDPClient {
3
+ ws = null;
4
+ messageId = 0;
5
+ pendingRequests = new Map();
6
+ eventHandlers = new Map();
7
+ options;
8
+ constructor(options) {
9
+ this.options = { host: '127.0.0.1', secure: false, ...options };
10
+ }
11
+ async connect() {
12
+ const { host, port, secure } = this.options;
13
+ const protocol = secure ? 'wss' : 'ws';
14
+ return new Promise((resolve, reject) => {
15
+ this.ws = new WebSocket(`${protocol}://${host}:${port}`);
16
+ this.ws.on('open', () => resolve());
17
+ this.ws.on('error', reject);
18
+ this.ws.on('message', (data) => this.handleMessage(data.toString()));
19
+ });
20
+ }
21
+ // Connect directly to a target using its WebSocket URL
22
+ async connectToTarget(wsUrl) {
23
+ return new Promise((resolve, reject) => {
24
+ this.ws = new WebSocket(wsUrl);
25
+ this.ws.on('open', () => resolve());
26
+ this.ws.on('error', reject);
27
+ this.ws.on('message', (data) => this.handleMessage(data.toString()));
28
+ });
29
+ }
30
+ disconnect() {
31
+ if (this.ws) {
32
+ this.ws.close();
33
+ this.ws = null;
34
+ }
35
+ this.pendingRequests.clear();
36
+ }
37
+ isConnected() {
38
+ return this.ws?.readyState === WebSocket.OPEN;
39
+ }
40
+ async sendCommand(method, params) {
41
+ if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
42
+ throw new Error('WebSocket not connected');
43
+ }
44
+ const id = ++this.messageId;
45
+ return new Promise((resolve, reject) => {
46
+ this.pendingRequests.set(id, {
47
+ resolve: (value) => resolve(value),
48
+ reject,
49
+ });
50
+ this.ws.send(JSON.stringify({ id, method, params }));
51
+ });
52
+ }
53
+ on(event, handler) {
54
+ if (!this.eventHandlers.has(event)) {
55
+ this.eventHandlers.set(event, new Set());
56
+ }
57
+ this.eventHandlers.get(event).add(handler);
58
+ }
59
+ off(event, handler) {
60
+ this.eventHandlers.get(event)?.delete(handler);
61
+ }
62
+ handleMessage(data) {
63
+ const message = JSON.parse(data);
64
+ // Handle response
65
+ if ('id' in message) {
66
+ const pending = this.pendingRequests.get(message.id);
67
+ if (pending) {
68
+ this.pendingRequests.delete(message.id);
69
+ if (message.error) {
70
+ pending.reject(new Error(`${message.error.code}: ${message.error.message}`));
71
+ }
72
+ else {
73
+ pending.resolve(message.result);
74
+ }
75
+ }
76
+ return;
77
+ }
78
+ // Handle event
79
+ if ('method' in message) {
80
+ // Capture console messages for later retrieval
81
+ if (message.method === 'Console.messageAdded') {
82
+ // Console.messageAdded has nested "message" object: { message: { level, text, ... } }
83
+ const params = message.params;
84
+ this.consoleMessages.push({
85
+ type: (params.message?.level ?? params.message?.type ?? 'log'),
86
+ text: params.message?.text ?? '',
87
+ timestamp: Date.now(),
88
+ });
89
+ }
90
+ // Runtime.consoleAPICalled has direct params: { type, args: [{type, value}], ... }
91
+ if (message.method === 'Runtime.consoleAPICalled') {
92
+ const params = message.params;
93
+ const text = params.args
94
+ ?.map((a) => a.value ?? a.description ?? String(a))
95
+ .join(' ') ?? '';
96
+ this.consoleMessages.push({
97
+ type: (params.type ?? 'log'),
98
+ text,
99
+ timestamp: params.timestamp ?? Date.now(),
100
+ });
101
+ }
102
+ const handlers = this.eventHandlers.get(message.method);
103
+ if (handlers) {
104
+ handlers.forEach((handler) => handler(message.params));
105
+ }
106
+ }
107
+ }
108
+ // Target/Page management
109
+ async getTargets() {
110
+ const result = await this.sendCommand('Target.getTargets');
111
+ return result.targetInfos;
112
+ }
113
+ async attachToTarget(targetId) {
114
+ const result = await this.sendCommand('Target.attachToTarget', { targetId });
115
+ return result.sessionId;
116
+ }
117
+ // Page operations
118
+ async navigate(url) {
119
+ await this.sendCommand('Page.navigate', { url });
120
+ }
121
+ async captureScreenshot(format = 'png', quality) {
122
+ const result = await this.sendCommand('Page.captureScreenshot', {
123
+ format,
124
+ quality,
125
+ });
126
+ return { data: result.data, timestamp: Date.now() };
127
+ }
128
+ async captureFullScreenshot() {
129
+ const { data } = await this.sendCommand('Page.captureSnapshot');
130
+ return { data, timestamp: Date.now() };
131
+ }
132
+ async getPageInfo() {
133
+ const result = await this.sendCommand('Page.getLayoutMetrics');
134
+ return {
135
+ title: '',
136
+ url: '',
137
+ dimensions: {
138
+ width: result.contentSize?.width ?? 0,
139
+ height: result.contentSize?.height ?? 0,
140
+ },
141
+ };
142
+ }
143
+ // Console - store messages locally from events
144
+ consoleMessages = [];
145
+ async enableConsole() {
146
+ // Clear previous messages
147
+ this.consoleMessages = [];
148
+ await this.sendCommand('Console.enable');
149
+ }
150
+ async getConsoleMessages() {
151
+ return this.consoleMessages;
152
+ }
153
+ // Call this to retrieve buffered console messages (used internally after events)
154
+ addConsoleMessage(msg) {
155
+ this.consoleMessages.push(msg);
156
+ }
157
+ async enableRuntimeConsole() {
158
+ // Enable Runtime to capture console API calls
159
+ await this.sendCommand('Runtime.enable');
160
+ }
161
+ // Network
162
+ async enableNetwork() {
163
+ await this.sendCommand('Network.enable');
164
+ }
165
+ async disableNetwork() {
166
+ await this.sendCommand('Network.disable');
167
+ }
168
+ async getNetworkRequests() {
169
+ const result = await this.sendCommand('Network.getRequests');
170
+ const requests = new Map();
171
+ result.records.forEach((r) => requests.set(r.requestId, r));
172
+ return { requests, responses: new Map() };
173
+ }
174
+ async getResponseBody(requestId) {
175
+ const result = await this.sendCommand('Network.getResponseBody', { requestId });
176
+ return result.base64Encoded ? Buffer.from(result.body, 'base64').toString() : result.body;
177
+ }
178
+ // DOM
179
+ async getDocument() {
180
+ const result = await this.sendCommand('DOM.getDocument');
181
+ return result.root;
182
+ }
183
+ async querySelector(nodeId, selector) {
184
+ const result = await this.sendCommand('DOM.querySelector', {
185
+ nodeId,
186
+ selector,
187
+ });
188
+ return result ? result.nodeId : null;
189
+ }
190
+ async getOuterHTML(nodeId) {
191
+ const result = await this.sendCommand('DOM.getOuterHTML', { nodeId });
192
+ return result.outerHTML;
193
+ }
194
+ async getAttributes(nodeId) {
195
+ const result = await this.sendCommand('DOM.getAttributes', {
196
+ nodeId,
197
+ });
198
+ return result.attributes;
199
+ }
200
+ async resolveNode(nodeId) {
201
+ return this.sendCommand('DOM.resolveNode', { nodeId });
202
+ }
203
+ // Runtime
204
+ async evaluate(expression, returnByValue = true) {
205
+ const result = await this.sendCommand('Runtime.evaluate', {
206
+ expression,
207
+ returnByValue,
208
+ generatePreview: true,
209
+ });
210
+ return result.result.value ?? result.result;
211
+ }
212
+ async callFunctionOn(functionDeclaration, objectId) {
213
+ const result = await this.sendCommand('Runtime.callFunctionOn', {
214
+ functionDeclaration,
215
+ objectId,
216
+ });
217
+ return result.result.value;
218
+ }
219
+ async getProperties(objectId) {
220
+ const result = await this.sendCommand('Runtime.getProperties', { objectId });
221
+ return result.result.map((p) => ({ name: p.name, value: p.value.value }));
222
+ }
223
+ // Debugger
224
+ async enableDebugger() {
225
+ await this.sendCommand('Debugger.enable');
226
+ }
227
+ async setBreakpoint(url, lineNumber, columnNumber) {
228
+ const result = await this.sendCommand('Debugger.setBreakpointByUrl', {
229
+ lineNumber,
230
+ columnNumber,
231
+ url,
232
+ });
233
+ return result.breakpointId;
234
+ }
235
+ async listBreakpoints() {
236
+ const result = await this.sendCommand('Debugger.getBreakpoints');
237
+ return result.breakpoints;
238
+ }
239
+ async stepNext() {
240
+ await this.sendCommand('Debugger.stepNext');
241
+ }
242
+ async stepInto() {
243
+ await this.sendCommand('Debugger.stepInto');
244
+ }
245
+ async stepOut() {
246
+ await this.sendCommand('Debugger.stepOut');
247
+ }
248
+ async resume() {
249
+ await this.sendCommand('Debugger.resume');
250
+ }
251
+ // Log
252
+ async enableLog() {
253
+ await this.sendCommand('Log.enable');
254
+ }
255
+ async getLogEntries() {
256
+ return this.sendCommand('Log.getEntries');
257
+ }
258
+ }