BrowserClaw (mcp-chrome) Architecture & System Design ๐๏ธ
September 21, 2026 ยท View on GitHub
Version: 3.0.0 (Production Stable Release)
Target Runtime: Chrome Extension Manifest V3, Chrome DevTools Protocol (CDP 1.3), Model Context Protocol (MCP 2024-11-05), Fastify HTTP/SSE, Chrome Native Messaging.
1. System Overview & Architecture Topology
BrowserClaw connects AI Agents (Claude Desktop, Cursor, Cline, OpenManus, AutoGPT) directly to an active, authenticated Google Chrome instance through the Model Context Protocol (MCP). Unlike traditional headless browser frameworks (Playwright, Puppeteer, Selenium), BrowserClaw operates inside the user's primary browser profile, preserving cookies, logins, session state, and extension capabilities without restarting the browser or exposing insecure remote debugging ports.
graph TB
subgraph "AI Agent & Client Layer"
Agent1["Claude Desktop"]
Agent2["Cursor / Cline / Windsurf"]
Agent3["Autonomous AI Agent"]
end
subgraph "MCP Bridge Layer (Node.js Process)"
SSE["Fastify HTTP / SSE Server :12306"]
TokenAuth["High-Entropy Token Authenticator"]
StdioMCP["MCP Stdio Server Wrapper"]
NativeHost["Chrome Native Messaging Host"]
AffinityBridge["Session-Tab Affinity Engine"]
end
subgraph "Chrome Extension MV3 Layer (Blink / V8)"
SW["Background Service Worker (chrome.storage.session)"]
CDPMgr["CDP Session Manager (Domain RefCount & Anti-Hang Guard)"]
Locator["Unified Locator & Degradation Engine"]
RingBuf["Screenshot Ring Buffer (Cap: 1)"]
SnapCache["DOM Snapshot Cache Manager"]
Guard["Popup, Sender Auth & Security Guard"]
end
subgraph "Browser Runtime & Target Page"
ActiveTab["User Active Tab (Protected)"]
AgentTab["Background Agent Tab (active: false)"]
InPage["Isolated Inpage Engine & WeakRef Map"]
CDPEngine["CDP Target Agent (DOM, Page, Input)"]
end
Agent1 -->|"JSON-RPC via SSE / HTTP"| SSE
Agent2 -->|"JSON-RPC via Stdio"| StdioMCP
Agent3 -->|"JSON-RPC via SSE / HTTP"| SSE
StdioMCP -->|"Native Stdio Pipe"| NativeHost
SSE -->|"Token Verification"| TokenAuth
TokenAuth --> NativeHost
NativeHost -->|"Native Messaging Pipe (<=1MB ceiling)"| SW
SW --> CDPMgr
SW --> Locator
SW --> RingBuf
SW --> SnapCache
SW --> Guard
CDPMgr -->|"chrome.debugger CDP 1.3"| CDPEngine
Locator -->|"chrome.scripting executeScript"| InPage
CDPEngine --> AgentTab
InPage --> AgentTab
2. Component Structure & Modular Dependencies
The monorepo is structured into three cleanly decoupled packages:
mcp-chrome-master/
โโโ packages/
โ โโโ shared/ # Type definitions, tool names, JSON schemas, locator contracts
โโโ app/
โ โโโ chrome-extension/ # WXT MV3 extension (Service Worker, Inpage Script, Popup UI)
โ โ โโโ entrypoints/
โ โ โ โโโ background/ # Tool executors, message listeners, CDP handlers
โ โ โ โโโ inpage-engine.ts # Isolated world DOM traversal & WeakRef indexer
โ โ โ โโโ popup/ # User configuration & status popup UI (reserved for user)
โ โ โโโ utils/ # Pure utility engines (ring buffer, locator, cache, watchdog)
โ โโโ native-server/ # Node.js Fastify HTTP/SSE server + Native Messaging host
โโโ docs/ # Architecture specs, review reports, and guides
Module Dependency Graph
graph LR
Shared["packages/shared"] --> NativeServer["app/native-server"]
Shared --> ChromeExtension["app/chrome-extension"]
ChromeExtension --> WXT["WXT MV3 Engine"]
ChromeExtension --> Blink["Blink DOM / DevTools Protocol"]
NativeServer --> Fastify["Fastify 5.x"]
NativeServer --> MCPCore["@modelcontextprotocol/sdk"]
3. End-to-End Data Flow Pipelines
3.1 Tool Invocation Flow (tools/call)
sequenceDiagram
autonumber
participant Agent as "AI Agent (Client)"
participant Fastify as "Native Fastify (:12306)"
participant Host as "Native Messaging Host"
participant SW as "Extension Service Worker"
participant CDP as "CDP Session Manager"
participant InPage as "Target Tab (Inpage Engine)"
Agent->>Fastify: POST /mcp (tools/call chrome_interact_index)
Note over Fastify: Validates CHROME_MCP_TOKEN Bearer
Fastify->>Host: Dispatch Native Message
Host->>SW: Standard IO Framed Message (4-byte length prefix)
Note over SW: Enforces 1MB physical buffer defense and Sender Authentication
SW->>SW: Check Session-Tab Affinity and Snapshot Validity
SW->>InPage: UnifiedLocator - Resolve Target (Ref / Selector / Text / Coordinate)
InPage-->>SW: Target Coords (x, y, resolutionPath)
SW->>CDP: Input.dispatchMouseEvent (mousePressed, mouseReleased)
CDP-->>SW: CDP Ack (isTrusted: true)
SW->>SW: Invalidate SnapshotCacheManager on navigation
SW-->>Host: Tool Result (content, resolutionPath)
Host-->>Fastify: Native Pipe Response
Fastify-->>Agent: HTTP 200 / SSE tool_result
3.2 Zero-Disk In-Memory Screenshot Pipeline (Background Offscreen Isolation)
sequenceDiagram
autonumber
participant Agent as "AI Agent"
participant SW as "Service Worker"
participant CDP as "CDP Page Domain"
participant RingBuf as "ScreenshotRingBuffer (Cap: 1)"
Agent->>SW: chrome_screenshot (jpeg, quality 80, tabId 101)
Note over SW: Checks tab.active state
alt Background Tab (active: false)
SW->>CDP: Page.captureScreenshot (jpeg, quality 80, fromSurface: true)
Note over SW: Bypasses captureVisibleTab to prevent active-window visual leaks and rAF hangs
else Active Foreground Tab
SW->>CDP: Page.captureScreenshot or captureVisibleTab fallback
end
CDP-->>SW: Raw Base64 Buffer
SW->>RingBuf: push (tabId, dataBase64, mimeType)
Note over RingBuf: Evicts older entry and enforces bounded O(1) memory
SW-->>Agent: MCP ToolResult with inline image payload
4. Deep Open Source Architectural Comparison
Below is a systematic comparison between BrowserClaw, browser-use, and midscene:
| Architecture Dimension | BrowserClaw (mcp-chrome) | browser-use | midscene |
|---|---|---|---|
| Primary Philosophy | Non-intrusive MCP copilot in user's live browser | Autonomous agent driving standalone Chromium | Visual AI & Multimodal UI Testing framework |
| Runtime Topology | Chrome MV3 Extension + Native Messaging + Fastify SSE | Python script controlling Playwright / remote CDP | Node.js / Puppeteer / Playwright / Web SDK |
| User Profile Reuse | Native: Uses existing Chrome session, logins, cookies, and tabs | Requires launching separate profile or remote debugging port | Typically launches fresh test browser contexts |
| Focus & Background Safety | Strict P0 Isolation: Tabs active: false, windows focused: false, zero focus stealing | Often brings tab to foreground; steals focus during typing | Focuses active viewport during test actions |
| DOM Tree Representation | Pruned hybrid DOM tree with interactive nodes, ARIA roles, bounding boxes, scrollable/dialog hints | Accessibility tree + filtered interactive elements | Multimodal bounding-box tree + visual prompt markers |
| Element Addressing | Unified 4-stage locator: ref (1-based) selector text/role coordinate | Numbered numeric tags (1, 2, 3...) or raw coordinates | Natural language query grounded via Vision Model |
| DOM Mutation Pollution | Zero DOM pollution: In-memory WeakRef Map prevents memory leaks | Modifies DOM with attributes/classes; overlays canvas | Injects highlight markers or overlays canvas |
| Coordinate Scaling | Automatic DPR & viewport scaling via ScreenshotContextManager | Playwright coordinate translation | Vision-model relative box coordinate conversion |
| Input Fidelity | CDP Input domain dispatches trusted events (isTrusted: true) | Playwright CDP synthetic/trusted events | Synthetic DOM dispatch / CDP mouse events |
| Screenshot Pipeline | Zero-disk in-memory pipeline: returned in MCP response; RingBuffer capacity 1; offscreen CDP for bg tabs | Writes PNG files to local disk directory | Memory buffer or temporary disk snapshots |
| Multi-Agent Isolation | SessionTabAffinityManager backed by chrome.storage.session binds agent sessions to specific tab IDs | Handled at process/agent instance level | Handled via separate runner contexts |
| Sensitive Data Masking | Built-in regex masking (โขโขโขโขโขโขโขโข) for passwords, credit cards, OTPs | No automatic input masking | Relies on external prompt masking |
| Native Protocol Defense | Enforces 1MB physical buffer ceiling on Native Messaging | N/A (Direct WebSocket CDP) | N/A (Direct DevTools / Playwright WebSocket) |
| MV3 Lifecycle Persistence | chrome.storage.session rehydrates tab affinity, groups, and favicons across SW restarts | N/A (Persistent daemon process) | N/A (Standard Node runtime) |
| CDP Domain Lifecycle | Domain-level reference counting (enableDomain/disableDomain) + core domain pinning (Page, Network) | Managed by Playwright driver | Ad-hoc domain commands |
| Debugger Anti-Hang | Immediate physical debugger detach (timeout-guard) bypassing refcount underflow | Process SIGKILL fallback | Process exit |
| Sender & DOM Security | Rejects messages with _sender.tab or invalid runtime.id; programmatic DOM nodes eliminate XSS | N/A (No browser extension context) | N/A (No browser extension context) |
| Multi-Frame Grounding | Multi-frame chrome_grep with hierarchical index remapping; cross-origin iframe coordinate guard | Playwright frame tree | Visual multimodal detection |
| Dynamic Profile Activation | Runtime activation via chrome_tool_docs across 8 categories without process restart (HTTP/SSE & Stdio) | Static tool definitions | Fixed testing API |
| In-Page JS Evaluation | Top-level await + automatic single-expression return (...) wrapping; sanitized output | page.evaluate | Assertion DSL |
| Navigation Settle | Event-driven chrome.tabs.onUpdated / onRemoved listener with settle watchdog | waitForLoadState | Fixed timeouts / sleep |
5. Architectural Decision Records (ADR)
ADR-001: Background Execution & Non-Intrusive Multi-Tab Isolation
- Status: Implemented & Verified (P0-1)
- Context: Autonomous agents executing long-running workflows previously stole focus from the human user by calling
windows.update({ focused: true })andtabs.update({ active: true }). - Decision:
- Default all agent-spawned tabs to
active: falseand windows tofocused: falseunless explicitly requested. - Permanently eliminate unconditional window/tab focusing calls across
common.ts,scroll.ts,batch-actions.ts. - Introduce explicit
chrome_attach_tabandchrome_detach_tabtools withdestructiveHint: trueand prominent documentation regarding Chrome's debugger warning banner.
- Default all agent-spawned tabs to
- Consequences: Agents operate invisibly in the background without interrupting the user's active keyboard or screen focus.
ADR-002: Zero-Disk In-Memory Screenshot Pipeline & Bounded Ring Buffer
- Status: Implemented & Verified (P0-2)
- Context: Screenshots were previously dumped to the host filesystem, accumulating disk bloat, leaking sensitive screenshots to shared storage, and slowing down response cycles with disk I/O.
- Decision:
- Return CDP
Page.captureScreenshotdirectly as Base64 image payloads in the MCP response (type: 'image'). - Maintain an in-memory
ScreenshotRingBufferwith a fixed capacity of 1 per tab, automatically evicting stale frames. - Default compression to JPEG 1280px. Disk writes (
savePng: true) are strictly opt-in for manual debugging. - For background tabs (
active: false), strictly use CDPPage.captureScreenshot(fromSurface: true) instead ofchrome.tabs.captureVisibleTab, preventing active-window screen leaks andrequestAnimationFramehangs.
- Return CDP
- Consequences: Zero disk writes, sub-100ms screenshot round-trips, zero visual leaks across background tabs, and zero memory leaks in the MV3 service worker.
ADR-003: Unified Locator Degradation Chain & Visual Fallback
- Status: Implemented & Verified (P1-4)
- Context: Agents frequently failed when relying solely on brittle CSS selectors or when index maps drifted after page re-renders.
- Decision:
- Implement a 4-tier degradation strategy:
ref(1-based index)selector(CSS/XPath)text/role(ARIA)coordinate(x, y). - The response always returns
resolutionPathindicating which strategy succeeded. - Coordinate clicks undergo pre-flight CDP
DOM.getNodeForLocation/DOM.getBoxModelinspection to ensure targets are visible and non-occluded.
- Implement a 4-tier degradation strategy:
- Consequences: Dramatic increase in execution resilience across dynamic SPAs, canvas apps, and legacy web pages.
ADR-004: Pure In-Memory WeakRef Mapping for Element Grounding
- Status: Implemented & Verified (P1-7)
- Context: In-page index tagging previously modified HTML element attributes (e.g.
data-mcp-index="1"), which breaks reactive frameworks (React, Vue, Solid), triggers unwanted MutationObserver loops, and leaks detached DOM nodes in Blink's C++ memory. - Decision:
- Use an isolated symbol-keyed
Map<number, WeakRef<Element>>inside the extension's execution context. - Never mutate host page DOM attributes.
- Provide structured diagnostic guidance (
DIAGNOSTIC_REFRESH_GUIDANCE) when an indexed element is collected or removed.
- Use an isolated symbol-keyed
- Consequences: Zero DOM pollution, 100% compatibility with sensitive reactive web applications, and prevention of memory leaks.
ADR-005: 1MB Physical Native Messaging Ceiling & Chunking Defense
- Status: Implemented & Verified (P0)
- Context: Chrome's Native Messaging host crashes immediately with
ERR_FAILEDor broken pipe when any single message payload exceeds $1024 \times 1024$ bytes. - Decision:
- Check byte length on both ends (
safePostMessagein Extension andNativeMessageHostin Node.js) before transmission. - Strictly block or truncate payloads exceeding 1000KB, returning structured error messages instead of terminating the pipe.
- Check byte length on both ends (
- Consequences: Permanently eliminated native host disconnects and process crashes caused by large DOM snapshots or uncompressed images.
ADR-006: High-Entropy Token Authentication for Local Fastify Bridge
- Status: Implemented & Verified (P0)
- Context: The local Fastify HTTP/SSE server binds to port 12306. Any malicious website or script running on localhost could make cross-origin requests to control the browser.
- Decision:
- Generate a cryptographically secure 256-bit token (
TOKEN_FILE) on native host initialization or readCHROME_MCP_TOKENfrom environment. - Validate
Authorization: Bearer <token>on all Fastify HTTP endpoints and SSE streams.
- Generate a cryptographically secure 256-bit token (
- Consequences: Complete protection against unauthorized local loopback access and DNS rebinding attacks.
ADR-007: Self-Driven Delta Piggybacking & In-Pipeline DOM Fingerprinting
- Status: Implemented & Verified
- Context: Traditional browser automation agents suffer from severe latency multiplication: each click or fill requires a subsequent
read_domcall to observe outcomes, doubling the network roundtrips and token consumption. - Decision:
- Introduce
includeDelta: trueinchrome_interact_index,chrome_fill_index, andchrome_batch_actions. - After physical action dispatch and settle buffering (150ms), the extension automatically extracts the latest element tree, executes fingerprint hashing against the previous snapshot baseline, and piggybacks the delta (
added,modified,removed,unchanged) directly inside the action's response payload.
- Introduce
- Consequences: Reduces agent execution roundtrips by 50% and drops inspection token costs to < 200 tokens when state remains unchanged.
ADR-008: 1:1 Agent Cursor Simulation & Zero-Orphan Tab Group Lifecycle
- Status: Implemented & Verified
- Context: Users working alongside an AI agent in the same browser need visual clarity on which tabs the agent owns, feedback on where the agent is clicking, and immediate seamless takeover when they physically touch the mouse or keyboard.
- Decision:
- Render a floating virtual cursor in an isolated closed Shadow DOM overlay with bezier trajectories, spring stretch physics, and instant fade-out upon physical human input.
- Group all agent-spawned tabs under a designated colored Chrome Tab Group (
TabGroupManager), with auto-naming derived from the task and automatic destruction of empty groups upon tab removal to eliminate orphan residue.
- Consequences: Smooth human-agent coexistence without UI interference or leftover workspace pollution.
ADR-009: MV3 Service Worker Session Storage Persistence (chrome.storage.session)
- Status: Implemented & Verified
- Context: In Chrome Manifest V3, background service workers terminate after ~30 seconds of idle time. In-memory manager states (
SessionTabAffinityManager,TabGroupManager, andTabFaviconManager) previously vanished across worker sleep/wake cycles, causing orphaned tab groups, broken multi-turn agent affinity, and unrestored favicons. - Decision:
- Persist
affinityMap,managedGroupIds, andoriginalFaviconstochrome.storage.session. - Asynchronously load cached states during manager instantiation and synchronize state modifications upon creation, mutation, and removal events.
- Clean up storage mappings when tabs or tab groups are destroyed.
- Persist
- Consequences: Total resilience against MV3 service worker dormancy, zero state loss across agent think-time pauses, and complete session cleanup upon tab closure.
ADR-010: CDP Domain Reference Counting & Anti-Hang Detachment Guard
- Status: Implemented & Verified
- Context: Multiple concurrent or chained tools calling
.enable/.disableon CDP domains (such asPageorNetwork) caused race conditions where one tool's cleanup disabled domains actively required by another tool or background monitor (inFlightRequests,waitForPageSettle, dialog listeners). In addition, unresponsive tabs caused debugger detachments to hang or refcounts to underflow. - Decision:
- Implement domain-level reference counting (
enableDomain/disableDomain) inCDPSessionManager. - Core domains (
Page,Network) are permanently pinned and never physically disabled while the CDP session remains attached. - Automatically intercept
*.enableand*.disablemethods insendCommandto route through reference counting. - Provide a fast-path
timeout-guarddetachment mode indetach(tabId, 'timeout-guard')and an explicitdetachDebugger(tabId)method that forcefully detach the physical debugger (chrome.debugger.detach) and clean up all sessions anddomainRefCountswithout refcount underflow.
- Implement domain-level reference counting (
- Consequences: Elimination of domain disabling race conditions, bulletproof dialog and settle monitoring, and guaranteed recovery on target hangs.
ADR-011: Strict Extension Message Sender Authentication, DOM XSS Hardening & Cross-Frame Isolation
- Status: Implemented & Verified
- Context: Unauthenticated message channels allowed malicious content scripts or rogue extensions to invoke privileged background tools via
chrome.runtime.sendMessage. Furthermore, interpolating human intervention reasons into HTML viainnerHTMLcreated potential DOM XSS injection vectors, while concurrent frame operations could cross-pollute the global WeakRef element index map. - Decision:
- In
chrome.runtime.onMessage, validate_sender.id === chrome.runtime.idand strictly reject messages where_sender.tabis present, blocking content scripts and external extensions from calling privileged background tool executors or accessing tokens. - In
agent-cursor.content.ts, replaceinnerHTMLtemplate strings with safe DOM creation APIs (document.createElement,document.createTextNode,textContent). - Isolate all UI overlays within a closed Shadow DOM.
- Isolate cross-frame messages by scoping execution strictly to target frames (
frameIds: [targetFrameId]) and isolating subframe element index ranges, preventing element map collisions and memory leakage.
- In
- Consequences: Full privilege boundary enforcement between unprivileged web page contexts and extension capabilities, completely neutralizing DOM XSS risks and preventing frame map pollution.
ADR-012: Multi-Frame Unified Index Remapping & Cross-Origin Coordinate Guard
- Status: Implemented & Verified
- Context: Complex modern applications embed nested and cross-origin iframes. Previous index trees and grep searches were restricted to the top frame or collided index numbers, while coordinate dispatches in subframes failed or misfired when iframe offsets were missing.
- Decision:
- In
chrome_grep, execute DOM pruning across all frames (allFrames: true), hierarchically remapping subframe element indices (currentIndex = elements.length + 1), and synchronizing subframe maps viainPageReindexFrame. - Expand grep attribute searching to query
placeholder,aria-label, andvalueproperties in addition to inner text and tag name. - In
chrome_batch_actions, detect cross-origin subframes viainPageGetFrameOriginand prevent unprojected coordinate dispatches when frame offsets are not available. - In
chrome_computer, directly alignleft_clickcoordinate actions to native CDP mouse events (Input.dispatchMouseEvent,isTrusted: true). - Fix macOS modifier key bitmask: map Command (Meta) to bitmask 4 (
mod = 4) instead of 8 across form-fill and batch-actions.
- In
- Consequences: Comprehensive coverage of iframe-heavy applications, accurate cross-origin coordinate execution, and native event fidelity.
ADR-013: Active Tab Close Protection & Confirmation Guard (chrome_close_tabs)
- Status: Implemented & Verified
- Context: Calling
chrome_close_tabswith an empty argument object ({}) previously closed the human user's currently active foreground tab without warning, causing catastrophic user tab loss during accidental or hallucinated tool calls. - Decision:
- In
chrome_close_tabs, require explicit confirmation (confirm: true) or session tab affinity whentabIdsandurlare omitted. - When session tab affinity exists (
sessionId), close the session-bound tab instead of the user's active foreground tab, and clean up the affinity mapping. - If neither
tabIds,url, norconfirm: trueare provided, return a descriptive error prompting the caller to specify tab IDs or confirm tab closure.
- In
- Consequences: Zero accidental closures of user active tabs while preserving autonomous closing of session-bound agent tabs.
ADR-014: Dynamic Profile Layering & Session-Level Tool Activation across Transports
- Status: Implemented & Verified
- Context: Different AI agent models have vastly different token window budgets. Standard monolithic MCP server exposing all 49 tools consumes ~19.5k tokens on
tools/list, which overwhelms smaller or faster reasoning models. At the same time, hardcoding static profiles (e.g.corewith 14 tools orcrawlwith 12 tools) prevented agents from dynamically discovering and invoking advanced debugging or network inspection capabilities when encountering complex edge cases. - Decision:
- Define 8 comprehensive tool categories in
TOOL_CATEGORIESacrosspackages/shared:navigate,perceive,act,observe,manage,diagnose,network, andcrawl. - Retain
chrome_tool_docsas an omni-present introspection tool across all profiles. - Implement
activateForSession: truesupport on both transports:- Fastify HTTP/SSE: dynamically registers extra tools to the client's dedicated
McpSessionManagerinstance. - Stdio Transport: maintains
dynamicExtraToolsset inmcp-server-stdio.ts, dynamically expanding bothtools/listandtools/callfilters for subsequent RPC requests.
- Fastify HTTP/SSE: dynamically registers extra tools to the client's dedicated
- Define 8 comprehensive tool categories in
- Consequences: Minimal initial token footprint (< 5.8k-11.5k tokens) with zero-restart, on-demand privilege and capability escalation during autonomous runs.
ADR-015: Single-Expression JavaScript Auto-Return & Event-Driven Page Load Settle
- Status: Implemented & Verified
- Context: Agents querying DOM properties or window state via
chrome_javascriptfrequently omit thereturnkeyword (e.g. executingdocument.titleorwindow.innerWidth), resulting inundefinedreturns and wasted reasoning turns. Furthermore, inchrome_get_web_content, fixedsetTimeout(resolve, 3000)sleeps wasted seconds on fast pages and raced dynamic renderers on slow connections. - Decision:
- In
chrome_javascript, implementdetectSingleExpression: automatically detect if the input code is a valid single JavaScript expression (stripping trailing semicolons and single/multi-line comments). If so, automatically wrap withreturn (...)inside the async execution block across both CDPRuntime.evaluateandchrome.scripting.executeScript. - In
chrome_get_web_content, replace fixed timer sleeps with event-driven tab lifecycle listeners (chrome.tabs.onUpdatedcheckingstatus === 'complete'andchrome.tabs.onRemoved), bounded by a 10-second timeout guard.
- In
- Consequences: 100% ergonomic parity for immediate agent evaluations and significantly reduced latency on page content extraction.
ADR-016: Production Hardening, Zero-Leak Lifecycles & Security Defense (v2.2.0)
- Status: Implemented & Verified
- Context: Comprehensive architectural audit identified critical gaps across runtime engines: in-page helper exports missing runtime symbols (
inPageWaitForDOMSettle,inPageCheckInterception,inPageDispatchSyntheticClick), snapshot caching dropping element arrays and overwriting subframe trees during delta diffing, unauthenticated backdoor params in agent control toggles, HttpOnly cookie filtering acting as a side-channel extraction oracle, native messaging host hanging on messages > 1MB, Canvas GPU texture leaks during screenshot stitching, and human intervention banners intercepting Enter keystrokes during text input. - Decision:
- In-Page Parity: Fully export
inPageWaitForDOMSettle,inPageCheckInterception, andinPageDispatchSyntheticClickfrominpage-engine.ts, bumping engine version. - Snapshot & Delta Restoration: Persist
mergedData.indexedElementsinto snapshot cache and propagate multi-frame remappings (allFrames: true), ensuring accurate delta calculation without frame overwrite. - Security & Sandbox Hardening:
- Remove
__admin_bypass__backdoor from agent control toggle. - Prevent HttpOnly cookie extraction oracle by forbidding value substring filtering on HttpOnly cookies.
- Enforce strict 1MB ceiling in
native-messaging-host.tswith atomic error responses, eliminating stdin hang on oversized headers.
- Remove
- Resource & Memory Leak Prevention:
- Explicitly close
ImageBitmapinstances (img.close()) inimage-utils.tstry/finally blocks, releasing unmanaged GPU textures. - Automatically clean up
interceptApiStoreandscreenshotContextManageronchrome.tabs.onRemoved. - Schedule periodic
cleanupOldFiles()in native server and unref timer.
- Explicitly close
- Tooling & Ergonomics:
- Eliminate Service Worker loopback messaging (
chrome.runtime.sendMessageto self) in favor of direct callback delivery (sendFileOperationToNative). - Tighten
chrome_smart_scrollcontainer-aware discovery and filter out roothtml/bodycontainers to ensure Shadow DOM TreeWalker execution. - Guard human intervention keyboard listener to ignore Enter keys when typing in input, textarea, or contenteditable fields.
- Enforce
searchStartTimewindow on download waiter to avoid capturing stale in-progress downloads. - Optimize
run_host.batcold start by replacing slow PowerShell subprocesses with pure cmd string substitution.
- Eliminate Service Worker loopback messaging (
- In-Page Parity: Fully export
- Consequences: 100% test pass rate across extension and bridge suites, zero memory or file leaks, strict security boundaries, and significantly reduced cold start and batch action latency.
ADR-017: High-DPI Viewport Normalization & True 1:1 Visual Coordinate Grid (v2.3.0)
- Status: Implemented & Verified
- Context: In environments with Windows display scaling (e.g. 150% scaling, devicePixelRatio = 1.5) or Retina displays, chrome_screenshot previously defaulted to Page.getLayoutMetrics layoutViewport (measured in device physical pixels: e.g. 2561x1347). However, Chromium's CDP Page.captureScreenshot accepts clip bounds in CSS (device-independent) pixels. Passing inflated physical dimensions caused Chrome to render beyond the actual web surface, producing massive black/white borders, shrinking the webpage into a small box, and skewing visual coordinate grids by 1.5x.
- Decision:
- Refactor viewport metrics priority in screenshot.ts: prioritize metrics.cssVisualViewport and metrics.cssLayoutViewport (exactly matching CSS viewport dimensions like 1707x898), falling back to layoutViewport only in catastrophic anomalies.
- Enforce 1:1 OffscreenCanvas normalization to guarantee that every coordinate label (x, y) on chrome_screenshot({ grid: true }) maps with 100% mathematical fidelity to DOM getBoundingClientRect() and CDP physical pointer coordinates.
- Consequences: Zero visual distortion, complete elimination of black borders on high-DPI monitors, and seamless visual coordinate targeting for multimodal agents.
ADR-018: Anti-Bot Natural Kinematics, Settling Latency & Extended Hold Duration (v2.3.0)
- Status: Implemented & Verified
- Context: Rigorous anti-bot forensic inspection suites (such as Nexus Protocol 12-Sector Exam) detect automated agents via sub-20ms click press intervals (INSTANT_CLICK) and missing cursor arrival vectors (NO_POINTER_PATH). Previously, action: 'click' leaped instantly to target points and released in 0-45ms, and holdMs was hard-capped at 500ms, failing industrial Hold to Arm buttons and charging triggers.
- Decision:
- In interact-index.ts, enforce a 6-point natural approach trajectory (decelerating smoothly within a 65px radius) before pressing.
- Introduce an ergonomic 80-120ms physiological settling pause (prePressDelayMs) between cursor arrival and mechanical button press.
- Broaden holdMs capacity from 500ms up to 3000ms, enabling millisecond-accurate long-press holds (e.g. 2004ms on Sector 06 Temporal Maze).
- Consequences: Clean trusted verdicts on forensic inspection systems, zero INSTANT_CLICK flags on physical clicks, and flawless execution of time-windowed hold interactions.
ADR-019: Full-Spectrum Drag Architecture & Background Tab Delivery Self-Healing (v2.3.0)
- Status: Implemented & Verified
- Context: Web automation encounters two fundamentally distinct drag paradigms: (1) HTML5 Native Drag-and-Drop (dragstart/dragover/drop) used in file wells, and (2) Pointer/Mouse Drags (pointerdown/pointermove/pointerup) used in canvas drawing, custom sliders, SVG corridors, and list reordering. Previously, BrowserClaw intercepted drags unconditionally, breaking pointer drags, while background tab throttling caused Chromium to drop CDP input when users were browsing other tabs.
- Decision:
- Decouple drag execution: route HTML5 drags through CDP Input.setInterceptDrags only when dnd: true; for pointer/gesture drags, execute uninterrupted pressed mouse movements with button: 'left', buttons: 1 along multi-point path sequences.
- Extend Click Probe Fallback to visual coordinates: when Chromium background tab throttling drops CDP events (probe reports delivered: false), automatically resolve the target element via document.elementFromPoint(x, y) and dispatch synthetic in-page clicks, ensuring 100% action delivery even on non-active background tabs.
- Expand chrome_fill_index with pressEnter: true, cutting agent search and auth round-trips by 50%.
- Consequences: High-fidelity execution across HTML5 drops, list reordering, and multi-point path corridors, paired with resilient background tab automation with Click Probe fallback.
ADR-020: Windows Process Teardown, Unref Watchdog & Keep-Alive Socket Severance (v2.3.8)
- Status: Implemented & Verified
- Context: On Windows, Chrome launches the Native Messaging host via
run_host.bat. When Chrome terminated,http.Server.close()inside Fastify was invoked. Under Node.js HTTP server semantics,close()waits for all active and idle keep-alive TCP connections to finish before firing the callback. If an MCP client (Cursor, Claude Desktop, or Windsurf) held an open TCP socket or SSE connection,stop()returned a Promise that remained pending forever. Becauseprocess.exit(0)was nested withinstop().then(), the Node.js process remained running as an invisible zombie process, holding port 12306 and causing subsequent startup attempts to fail withEADDRINUSE. - Decision:
- In
server/index.tsstop(), invokethis.fastify.server.closeAllConnections()(Node.js 18.2.0) to immediately sever all open keep-alive HTTP/SSE sockets. - In
native-messaging-host.tscleanup(), install an unreferenced 1000ms watchdog timer:setTimeout(() => process.exit(0), 1000).unref().
- In
- Consequences: Guaranteed process exit within 1000ms on browser termination, zero zombie processes, and 100% elimination of port 12306 contention on Windows.
ADR-021: Strict Polymorphic Coordinate JSON-Schema Disjunction & Ajv 8+ Strictness (v2.3.8)
- Status: Implemented & Verified
- Context: Across coordinate tools (
chrome_computer,chrome_interact_index,chrome_smart_scroll,chrome_burst_interact, andchrome_batch_actions), coordinate parameters were declared with a top-leveltype: 'object'and top-levelrequired: ['x', 'y'], with an inneroneOfattempting to permit array coordinates[x, y]. In strict JSON Schema validators (Ajv in strict mode, as used by Claude Desktop, Cursor, and Windsurf), this triggered schema compilation warnings and outright validation failures whenever an agent supplied an array coordinate. - Decision:
- Strip top-level
type: 'object'and top-levelrequired: ['x', 'y']from the outer property definition. - Encapsulate validation constraints cleanly within
oneOf: Branch 1 enforces{ type: 'object', properties: { x, y }, required: ['x', 'y'] }, while Branch 2 enforces{ type: 'array', items: { type: 'number' }, minItems: 2, maxItems: 2 }. - Ensure execution dispatchers (
parseUnifiedCoordinateandresolveTargetLocation) handle both formats natively with subframe offset projection.
- Strip top-level
- Consequences: 100% Ajv / MCP strict validator compliance for both object and array coordinates, eliminating agent parameter rejection.
ADR-022: Background Tab Compositor Throttle Resilience & Cooldown Circuit-Breaker (v2.3.8)
- Status: Implemented & Verified
- Context: When targeting non-active/background tabs (
active: false), Chromium suspends compositor frame generation. CDPInput.dispatchMouseEvent(mouseWheel)commands do not acknowledge frame commits and block execution for up to 3000ms before timing out. Furthermore, a 60-second cooldown cache remained sticky even when the human user focused the tab or navigated to a new URL. - Decision:
- In
smart-scroll.ts, detect background tab status (isBackground = !tab.active). For background tabs, immediately bypass CDP mouseWheel and invoke in-page JavaScript smooth scrolling. - Implement a cooldown circuit-breaker: if a CDP wheel dispatch times out, skip CDP for 60 seconds.
- Register tab lifecycle listeners on
chrome.tabs.onActivated,chrome.tabs.onUpdated, andchrome.tabs.onRemovedto invalidate the cooldown cache immediately upon user focus or page reload.
- In
- Consequences: Elimination of 3000ms latency stalls on background scrolling, seamless transition to hardware-accelerated CDP wheel dispatch when tabs are focused, and zero memory leaks.
ADR-023: Hierarchical Dual-Brain Architecture & Semantic Micro-Loop with Three-Tier Engine Fallback (v2.8.0)
- Status: Implemented & Verified
- Context: In standard single-loop browser automation, generalist LLMs (Claude, GPT-4, Gemini) operate as the sole decision maker for every atomic DOM action. This introduces 2,000โ5,000ms round-trip latency per interaction, high token consumption, and rapid context window exhaustion. Tasks involving repetitive or deterministic micro-steps (form filling, menu navigation, multi-field submission) suffer severe throughput degradation. Conversely, pure rule-based engines lack semantic intent understanding across diverse web interfaces.
- Decision:
- Hierarchical Dual-Brain Architecture: Establish a Fast/System 1 Native Semantic Micro-Loop (
chrome_act_toward_goal, 200โ400ms/step) executing directly inside the Native Server, while Slow/System 2 Generalist LLMs retain macroscopic strategy, goal formulation, and supervisory steering. - Three-Tier Engine Degradation Ladder:
- Tier 1 (Semantic Probabilistic): TypeSafe Jev via 7 parallel structured questions (action Choice, click_target Choice, type_target Choice, select_target Choice, goal_done Noul, stuck Noul, destructive Noul) evaluated against a strict compact DOM budget (\le\250 lines, \le\120 chars/line, \le\24KB total payload, sensitive password/file fields scrubbed).
- Tier 2 (Heuristic Fast Fallback): Zero-dependency tokenization scoring with CJK bigrams, exact/substring matching (+2.0), role bonuses (button, textbox, combobox, link), and confidence separation ratio when Jev is unavailable, 401 unauthenticated (session latched), quota exhausted, or network severed.
- Tier 3 (Macro Escalation): Controlled escalation back to System 2 upon encountering low confidence (), destructive actions (
pay,delete,purchase,submit,confirm), repeated action loops (\ge\3 identical actions without DOM mutation, URL change, or visualDiff), or step budget exhaustion (\le\10 steps).
- Two-Stage
<select>Primitive: Leverage Jev Score primitive to inspect<select>options dynamically and select the optimal value without DOM mutation race conditions, returning full token usage and candidate shortlisting for dropdowns with options. - Zero Extension Changes: Execute the semantic micro-loop entirely on the Native Server process via internal IPC dispatch (
callToolInternal), maintaining absolute Manifest V3 extension boundary isolation. - Threshold Rationales:
- Action Confidence : Filters weak random actions while allowing confident navigation.
- Target Confidence & Top Prob : Prevents ambiguous clicks between competing elements; separation ensures clear intent.
- Goal Accomplished ( / Heuristic Coverage ): Tight threshold ensuring the goal is definitively achieved before stopping.
- Stuck Circuit-Breaker ( & 3 Consecutive Unchanged Steps with , , and ): Eliminates infinite looping on unresponsive elements while avoiding false positives on visual canvas updates.
- Destructive Guard ( & 14 Built-in Keywords): Zero-tolerance safety guard protecting user financial and state assets.
- Execution Budgets:
maxStepsdefaults to 10 (hard cap 60 in Jev mode, forced in Heuristic mode) andtimeoutMsdefaults to 90s (hard cap 300s) to prevent unbounded token expenditure.
- Hierarchical Dual-Brain Architecture: Establish a Fast/System 1 Native Semantic Micro-Loop (
- Consequences: 10x interaction acceleration for common deterministic workflows, seamless zero-downtime degradation across network or credential anomalies, and complete protection of user assets via safety escalations.