chrome-devtools-mcp 0.17.3 → 0.18.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/README.md CHANGED
@@ -73,6 +73,21 @@ Add the following config to your MCP client:
73
73
  > [!NOTE]
74
74
  > Using `chrome-devtools-mcp@latest` ensures that your MCP client will always use the latest version of the Chrome DevTools MCP server.
75
75
 
76
+ If you are intersted in doing only basic browser tasks, use the `--slim` mode:
77
+
78
+ ```json
79
+ {
80
+ "mcpServers": {
81
+ "chrome-devtools": {
82
+ "command": "npx",
83
+ "args": ["-y", "chrome-devtools-mcp@latest", "--slim", "--headless"]
84
+ }
85
+ }
86
+ }
87
+ ```
88
+
89
+ See [Slim tool reference](./docs/slim-tool-reference.md).
90
+
76
91
  ### MCP Client configuration
77
92
 
78
93
  <details>
@@ -399,7 +414,7 @@ If you run into any issues, checkout our [troubleshooting guide](./docs/troubles
399
414
 
400
415
  <!-- BEGIN AUTO GENERATED TOOLS -->
401
416
 
402
- - **Input automation** (8 tools)
417
+ - **Input automation** (9 tools)
403
418
  - [`click`](docs/tool-reference.md#click)
404
419
  - [`drag`](docs/tool-reference.md#drag)
405
420
  - [`fill`](docs/tool-reference.md#fill)
@@ -407,6 +422,7 @@ If you run into any issues, checkout our [troubleshooting guide](./docs/troubles
407
422
  - [`handle_dialog`](docs/tool-reference.md#handle_dialog)
408
423
  - [`hover`](docs/tool-reference.md#hover)
409
424
  - [`press_key`](docs/tool-reference.md#press_key)
425
+ - [`type_text`](docs/tool-reference.md#type_text)
410
426
  - [`upload_file`](docs/tool-reference.md#upload_file)
411
427
  - **Navigation automation** (6 tools)
412
428
  - [`close_page`](docs/tool-reference.md#close_page)
@@ -418,10 +434,11 @@ If you run into any issues, checkout our [troubleshooting guide](./docs/troubles
418
434
  - **Emulation** (2 tools)
419
435
  - [`emulate`](docs/tool-reference.md#emulate)
420
436
  - [`resize_page`](docs/tool-reference.md#resize_page)
421
- - **Performance** (3 tools)
437
+ - **Performance** (4 tools)
422
438
  - [`performance_analyze_insight`](docs/tool-reference.md#performance_analyze_insight)
423
439
  - [`performance_start_trace`](docs/tool-reference.md#performance_start_trace)
424
440
  - [`performance_stop_trace`](docs/tool-reference.md#performance_stop_trace)
441
+ - [`take_memory_snapshot`](docs/tool-reference.md#take_memory_snapshot)
425
442
  - **Network** (2 tools)
426
443
  - [`get_network_request`](docs/tool-reference.md#get_network_request)
427
444
  - [`list_network_requests`](docs/tool-reference.md#list_network_requests)
@@ -495,6 +512,10 @@ The Chrome DevTools MCP server supports the following configuration option:
495
512
  If enabled, ignores errors relative to self-signed and expired certificates. Use with caution.
496
513
  - **Type:** boolean
497
514
 
515
+ - **`--experimentalScreencast`/ `--experimental-screencast`**
516
+ Exposes experimental screencast tools (requires ffmpeg). Install ffmpeg https://www.ffmpeg.org/download.html and ensure it is available in the MCP server PATH.
517
+ - **Type:** boolean
518
+
498
519
  - **`--chromeArg`/ `--chrome-arg`**
499
520
  Additional arguments for Chrome. Only applies when Chrome is launched by chrome-devtools-mcp.
500
521
  - **Type:** array
@@ -528,6 +549,10 @@ The Chrome DevTools MCP server supports the following configuration option:
528
549
  - **Type:** boolean
529
550
  - **Default:** `true`
530
551
 
552
+ - **`--slim`**
553
+ Exposes a "slim" set of 3 tools covering navigation, script execution and screenshots only. Useful for basic browser tasks.
554
+ - **Type:** boolean
555
+
531
556
  <!-- END AUTO GENERATED OPTIONS -->
532
557
 
533
558
  Pass them via the `args` property in the JSON configuration. For example:
@@ -9,6 +9,7 @@ import path from 'node:path';
9
9
  import { extractUrlLikeFromDevToolsTitle, UniverseManager, urlsEqual, } from './DevtoolsUtils.js';
10
10
  import { NetworkCollector, ConsoleCollector } from './PageCollector.js';
11
11
  import { Locator } from './third_party/index.js';
12
+ import { PredefinedNetworkConditions } from './third_party/index.js';
12
13
  import { listPages } from './tools/pages.js';
13
14
  import { takeSnapshot } from './tools/snapshot.js';
14
15
  import { CLOSE_PAGE_ERROR } from './tools/ToolDefinition.js';
@@ -44,23 +45,24 @@ function getExtensionFromMimeType(mimeType) {
44
45
  export class McpContext {
45
46
  browser;
46
47
  logger;
47
- // The most recent page state.
48
+ // Maps LLM-provided isolatedContext name → Puppeteer BrowserContext.
49
+ #isolatedContexts = new Map();
50
+ // Reverse lookup: Page → isolatedContext name (for snapshot labeling).
51
+ // WeakMap so closed pages are garbage-collected automatically.
52
+ #pageToIsolatedContextName = new WeakMap();
53
+ // Auto-generated name counter for when no name is provided.
54
+ #nextIsolatedContextId = 1;
48
55
  #pages = [];
49
56
  #pageToDevToolsPage = new Map();
50
57
  #selectedPage;
51
- // The most recent snapshot.
52
58
  #textSnapshot = null;
53
59
  #networkCollector;
54
60
  #consoleCollector;
55
61
  #devtoolsUniverseManager;
56
62
  #extensionRegistry = new ExtensionRegistry();
57
63
  #isRunningTrace = false;
58
- #networkConditionsMap = new WeakMap();
59
- #cpuThrottlingRateMap = new WeakMap();
60
- #geolocationMap = new WeakMap();
61
- #viewportMap = new WeakMap();
62
- #userAgentMap = new WeakMap();
63
- #colorSchemeMap = new WeakMap();
64
+ #screenRecorderData = null;
65
+ #emulationSettingsMap = new WeakMap();
64
66
  #dialog;
65
67
  #pageIdMap = new WeakMap();
66
68
  #nextPageId = 1;
@@ -100,6 +102,10 @@ export class McpContext {
100
102
  this.#networkCollector.dispose();
101
103
  this.#consoleCollector.dispose();
102
104
  this.#devtoolsUniverseManager.dispose();
105
+ // Isolated contexts are intentionally not closed here.
106
+ // Either the entire browser will be closed or we disconnect
107
+ // without destroying browser state.
108
+ this.#isolatedContexts.clear();
103
109
  }
104
110
  static async from(browser, logger, opts,
105
111
  /* Let tests use unbundled Locator class to avoid overly strict checks within puppeteer that fail when mixing bundled and unbundled class instances */
@@ -163,8 +169,20 @@ export class McpContext {
163
169
  getConsoleMessageById(id) {
164
170
  return this.#consoleCollector.getById(this.getSelectedPage(), id);
165
171
  }
166
- async newPage(background) {
167
- const page = await this.browser.newPage({ background });
172
+ async newPage(background, isolatedContextName) {
173
+ let page;
174
+ if (isolatedContextName !== undefined) {
175
+ let ctx = this.#isolatedContexts.get(isolatedContextName);
176
+ if (!ctx) {
177
+ ctx = await this.browser.createBrowserContext();
178
+ this.#isolatedContexts.set(isolatedContextName, ctx);
179
+ }
180
+ page = await ctx.newPage();
181
+ this.#pageToIsolatedContextName.set(page, isolatedContextName);
182
+ }
183
+ else {
184
+ page = await this.browser.newPage({ background });
185
+ }
168
186
  await this.createPagesSnapshot();
169
187
  this.selectPage(page);
170
188
  this.#networkCollector.addPage(page);
@@ -177,84 +195,133 @@ export class McpContext {
177
195
  }
178
196
  const page = this.getPageById(pageId);
179
197
  await page.close({ runBeforeUnload: false });
198
+ this.#pageToIsolatedContextName.delete(page);
180
199
  }
181
200
  getNetworkRequestById(reqid) {
182
201
  return this.#networkCollector.getById(this.getSelectedPage(), reqid);
183
202
  }
184
- setNetworkConditions(conditions) {
203
+ async emulate(options) {
185
204
  const page = this.getSelectedPage();
186
- if (conditions === null) {
187
- this.#networkConditionsMap.delete(page);
205
+ const currentSettings = this.#emulationSettingsMap.get(page) ?? {};
206
+ const newSettings = { ...currentSettings };
207
+ let timeoutsNeedUpdate = false;
208
+ if (options.networkConditions !== undefined) {
209
+ timeoutsNeedUpdate = true;
210
+ if (options.networkConditions === null ||
211
+ options.networkConditions === 'No emulation') {
212
+ await page.emulateNetworkConditions(null);
213
+ delete newSettings.networkConditions;
214
+ }
215
+ else if (options.networkConditions === 'Offline') {
216
+ await page.emulateNetworkConditions({
217
+ offline: true,
218
+ download: 0,
219
+ upload: 0,
220
+ latency: 0,
221
+ });
222
+ newSettings.networkConditions = 'Offline';
223
+ }
224
+ else if (options.networkConditions in PredefinedNetworkConditions) {
225
+ const networkCondition = PredefinedNetworkConditions[options.networkConditions];
226
+ await page.emulateNetworkConditions(networkCondition);
227
+ newSettings.networkConditions = options.networkConditions;
228
+ }
229
+ }
230
+ if (options.cpuThrottlingRate !== undefined) {
231
+ timeoutsNeedUpdate = true;
232
+ if (options.cpuThrottlingRate === null) {
233
+ await page.emulateCPUThrottling(1);
234
+ delete newSettings.cpuThrottlingRate;
235
+ }
236
+ else {
237
+ await page.emulateCPUThrottling(options.cpuThrottlingRate);
238
+ newSettings.cpuThrottlingRate = options.cpuThrottlingRate;
239
+ }
240
+ }
241
+ if (options.geolocation !== undefined) {
242
+ if (options.geolocation === null) {
243
+ await page.setGeolocation({ latitude: 0, longitude: 0 });
244
+ delete newSettings.geolocation;
245
+ }
246
+ else {
247
+ await page.setGeolocation(options.geolocation);
248
+ newSettings.geolocation = options.geolocation;
249
+ }
250
+ }
251
+ if (options.userAgent !== undefined) {
252
+ if (options.userAgent === null) {
253
+ await page.setUserAgent({ userAgent: undefined });
254
+ delete newSettings.userAgent;
255
+ }
256
+ else {
257
+ await page.setUserAgent({ userAgent: options.userAgent });
258
+ newSettings.userAgent = options.userAgent;
259
+ }
260
+ }
261
+ if (options.colorScheme !== undefined) {
262
+ if (options.colorScheme === null || options.colorScheme === 'auto') {
263
+ await page.emulateMediaFeatures([
264
+ { name: 'prefers-color-scheme', value: '' },
265
+ ]);
266
+ delete newSettings.colorScheme;
267
+ }
268
+ else {
269
+ await page.emulateMediaFeatures([
270
+ { name: 'prefers-color-scheme', value: options.colorScheme },
271
+ ]);
272
+ newSettings.colorScheme = options.colorScheme;
273
+ }
274
+ }
275
+ if (options.viewport !== undefined) {
276
+ if (options.viewport === null) {
277
+ await page.setViewport(null);
278
+ delete newSettings.viewport;
279
+ }
280
+ else {
281
+ const defaults = {
282
+ deviceScaleFactor: 1,
283
+ isMobile: false,
284
+ hasTouch: false,
285
+ isLandscape: false,
286
+ };
287
+ const viewport = { ...defaults, ...options.viewport };
288
+ await page.setViewport(viewport);
289
+ newSettings.viewport = viewport;
290
+ }
291
+ }
292
+ if (Object.keys(newSettings).length) {
293
+ this.#emulationSettingsMap.set(page, newSettings);
188
294
  }
189
295
  else {
190
- this.#networkConditionsMap.set(page, conditions);
296
+ this.#emulationSettingsMap.delete(page);
297
+ }
298
+ if (timeoutsNeedUpdate) {
299
+ this.#updateSelectedPageTimeouts();
191
300
  }
192
- this.#updateSelectedPageTimeouts();
193
301
  }
194
302
  getNetworkConditions() {
195
303
  const page = this.getSelectedPage();
196
- return this.#networkConditionsMap.get(page) ?? null;
197
- }
198
- setCpuThrottlingRate(rate) {
199
- const page = this.getSelectedPage();
200
- this.#cpuThrottlingRateMap.set(page, rate);
201
- this.#updateSelectedPageTimeouts();
304
+ return this.#emulationSettingsMap.get(page)?.networkConditions ?? null;
202
305
  }
203
306
  getCpuThrottlingRate() {
204
307
  const page = this.getSelectedPage();
205
- return this.#cpuThrottlingRateMap.get(page) ?? 1;
206
- }
207
- setGeolocation(geolocation) {
208
- const page = this.getSelectedPage();
209
- if (geolocation === null) {
210
- this.#geolocationMap.delete(page);
211
- }
212
- else {
213
- this.#geolocationMap.set(page, geolocation);
214
- }
308
+ return this.#emulationSettingsMap.get(page)?.cpuThrottlingRate ?? 1;
215
309
  }
216
310
  getGeolocation() {
217
311
  const page = this.getSelectedPage();
218
- return this.#geolocationMap.get(page) ?? null;
219
- }
220
- setViewport(viewport) {
221
- const page = this.getSelectedPage();
222
- if (viewport === null) {
223
- this.#viewportMap.delete(page);
224
- }
225
- else {
226
- this.#viewportMap.set(page, viewport);
227
- }
312
+ return this.#emulationSettingsMap.get(page)?.geolocation ?? null;
228
313
  }
229
314
  getViewport() {
230
315
  const page = this.getSelectedPage();
231
- return this.#viewportMap.get(page) ?? null;
232
- }
233
- setUserAgent(userAgent) {
234
- const page = this.getSelectedPage();
235
- if (userAgent === null) {
236
- this.#userAgentMap.delete(page);
237
- }
238
- else {
239
- this.#userAgentMap.set(page, userAgent);
240
- }
316
+ return this.#emulationSettingsMap.get(page)?.viewport ?? null;
241
317
  }
242
318
  getUserAgent() {
243
319
  const page = this.getSelectedPage();
244
- return this.#userAgentMap.get(page) ?? null;
245
- }
246
- setColorScheme(scheme) {
247
- const page = this.getSelectedPage();
248
- if (scheme === null) {
249
- this.#colorSchemeMap.delete(page);
250
- }
251
- else {
252
- this.#colorSchemeMap.set(page, scheme);
253
- }
320
+ return this.#emulationSettingsMap.get(page)?.userAgent ?? null;
254
321
  }
255
322
  getColorScheme() {
256
323
  const page = this.getSelectedPage();
257
- return this.#colorSchemeMap.get(page) ?? null;
324
+ return this.#emulationSettingsMap.get(page)?.colorScheme ?? null;
258
325
  }
259
326
  setIsRunningPerformanceTrace(x) {
260
327
  this.#isRunningTrace = x;
@@ -262,6 +329,12 @@ export class McpContext {
262
329
  isRunningPerformanceTrace() {
263
330
  return this.#isRunningTrace;
264
331
  }
332
+ getScreenRecorder() {
333
+ return this.#screenRecorderData;
334
+ }
335
+ setScreenRecorder(data) {
336
+ this.#screenRecorderData = data;
337
+ }
265
338
  isCruxEnabled() {
266
339
  return this.#options.performanceCrux;
267
340
  }
@@ -353,19 +426,14 @@ export class McpContext {
353
426
  });
354
427
  }
355
428
  }
356
- /**
357
- * Creates a snapshot of the pages.
358
- */
359
429
  async createPagesSnapshot() {
360
- const allPages = await this.browser.pages(this.#options.experimentalIncludeAllPages);
430
+ const allPages = await this.#getAllPages();
361
431
  for (const page of allPages) {
362
432
  if (!this.#pageIdMap.has(page)) {
363
433
  this.#pageIdMap.set(page, this.#nextPageId++);
364
434
  }
365
435
  }
366
436
  this.#pages = allPages.filter(page => {
367
- // If we allow debugging DevTools windows, return all pages.
368
- // If we are in regular mode, the user should only see non-DevTools page.
369
437
  return (this.#options.experimentalDevToolsDebugging ||
370
438
  !page.url().startsWith('devtools://'));
371
439
  });
@@ -376,9 +444,37 @@ export class McpContext {
376
444
  await this.detectOpenDevToolsWindows();
377
445
  return this.#pages;
378
446
  }
447
+ async #getAllPages() {
448
+ const defaultCtx = this.browser.defaultBrowserContext();
449
+ const allPages = await this.browser.pages(this.#options.experimentalIncludeAllPages);
450
+ // Build a reverse lookup from BrowserContext instance → name.
451
+ const contextToName = new Map();
452
+ for (const [name, ctx] of this.#isolatedContexts) {
453
+ contextToName.set(ctx, name);
454
+ }
455
+ // Auto-discover BrowserContexts not in our mapping (e.g., externally
456
+ // created incognito contexts) and assign generated names.
457
+ const knownContexts = new Set(this.#isolatedContexts.values());
458
+ for (const ctx of this.browser.browserContexts()) {
459
+ if (ctx !== defaultCtx && !ctx.closed && !knownContexts.has(ctx)) {
460
+ const name = `isolated-context-${this.#nextIsolatedContextId++}`;
461
+ this.#isolatedContexts.set(name, ctx);
462
+ contextToName.set(ctx, name);
463
+ }
464
+ }
465
+ // Use page.browserContext() to determine each page's context membership.
466
+ for (const page of allPages) {
467
+ const ctx = page.browserContext();
468
+ const name = contextToName.get(ctx);
469
+ if (name) {
470
+ this.#pageToIsolatedContextName.set(page, name);
471
+ }
472
+ }
473
+ return allPages;
474
+ }
379
475
  async detectOpenDevToolsWindows() {
380
476
  this.logger('Detecting open DevTools windows');
381
- const pages = await this.browser.pages(this.#options.experimentalIncludeAllPages);
477
+ const pages = await this.#getAllPages();
382
478
  this.#pageToDevToolsPage = new Map();
383
479
  for (const devToolsPage of pages) {
384
480
  if (devToolsPage.url().startsWith('devtools://')) {
@@ -409,6 +505,9 @@ export class McpContext {
409
505
  getPages() {
410
506
  return this.#pages;
411
507
  }
508
+ getIsolatedContextName(page) {
509
+ return this.#pageToIsolatedContextName.get(page);
510
+ }
412
511
  getDevToolsPage(page) {
413
512
  return this.#pageToDevToolsPage.get(page);
414
513
  }
@@ -560,10 +659,10 @@ export class McpContext {
560
659
  waitForTextOnPage(text, timeout) {
561
660
  const page = this.getSelectedPage();
562
661
  const frames = page.frames();
563
- let locator = this.#locatorClass.race(frames.flatMap(frame => [
564
- frame.locator(`aria/${text}`),
565
- frame.locator(`text/${text}`),
566
- ]));
662
+ let locator = this.#locatorClass.race(frames.flatMap(frame => text.flatMap(value => [
663
+ frame.locator(`aria/${value}`),
664
+ frame.locator(`text/${value}`),
665
+ ])));
567
666
  if (timeout) {
568
667
  locator = locator.setTimeout(timeout);
569
668
  }
@@ -583,7 +682,8 @@ export class McpContext {
583
682
  },
584
683
  };
585
684
  });
586
- await this.#networkCollector.init(await this.browser.pages());
685
+ const pages = await this.#getAllPages();
686
+ await this.#networkCollector.init(pages);
587
687
  }
588
688
  async installExtension(extensionPath) {
589
689
  const id = await this.browser.installExtension(extensionPath);
@@ -325,15 +325,24 @@ Call ${handleDialog.name} to handle it before continuing.`);
325
325
  if (this.#includePages) {
326
326
  const parts = [`## Pages`];
327
327
  for (const page of context.getPages()) {
328
- parts.push(`${context.getPageId(page)}: ${page.url()}${context.isPageSelected(page) ? ' [selected]' : ''}`);
328
+ const isolatedContextName = context.getIsolatedContextName(page);
329
+ const contextLabel = isolatedContextName
330
+ ? ` isolatedContext=${isolatedContextName}`
331
+ : '';
332
+ parts.push(`${context.getPageId(page)}: ${page.url()}${context.isPageSelected(page) ? ' [selected]' : ''}${contextLabel}`);
329
333
  }
330
334
  response.push(...parts);
331
335
  structuredContent.pages = context.getPages().map(page => {
332
- return {
336
+ const isolatedContextName = context.getIsolatedContextName(page);
337
+ const entry = {
333
338
  id: context.getPageId(page),
334
339
  url: page.url(),
335
340
  selected: context.isPageSelected(page),
336
341
  };
342
+ if (isolatedContextName) {
343
+ entry.isolatedContext = isolatedContextName;
344
+ }
345
+ return entry;
337
346
  });
338
347
  }
339
348
  if (this.#tabId) {
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { McpResponse } from './McpResponse.js';
7
+ export class SlimMcpResponse extends McpResponse {
8
+ async handle(_toolName, _context) {
9
+ const text = {
10
+ type: 'text',
11
+ text: this.responseLines.join('\n'),
12
+ };
13
+ return {
14
+ content: [text],
15
+ structuredContent: text,
16
+ };
17
+ }
18
+ }
@@ -3,6 +3,7 @@
3
3
  * Copyright 2025 Google LLC
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
+ import { execSync } from 'node:child_process';
6
7
  import fs from 'node:fs';
7
8
  import os from 'node:os';
8
9
  import path from 'node:path';
@@ -103,6 +104,22 @@ export async function ensureBrowserConnected(options) {
103
104
  logger('Connected Puppeteer');
104
105
  return browser;
105
106
  }
107
+ export function detectDisplay() {
108
+ // Only detect display on Linux/UNIX.
109
+ if (os.platform() === 'win32' || os.platform() === 'darwin') {
110
+ return;
111
+ }
112
+ if (!process.env['DISPLAY']) {
113
+ try {
114
+ const result = execSync(`ps -u $(id -u) -o pid= | xargs -I{} cat /proc/{}/environ 2>/dev/null | tr '\\0' '\\n' | grep -m1 '^DISPLAY=' | cut -d= -f2`);
115
+ const display = result.toString('utf8').trim();
116
+ process.env['DISPLAY'] = display;
117
+ }
118
+ catch {
119
+ // no-op
120
+ }
121
+ }
122
+ }
106
123
  export async function launch(options) {
107
124
  const { channel, executablePath, headless, isolated } = options;
108
125
  const profileDirName = channel && channel !== 'stable'
@@ -133,6 +150,9 @@ export async function launch(options) {
133
150
  ? `chrome-${channel}`
134
151
  : 'chrome';
135
152
  }
153
+ if (!headless) {
154
+ detectDisplay();
155
+ }
136
156
  try {
137
157
  const browser = await puppeteer.launch({
138
158
  channel: puppeteerChannel,
package/build/src/cli.js CHANGED
@@ -159,6 +159,10 @@ export const cliOptions = {
159
159
  describe: 'Whether to enable interoperability tools',
160
160
  hidden: true,
161
161
  },
162
+ experimentalScreencast: {
163
+ type: 'boolean',
164
+ describe: 'Exposes experimental screencast tools (requires ffmpeg). Install ffmpeg https://www.ffmpeg.org/download.html and ensure it is available in the MCP server PATH.',
165
+ },
162
166
  chromeArg: {
163
167
  type: 'array',
164
168
  describe: 'Additional arguments for Chrome. Only applies when Chrome is launched by chrome-devtools-mcp.',
@@ -213,6 +217,10 @@ export const cliOptions = {
213
217
  hidden: true,
214
218
  describe: 'Include watchdog PID in Clearcut request headers (for testing).',
215
219
  },
220
+ slim: {
221
+ type: 'boolean',
222
+ describe: 'Exposes a "slim" set of 3 tools covering navigation, script execution and screenshots only. Useful for basic browser tasks.',
223
+ },
216
224
  };
217
225
  export function parseArguments(version, argv = process.argv) {
218
226
  const yargsInstance = yargs(hideBin(argv))
@@ -286,6 +294,10 @@ export function parseArguments(version, argv = process.argv) {
286
294
  '$0 --no-performance-crux',
287
295
  'Disable CrUX (field data) integration in performance tools.',
288
296
  ],
297
+ [
298
+ '$0 --slim',
299
+ 'Only 3 tools: navigation, JavaScript execution and screenshot',
300
+ ],
289
301
  ]);
290
302
  return yargsInstance
291
303
  .wrap(Math.min(120, yargsInstance.terminalWidth()))