Skip to Content
DocsBrowser CLI

Browser CLI

@msw-dev-tool/browser-cli lets an AI agent or script control HTTP and WebSocket scenarios in a browser MSW Dev Tool session through Chrome DevTools Protocol (CDP). Set a scenario with the CLI, inspect the same target through CDP, and verify the user-visible result.

Configuration

Configure Chrome DevTools MCP

For Codex, use .codex/config.toml:

[mcp_servers.chrome-devtools] command = "npx" args = ["-y", "chrome-devtools-mcp@latest", "--browser-url=http://127.0.0.1:9222"] startup_timeout_sec = 120.0

For Claude Code, use the root .mcp.json:

{ "mcpServers": { "chrome-devtools": { "command": "npx", "args": [ "-y", "chrome-devtools-mcp@latest", "--browser-url=http://127.0.0.1:9222" ] } } }

See the Chrome DevTools MCP documentation for other clients and connection options.

Install and connect the runtime

pnpm add -D @msw-dev-tool/browser-cli @msw-dev-tool/core msw

The target tab must run setupDevToolWorker(...handlers). Start a separate Chrome profile with remote debugging enabled:

open -na "Google Chrome" --args --remote-debugging-address=127.0.0.1 --remote-debugging-port=9222 --user-data-dir=/private/tmp/chrome-debug-9222

Choose a target

List browser page targets, confirm the selected tab has initialized setupDevToolWorker(...handlers), and use that exact target ID for every mutation. sessionStorage is tab-scoped.

msw-dev-tool-browser tabs --cdp-url http://127.0.0.1:9222 target_id="paste-the-id-of-the-tab-that-runs-setupDevToolWorker" cdp_args=(--cdp-url http://127.0.0.1:9222 --target "$target_id") msw-dev-tool-browser session "${cdp_args[@]}"
⚠️

The remote-debugging endpoint gives local processes browser-debugging access. Keep the separate Chrome profile running and do not use a regular browsing profile.

Commands & API

Successful commands print machine-readable JSON to stdout. Errors are plain text on stderr and exit with a non-zero status. The examples use the cdp_args array from the target-selection step.

HTTP scenarios

msw-dev-tool-browser list "${cdp_args[@]}" msw-dev-tool-browser get '{"path":"/api/items","method":"get"}' "${cdp_args[@]}" msw-dev-tool-browser set-behavior '{"path":"/api/items","method":"get"}' delay "${cdp_args[@]}" msw-dev-tool-browser set-enabled '{"path":"/api/items","method":"get"}' false "${cdp_args[@]}" msw-dev-tool-browser set-mock-enabled false "${cdp_args[@]}" msw-dev-tool-browser set-custom-response '{"path":"/api/items","method":"get"}' --json '{"status":"200","contentType":"application/json","response":"[]","delay":100}' "${cdp_args[@]}" msw-dev-tool-browser set-behavior '{"path":"/api/items","method":"get"}' 'custom response' "${cdp_args[@]}" msw-dev-tool-browser add-temp --json '{"path":"/api/preview","method":"get","contentType":"application/json","status":"200","response":"{\\"ok\\":true}"}' "${cdp_args[@]}" msw-dev-tool-browser remove-temp '{"path":"/api/preview","method":"get"}' "${cdp_args[@]}" msw-dev-tool-browser reset "${cdp_args[@]}"
{"ok":true,"handlers":[{"id":"{\\"path\\":\\"/api/items\\",\\"method\\":\\"get\\"}","path":"/api/items","method":"get","behavior":"default","enabled":true}],"mockEnabled":true}

set-enabled <handlerId> <true|false> bypasses only that HTTP handler. set-mock-enabled <true|false> is the global HTTP and WebSocket switch; its result includes mockEnabled. Both leave selected behavior and custom response data intact, so they resume when enabled again.

WebSocket scenarios

msw-dev-tool-browser ws-list "${cdp_args[@]}" endpoint_id="$(msw-dev-tool-browser ws-add-endpoint \ --json '{"kind":"string","value":"ws://localhost:8080/preview"}' "${cdp_args[@]}" \ | jq -r '.endpoint.endpointId')" listener_id="$(msw-dev-tool-browser ws-add-listener "$endpoint_id" --json '{"behavior":{"preset":"default"},"response":{"type":"send","dataType":"string","value":"temp response","delay":300,"repeat":{"interval":500,"repetitions":3}},"customResponse":{"type":"send","dataType":"string","value":"custom response","delay":100}}' "${cdp_args[@]}" \ | jq -r '.listener.info.id')" msw-dev-tool-browser ws-get-endpoint "$endpoint_id" "${cdp_args[@]}" msw-dev-tool-browser ws-set-endpoint-enabled "$endpoint_id" false "${cdp_args[@]}" msw-dev-tool-browser ws-set-listener-behavior "$listener_id" --json '{"preset":"close"}' "${cdp_args[@]}" msw-dev-tool-browser ws-set-listener-response "$listener_id" --json '{"type":"send","dataType":"string","value":"scheduled","delay":300,"repeat":{"interval":500,"repetitions":"Infinity"}}' "${cdp_args[@]}" msw-dev-tool-browser ws-set-listener-enabled "$listener_id" false "${cdp_args[@]}" msw-dev-tool-browser ws-remove-listener "$listener_id" "${cdp_args[@]}" msw-dev-tool-browser ws-remove-endpoint "$endpoint_id" "${cdp_args[@]}"
{"ok":true,"endpoint":{"endpointId":"<value returned in endpoint.endpointId>","enabled":false,"listeners":[]}}

ws-set-*-enabled commands apply only to the specified WebSocket endpoint, listener, or logical event branch; the global set-mock-enabled switch takes precedence. ws-add-endpoint, ws-add-listener, and ws-set-listener-behavior use JSON input.

Temporary listeners default to { "preset": "default" }. response and customResponse are independent configurations containing payload, delay, and repeat; the selected behavior chooses which one runs. Repetitions include the first response, and "Infinity" requires a positive interval. Use a local test client for an unbounded sequence because it can flood the client. Stop it by updating or removing the listener, closing the client, or resetting the Dev Tool.

Use ws-set-listener-response and ws-set-listener-custom-response to replace each complete configuration. Send responses use dataType: "string", "Blob", or "ArrayBuffer"; binary values are space-separated hexadecimal bytes. Close responses accept optional code and reason. Browser changes apply immediately to the in-memory store and persist to the selected tab’s sessionStorage; refresh only to confirm persistence.

After the scenario, run msw-dev-tool-browser reset "${cdp_args[@]}" and inspect the returned JSON before reusing the tab. Then remove temporary items and close the dedicated Chrome debug profile. Code-discovered WebSocket endpoints and listeners cannot be deleted, while temporary ones can.

Last updated on