From f717fe5abc63332447b16110ee8bb8a9a382e49d Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Sat, 14 Feb 2026 13:16:46 -0800 Subject: [PATCH 1/2] chore(cli): iterate over skills (#39276) --- packages/playwright/src/skill/SKILL.md | 39 +++++++++++++++++++------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/packages/playwright/src/skill/SKILL.md b/packages/playwright/src/skill/SKILL.md index 29182e7630425..11bad2b874ab4 100644 --- a/packages/playwright/src/skill/SKILL.md +++ b/packages/playwright/src/skill/SKILL.md @@ -17,7 +17,7 @@ playwright-cli goto https://playwright.dev playwright-cli click e15 playwright-cli type "page.click" playwright-cli press Enter -# take a screenshot +# take a screenshot (rarely used, as snapshot is more common) playwright-cli screenshot # close the browser playwright-cli close @@ -155,14 +155,7 @@ playwright-cli video-start playwright-cli video-stop video.webm ``` -### Install - -```bash -playwright-cli install --skills -playwright-cli install-browser -``` - -### Configuration +## Open parameters ```bash # Use specific browser when creating session playwright-cli open --browser=chrome @@ -186,7 +179,24 @@ playwright-cli close playwright-cli delete-data ``` -### Browser Sessions +## Snapshots + +After each command, playwright-cli provides a snapshot of the current browser state. + +```bash +> playwright-cli goto https://example.com +### Page +- Page URL: https://example.com/ +- Page Title: Example Domain +### Snapshot +[Snapshot](.playwright-cli/page-2026-02-14T19-22-42-679Z.yml) +``` + +You can also take a snapshot on demand using `playwright-cli snapshot` command. + +If `--filename` is not provided, a new snapshot file is created with a timestamp. Default to automatic file naming, use `--filename=` when artifact is a part of the workflow result. + +## Browser Sessions ```bash # create new browser session named "mysession" with persistent profile @@ -204,6 +214,15 @@ playwright-cli close-all playwright-cli kill-all ``` +## Local installation + +In some cases user might want to install playwright-cli locally. If running globally available `playwright-cli` binary fails, use `npx playwright-cli` to run the commands. For example: + +```bash +npx playwright-cli open https://example.com +npx playwright-cli click e1 +``` + ## Example: Form submission ```bash From c6385e174b4bf2992914733c5bb63f95561c613d Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Sat, 14 Feb 2026 13:24:17 -0800 Subject: [PATCH 2/2] Revert "chore: rename --no-sandbox to --no-chromium-sandbox (#39208)" (#39277) --- packages/playwright/src/mcp/browser/config.ts | 12 ++++++------ packages/playwright/src/mcp/program.ts | 8 ++++---- tests/mcp/config.spec.ts | 14 +++++++------- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/packages/playwright/src/mcp/browser/config.ts b/packages/playwright/src/mcp/browser/config.ts index 2dbecdc8a51b9..a8b30227b20f7 100644 --- a/packages/playwright/src/mcp/browser/config.ts +++ b/packages/playwright/src/mcp/browser/config.ts @@ -44,7 +44,6 @@ export type CLIOptions = { cdpEndpoint?: string; cdpHeader?: Record; cdpTimeout?: number; - chromiumSandbox?: boolean; codegen?: 'typescript' | 'none'; config?: string; consoleLevel?: 'error' | 'warning' | 'info' | 'debug'; @@ -59,6 +58,7 @@ export type CLIOptions = { initPage?: string[]; isolated?: boolean; imageResponses?: 'allow' | 'omit'; + sandbox?: boolean; outputDir?: string; outputMode?: 'file' | 'stdout'; port?: number; @@ -223,10 +223,10 @@ export function configFromCLIOptions(cliOptions: CLIOptions): Config & { configF headless: cliOptions.headless, }; - // --chromium-sandbox was passed, enable the chromium sandbox - // --no-chromium-sandbox was passed, disable the chromium sandbox - if (cliOptions.chromiumSandbox !== undefined) - launchOptions.chromiumSandbox = cliOptions.chromiumSandbox; + // --sandbox was passed, enable the sandbox + // --no-sandbox was passed, disable the sandbox + if (cliOptions.sandbox !== undefined) + launchOptions.chromiumSandbox = cliOptions.sandbox; if (cliOptions.proxyServer) { launchOptions.proxy = { @@ -338,7 +338,7 @@ export function configFromEnv(): Config & { configFile?: string } { options.isolated = envToBoolean(process.env.PLAYWRIGHT_MCP_ISOLATED); if (process.env.PLAYWRIGHT_MCP_IMAGE_RESPONSES) options.imageResponses = enumParser<'allow' | 'omit'>('--image-responses', ['allow', 'omit'], process.env.PLAYWRIGHT_MCP_IMAGE_RESPONSES); - options.chromiumSandbox = envToBoolean(process.env.PLAYWRIGHT_MCP_CHROMIUM_SANDBOX); + options.sandbox = envToBoolean(process.env.PLAYWRIGHT_MCP_SANDBOX); options.outputDir = envToString(process.env.PLAYWRIGHT_MCP_OUTPUT_DIR); options.port = numberParser(process.env.PLAYWRIGHT_MCP_PORT); options.proxyBypass = envToString(process.env.PLAYWRIGHT_MCP_PROXY_BYPASS); diff --git a/packages/playwright/src/mcp/program.ts b/packages/playwright/src/mcp/program.ts index fda9347a8dce2..63d66a68553f0 100644 --- a/packages/playwright/src/mcp/program.ts +++ b/packages/playwright/src/mcp/program.ts @@ -37,8 +37,6 @@ export function decorateMCPCommand(command: Command, version: string) { .option('--cdp-endpoint ', 'CDP endpoint to connect to.') .option('--cdp-header ', 'CDP headers to send with the connect request, multiple can be specified.', headerParser) .option('--cdp-timeout ', 'timeout in milliseconds for connecting to CDP endpoint, defaults to 30000ms', numberParser) - .option('--chromium-sandbox', 'enable the chromium sandbox. disable with --no-chromium-sandbox.') - .option('--no-chromium-sandbox', 'disable the chromium sandbox.') .option('--codegen ', 'specify the language to use for code generation, possible values: "typescript", "none". Default is "typescript".', enumParser.bind(null, '--codegen', ['none', 'typescript'])) .option('--config ', 'path to the configuration file.') .option('--console-level ', 'level of console messages to return: "error", "warning", "info", "debug". Each level includes the messages of more severe levels.', enumParser.bind(null, '--console-level', ['error', 'warning', 'info', 'debug'])) @@ -53,11 +51,13 @@ export function decorateMCPCommand(command: Command, version: string) { .option('--init-script ', 'path to JavaScript file to add as an initialization script. The script will be evaluated in every page before any of the page\'s scripts. Can be specified multiple times.') .option('--isolated', 'keep the browser profile in memory, do not save it to disk.') .option('--image-responses ', 'whether to send image responses to the client. Can be "allow" or "omit", Defaults to "allow".', enumParser.bind(null, '--image-responses', ['allow', 'omit'])) + .option('--no-sandbox', 'disable the sandbox for all process types that are normally sandboxed.') .option('--output-dir ', 'path to the directory for output files.') .option('--output-mode ', 'whether to save snapshots, console messages, network logs to a file or to the standard output. Can be "file" or "stdout". Default is "stdout".', enumParser.bind(null, '--output-mode', ['file', 'stdout'])) .option('--port ', 'port to listen on for SSE transport.') .option('--proxy-bypass ', 'comma-separated domains to bypass proxy, for example ".com,chromium.org,.domain.com"') .option('--proxy-server ', 'specify proxy server, for example "http://myproxy:3128" or "socks5://myproxy:8080"') + .option('--sandbox', 'enable the sandbox for all process types that are normally not sandboxed.') .option('--save-session', 'Whether to save the Playwright MCP session into the output directory.') .option('--save-trace', 'Whether to save the Playwright Trace of the session into the output directory.') .option('--save-video ', 'Whether to save the video of the session into the output directory. For example "--save-video=800x600"', resolutionParser.bind(null, '--save-video')) @@ -74,8 +74,8 @@ export function decorateMCPCommand(command: Command, version: string) { .addOption(new ProgramOption('--vision', 'Legacy option, use --caps=vision instead').hideHelp()) .action(async options => { - // normalize the --no-chromium-sandbox option: chromiumSandbox = true => nothing was passed, chromiumSandbox = false => --no-chromium-sandbox was passed. - options.chromiumSandbox = options.chromiumSandbox === true ? undefined : false; + // normalize the --no-sandbox option: sandbox = true => nothing was passed, sandbox = false => --no-sandbox was passed. + options.sandbox = options.sandbox === true ? undefined : false; setupExitWatchdog(); diff --git a/tests/mcp/config.spec.ts b/tests/mcp/config.spec.ts index 25ae88ae4d9de..9e0eaadfe8400 100644 --- a/tests/mcp/config.spec.ts +++ b/tests/mcp/config.spec.ts @@ -78,15 +78,15 @@ test.describe(() => { }); }); -test('test chromiumSandbox configuration', async ({}) => { - async function sandboxOption(cli: any) { - const config: any = await resolveCLIConfig(cli); - return config.browser.launchOptions.chromiumSandbox; - } +async function sandboxOption(cli: any) { + const config: any = await resolveCLIConfig(cli); + return config.browser.launchOptions.chromiumSandbox; +} +test('test sandbox configuration', async ({}) => { expect(await sandboxOption({ browser: 'chromium' })).toBe(process.platform !== 'linux'); - expect(await sandboxOption({ browser: 'chromium', chromiumSandbox: true })).toBe(true); - expect(await sandboxOption({ browser: 'chrome', chromiumSandbox: false })).toBe(false); + expect(await sandboxOption({ browser: 'chromium', sandbox: true })).toBe(true); + expect(await sandboxOption({ browser: 'chrome', sandbox: false })).toBe(false); expect(await sandboxOption({ browser: 'chrome' })).toBe(true); expect(await sandboxOption({ browser: 'msedge' })).toBe(true); });