gut(browser): remove Playwright automation framework#2330
Merged
alexey-pelykh merged 1 commit intomainfrom Apr 12, 2026
Merged
Conversation
Per the Middleware Boundary Principle, the browser_request MCP tool
routes through paired nodes — that's infrastructure. The Playwright
automation layer (~14k lines) was generic browser automation, not
node-bound routing.
Deletes the Playwright layer in src/browser/:
- All pw-* files (pw-session, pw-ai, pw-tools-core.*)
- All routes/agent.* files (act, snapshot, storage, debug, hooks)
- Chrome process management (chrome.ts, chrome.executables,
chrome.profile-decoration)
- Client action wrappers (client-actions*)
- Automation utilities (screenshot, paths, form-fields, safe-filename,
output-atomic, session-tab-registry)
Removes downstream consumers backed by deleted agent routes:
- src/cli/browser-cli-{actions-input,actions-observe,debug,inspect,
resize,state,state.cookies-storage}
- src/agents/tools/browser-tool.actions.ts (orphan since no callers)
Surgically refactors KEEP files:
- routes/index.ts: drops registerBrowserAgentRoutes
- routes/basic.ts: inlines resolveProfileContext, drops chrome
process metadata from /status
- server-context.ts: drops Playwright fallbacks, drops local Chrome
launch path (only attached/extension/remote modes remain)
- profiles-service.ts: switches resolveRemoteClawUserDataDir to new
profile-paths helper
- client.ts: drops browserSnapshot + dead BrowserStatus fields
- gateway/server-methods/sessions.ts: drops
closeTrackedBrowserTabsForSessions (registry was never populated)
Relocates utilities used by KEEP code:
- browser/trash.ts → infra/trash.ts (used by gateway, CLI, profiles)
- browser/proxy-files.ts → gateway/server-methods/browser-proxy-files.ts
(only consumer was gateway/server-methods/browser.ts)
- Extracted CDP reachability checks from chrome.ts into a new
cdp-reachability.ts (no Chrome process semantics)
- Added profile-paths.ts for resolveRemoteClawUserDataDir
Removes playwright-core from package.json and Dockerfile.
Build, lint, format, and tests all green (743 files / 6488 tests).
~14,213 lines deleted, 99 added.
Closes #2304
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Removes the Playwright browser-automation layer from
src/browser/per the Middleware Boundary Principle. Thebrowser_requestMCP tool routes through paired nodes (infrastructure), butsrc/browser/also carried a full Playwright stack (~14k lines, 69% of the directory) that was generic browser automation, not node-bound routing. This PR keeps the node-routing layer (~5.5k lines: bridge-server, extension-relay, profiles, config, security, CDP layer, basic+tabs routes) and removes everything else.~14,373 lines deleted, 253 added across 115 files.
Deleted
Playwright layer (src/browser/):
pw-*files (pw-session, pw-ai, pw-tools-core.*) — 28 filesroutes/agent.*files (act, snapshot, storage, debug, hooks, output-paths) — 13 fileschrome.ts,chrome.executables.ts,chrome.profile-decoration.ts+ testsclient-actions.ts,client-actions-core.ts,client-actions-observe.ts,client-actions-state.tsscreenshot.ts,paths.ts,form-fields.ts,safe-filename.ts,output-atomic.ts,session-tab-registry.tsDownstream consumers (no longer backed by deleted agent routes):
src/cli/browser-cli-actions-input{,.ts,/*}(entire/actaction surface)src/cli/browser-cli-actions-observe.ts(/console,/pdf,/response/body)src/cli/browser-cli-debug.ts(/highlight,/errors,/requests,/trace/*)src/cli/browser-cli-inspect.ts(/screenshot,/snapshot)src/cli/browser-cli-state.ts,src/cli/browser-cli-state.cookies-storage.ts(/set/*,/storage/*)src/cli/browser-cli-resize.ts(uses/act)src/agents/tools/browser-tool.actions.ts(orphan — no callers)Surgically refactored (KEEP files)
routes/index.ts— dropsregisterBrowserAgentRoutesimport + callroutes/basic.ts— inlinesresolveProfileContext(was in deletedagent.shared.ts); drops chrome process metadata fields (chosenBrowser,userDataDir,pid,detectedBrowser*,detectError) from/statuspayloadserver-context.ts— drops Playwright tab-op fallbacks (listPages/createPage/focus/close ViaPlaywright); removes local Chrome launch path entirely (launchRemoteClawChromeis gone — only attached/extension/remote modes remain); replaceschrome.tsreachability calls with newcdp-reachability.ts;resetProfilenow only moves user-data dir for local-loopback profiles, no Chrome shutdownserver-context.types.ts— dropsRunningChromefromProfileRuntimeState(runningfield gone)profiles-service.ts— switchesresolveRemoteClawUserDataDirimport to newprofile-paths.tshelper; switchesmovePathToTrashto new infra locationserver.ts— dropspw-ai-state.isPwAiLoadedshutdown branchcontrol-service.ts— dropspw-ai.closePlaywrightBrowserConnectionshutdown branchclient.ts— dropsbrowserSnapshot(uses deleted/snapshotroute); drops deadBrowserStatusfields (pid,chosenBrowser,userDataDir,executablePath,detectedBrowser*,detectError); dropsSnapshotResult/SnapshotAriaNodetypesgateway/server-methods/sessions.ts— dropscloseTrackedBrowserTabsForSessionscall (the registry was never populated by any caller in this codebase, so the call was a no-op)gateway/server-methods/agents.ts— switchesmovePathToTrashimport toinfra/trash.jsgateway/server-methods/browser.ts— switchesproxy-filesimport to localbrowser-proxy-files.tsRelocated (used by KEEP code)
src/browser/trash.tssrc/infra/trash.tssrc/browser/proxy-files.tssrc/gateway/server-methods/browser-proxy-files.tsgateway/server-methods/browser.tschrome.tssrc/browser/cdp-reachability.tsresolveRemoteClawUserDataDirfromchrome.tssrc/browser/profile-paths.tsprofiles-serviceandserver-context.resetProfileOther
package.json— removesplaywright-coredependencyDockerfile— drops the Playwright browser install step (still installs Xvfb whenREMOTECLAW_INSTALL_BROWSER=1)src/dockerfile.test.ts— updated to assert playwright-core is NOT in the Dockerfilesrc/browser/cdp-timeouts.ts— renamesCHROME_REACHABILITY_TIMEOUT_MS/CHROME_WS_READY_TIMEOUT_MStoCDP_*(more accurate; the chrome bootstrap/launch timeouts that are no longer used were removed)server.control-server.test-harness.ts— slimmed down: only mocks what still exists (cdp-reachability, profile-paths, infra/trash, cdp.js); drops the Playwright/Chrome mock surfaceserver-context.cdp-test-harness.ts— minimal CDP reachability mock for the few tests that need itAcceptance criteria
pw-*files remain insrc/browser/routes/agent.*files remainchrome.*process management files remainserver-context.tshas no Playwright importsroutes/index.tsregisters only basic + tabs routesTest plan
pnpm check(format + typecheck + lint) — cleanpnpm build— clean (warnings unchanged from main)pnpm test— 743 files, 6488 tests pass, 0 failuresremoteclaw browser status,remoteclaw browser tabs,remoteclaw browser open,remoteclaw browser focus,remoteclaw browser closeagainst an attached ChromeCloses #2304
🤖 Generated with Claude Code