The Problem

Developers who want an LLM to drive a browser must stitch together a Chrome DevTools Protocol (CDP) client, a long‑running daemon, and a set of ad‑hoc helper functions. Maintaining that glue code is tedious, error‑prone, and hard to reuse across projects.

What This Does

browser-harness provides a minimal, self‑healing harness that exposes a handful of Python helpers (helpers.py) and a daemon (daemon.py) over a single CDP websocket. The LLM can edit the helpers on‑the‑fly, add missing steps, and continue without a heavyweight framework.

  • Core files – run.py launches the environment, helpers.py (~195 LOC) implements actions like upload_file, click, and js. admin.py and daemon.py (~361 LOC total) bootstrap the daemon, manage the CDP connection, and handle remote‑debugging.
  • Skills – over 60 markdown skill files under domain-skills/ and interaction guides under interaction-skills/ describe selectors and flows for specific sites (e.g., domain-skills/amazon/product-search.md). The LLM writes new skill files automatically; the repo does not ship executable code for each site.

How It Is Wired

Execution starts at daemon.py:134 in the start function. start reads the Chrome DevTools port file (DevToolsActivePort) and calls get_ws_url, which builds the CDP websocket URL (filesystem read).

main (daemon.py:218) invokes serve, which creates the daemon socket, then calls attach_first_page (line 111). attach_first_page calls log (via helpers.py) and cdp to send CDP commands.

Key internal call hubs (from the measured call graph):

  • cdp – invoked 15 times from helpers (press_key, switch_tab, click, js, upload_file).
  • log – invoked 7 times, central for diagnostics.
  • _send – low‑level wrapper used 4 times for outbound HTTP calls.

External effects:

  • Filesystem – start reads DevToolsActivePort; main deletes the socket file with os.unlink.
  • Network – _send in helpers.py performs HTTP requests (no timeout).
  • Subprocess – admin.py runs external commands (e.g., launching Chrome).

The import graph is flat (4 modules, 2 import edges) with no circular dependencies, making the codebase easy to navigate but also indicating a single point of failure around daemon.py and helpers.py.

How To Use It

# Clone the repo
git clone https://github.com/moses-y/browser-harness
cd browser-harness

# Install Python dependencies (pyproject.toml)
pip install .
# Or, with uv for reproducibility (once a lockfile exists)
# uv pip install --frozen-lockfile .

# Copy example environment
cp .env.example .env   # adjust values as needed (e.g., CHROME_PATH)

# Start the daemon (runs Chrome in remote‑debug mode)
python -m daemon start

# Run a one‑off script with helpers pre‑loaded
python run.py          # entry point that loads helpers into the REPL

The README’s “Setup prompt” (install.md & SKILL.md) should be read for detailed browser‑connection steps. No CI, Dockerfile, or test suite is present, so manual validation is required before production use.

Real‑World Use

A SaaS platform that needs to scrape product listings can spin up the harness, invoke helpers.upload_file or helpers.click from an LLM‑generated script, and let the agent auto‑generate a new domain-skills/ markdown file when it encounters a novel page layout. The platform only needs to maintain the Python daemon and ensure Chrome is reachable on the configured port.

Code Health & Issues

  • High – missing lockfile – pyproject.toml declares dependencies but no poetry.lock/requirements.txt.
  • Medium – no Dependabot – repository lacks .github/dependabot.yml; advisory updates are manual.
  • Medium – outbound request timeout – helpers.py calls requests without timeout= (admin.py also).
  • Medium – file opened without context manager – admin.py, helpers.py, daemon.py use open(...) directly.
  • Medium – broad exception handling – same three files catch generic Exception.
  • Medium – deep nesting & duplicated blocks – admin.py and daemon.py contain 6‑level indentation and repeated 6‑line code fragments.
  • SDLC gaps – no tests, no CI pipeline, no Dockerfile. License is present.

The Bottom Line

browser-harness delivers a lean, editable CDP bridge that lets an LLM control a browser with minimal scaffolding. Its simplicity and flat module graph are strengths for rapid prototyping, but the lack of tests, CI, a lockfile, and robust error handling make it unsuitable for production without additional engineering effort. Teams comfortable adding their own test suite, CI, and hardening the helpers can extract considerable value from the core harness.