One stealth Chromium. Eight coding agents. One command.
English | 한국어
A one-command setup that lets your local coding agent drive a real GUI Chromium that passes common automated-browser detection (e.g. navigator.webdriver, Cloudflare Turnstile interactive challenges). Combines CloakBrowser as the stealth engine, Playwright as the automation CLI, and per-harness adapters so every supported agent uses the same browser.
Important: this repo is integration glue, not a stealth browser. All bot-bypass work is done by CloakBrowser. If that is what you need, install it directly.
Disclaimer. Intended for testing your own sites, authorized QA, internal automation, and local agent workflows. Respect each target site's Terms of Service and
robots.txt. Do not use this to bypass authentication, create accounts at scale, scrape protected resources, or otherwise violate site terms. You are responsible for how you use it.
![]() one command ./install.sh detects every supported harness |
![]() verified webdriver=false, plugins=5, real window.chrome
|
![]() passes bot.sannysoft.com all automation fingerprint checks green |
┌──────────────────────────────────────────────────────────────────┐
│ Your coding agent (pi · Claude Code · Codex · opencode · │
│ Gemini · Kiro · Amp · Crush) │
└──────────────────────────────────────────────────────────────────┘
│
│ reads its rule file written by
│ install.sh (CLAUDE.md / AGENTS.md /
│ GEMINI.md / BROWSER_RULE.md / …)
▼
┌──────────────────────────────────────────────────────────────────┐
│ pi-playwright (the `pw.js` CLI runner — npm: pi-playwright) │
└──────────────────────────────────────────────────────────────────┘
│
│ reads
▼
┌──────────────────────────────────────────────────────────────────┐
│ ~/.playwright/cli.config.json ◀── single shared launch config │
└──────────────────────────────────────────────────────────────────┘
│
│ launches
▼
┌──────────────────────────────────────────────────────────────────┐
│ CloakBrowser (stealth Chromium binary, headed by default) │
└──────────────────────────────────────────────────────────────────┘
This kit is the wiring in between — install.sh, the harness rule files,
the shell wrappers, the config template. Nothing else.
The installer detects which of these are present and configures each one. Any combination works — install pi today, add Claude Code tomorrow, run ./install.sh again.
![]() pi earendil-works/pi |
![]() Claude Code anthropics/claude-code |
![]() Codex CLI openai/codex |
opencode anomalyco/opencode |
|
Gemini CLI google-gemini/gemini-cli |
Kiro kirodotdev/Kiro |
Amp sourcegraph/amp |
![]() Crush charmbracelet/crush |
What each harness gets:
| Harness | Browser rule lives in | How it's injected |
|---|---|---|
| pi | ~/.pi/BROWSER_RULE.md + ## Browser section in ~/.pi/agent/AGENTS.md |
AGENTS.md auto-loads into every session's system prompt |
| Claude Code | ~/.claude/CLAUDE.md (## Browser section) |
Auto-loaded as global context file |
| Codex CLI | ~/.codex/AGENTS.md (## Browser section) |
Auto-loaded as global agent file |
| opencode | ~/.config/opencode/AGENTS.md (## Browser section) |
Auto-loaded as global agent file |
| Gemini CLI | ~/.gemini/GEMINI.md (## Browser section) |
Auto-loaded as global memory |
| Kiro | ~/.kiro/steering/browser.md |
Global steering file, auto-loaded into every interaction |
| Amp | ~/.config/AGENTS.md (## Browser section) |
Loaded as user-level agent file |
| Crush | ~/.config/crush/CRUSH.md (## Browser section) |
Loaded as user-level memory file |
Detection is non-destructive: if a harness is not installed, its section is skipped. Existing files are merged (a ## Browser section is replaced if present) and backed up.
prompts/BROWSER_RULE.md ships with trigger-word lists in English, Korean, Japanese, Chinese, and Spanish so the rule fires regardless of which language the user prompts in. If you only ever prompt in one or two languages, you can delete the other bullets from the ## Trigger words section after install — it slightly trims the system prompt, but leaving them in is harmless. The marker comments (<!-- browser-harness-kit:begin --> / :end) only protect the boundaries; the content between them is yours to edit.
Note on shared files: Amp and Crush both honor ~/.config/AGENTS.md as a generic user-level agent file. If you use both, the same file serves both — the installer only writes the section once.
Getting an LLM coding agent to actually open and use a real browser on WSL2 has several rough edges:
- Playwright's bundled Chromium leaks automation signals and gets blocked.
- A real headed window is not the default —
--headedalone is not enough. - The agent often refuses ("no browser tool") or runs
open/xdg-openand freezes the Bash tool. - Snapshot files can blow up the context window.
- Daemons go zombie and the next command hangs.
This repo packages a single install script and a small set of config files that resolve all of the above, across every harness it detects.
Requirements:
- WSL2 with WSLg (or native Linux X11/Wayland)
- Node 20+
- At least one supported harness installed
- A Playwright CLI runner — see below
This kit configures Playwright to use the CloakBrowser binary, but it does not install Playwright itself. Pick one:
-
For pi users (recommended):
pi install npm:pi-playwright
Provides a ready-to-use
pw.jsat$(npm root -g)/pi-playwright/skills/playwright-browser/scripts/pw.js. -
For everyone else: install
@playwright/test(or any other tool that runs Playwright commands via~/.playwright/cli.config.json) globally. The kit's only requirement is that something on the machine calls Playwright — the shared config file is what redirects it to CloakBrowser.npm i -g @playwright/test npx playwright install-deps # Linux system libs only; binaries come from CloakBrowser
If you skip this step, install.sh still finishes successfully, but agents will fail at the first node $PW ... call with Cannot find module.
git clone https://github.com/Blue-B/browser-harness-kit.git
cd browser-harness-kit
./install.shThe installer:
- Installs
cloakbrowserglobally and downloads the stealth Chromium binary. - Installs Chromium system dependencies.
- Writes
~/.playwright/cli.config.jsonpointing Playwright at the CloakBrowser binary withheadless: false. - Detects installed harnesses and writes the appropriate browser-rule file for each one (table above).
- Installs shell wrappers in
~/bin/that block directchromium-browser/open/xdg-openand tell the agent which command to use instead.
Existing files are backed up before modification.
Note: The installer does not install
pi-playwrightor@playwright/testfor you. That is intentional — different harnesses have different preferred Playwright runners, and this kit only owns the integration layer between them and CloakBrowser.
In a new shell:
PW=$(npm root -g)/pi-playwright/skills/playwright-browser/scripts/pw.js # if pi-playwright is installed
# or any harness's preferred way to invoke playwright-cli — the underlying binary is the same.
node $PW -s=check open https://example.com --headed --persistent
node $PW -s=check evaluate "() => ({webdriver: navigator.webdriver, plugins: navigator.plugins.length, hasChrome: !!window.chrome})"
node $PW kill-allExpected: { webdriver: false, plugins: 5, hasChrome: true }. If webdriver: true, the CloakBrowser binary is not being used — check ~/.playwright/cli.config.json.
To confirm actual Cloudflare Turnstile pass-through:
node $PW -s=check goto https://nopecha.com/demo/cloudflareUser: "open this site"
→ Agent (LLM) reads the browser rule from its harness's config file
→ runs: node $PW open https://... --headed
→ pi-playwright (or direct playwright-cli) handles the command
→ playwright-cli reads ~/.playwright/cli.config.json
→ launches /home/you/.cloakbrowser/chromium-*/chrome (stealth, headed)
→ real window appears on the desktop
The key file is ~/.playwright/cli.config.json — it is shared by every harness because Playwright's CLI is the same binary regardless of who invokes it. The per-harness work is just teaching each agent's instruction surface that the browser exists and how to call it.
| Path | Shared? | Purpose |
|---|---|---|
~/.cloakbrowser/chromium-*/chrome |
yes | Stealth Chromium binary (managed by cloakbrowser) |
~/.playwright/cli.config.json |
yes | Tells Playwright to use the CloakBrowser binary, headed mode on |
~/bin/{chromium-browser,chromium,google-chrome,open,xdg-open} |
yes | Wrappers that block direct browser launches |
~/.pi/BROWSER_RULE.md + ~/.pi/agent/AGENTS.md ## Browser section |
pi only | AGENTS.md auto-loaded by pi every session |
~/.claude/CLAUDE.md ## Browser section |
Claude Code only | Global context file |
~/.codex/AGENTS.md ## Browser section |
Codex CLI only | Global agent file |
~/.config/opencode/AGENTS.md ## Browser section |
opencode only | Global agent file |
~/.gemini/GEMINI.md ## Browser section |
Gemini CLI only | Global memory file |
~/.kiro/steering/browser.md |
Kiro only | Global steering file |
~/.config/AGENTS.md ## Browser section |
Amp only (also read by Crush if present) | User-level agent file |
~/.config/crush/CRUSH.md ## Browser section |
Crush only | User-level memory file |
Bypass for the user (any shell): PI_BROWSER_BYPASS=1 chromium-browser ....
CloakBrowser describes itself as a "Drop-in Playwright/Puppeteer replacement". It ships a stealth engine and an SDK, and intentionally delegates page-automation APIs to Playwright/Puppeteer. It has its own CLIs (python -m cloakbrowser, cloakserve for CDP), but a one-liner like "open URL → click → screenshot" lives in Playwright (or Puppeteer) land.
So the natural combination is:
- CloakBrowser — patched Chromium binary = stealth engine
- Playwright — automation CLI/daemon = one-liner interface that every harness can call via Bash
- This repo — wires the two together, plus per-harness instruction files so each agent actually knows it has a browser, plus shell guards against agents reaching past the official path
Hosted services (Browserbase, Steel, etc.) solve the same problem, but cost money and require sending pages off-machine. This setup keeps everything local.
See docs/harness-compat.md for full details on how the rule is injected for each harness and what trade-offs apply.
Short version: pi is the only harness with a true --append-system-prompt option, which places the rule at the strongest position in the prompt stack. For other harnesses, the rule lives in a context file (CLAUDE.md, AGENTS.md, CRUSH.md, GEMINI.md, Kiro steering files, etc.) — which is reliable in practice but theoretically softer than a direct system-prompt addition.
| Symptom | Fix |
|---|---|
| Browser opens but is invisible | ~/.playwright/cli.config.json is missing "headless": false |
| Agent says "no browser tool" | The harness has not loaded the rule — open a new shell, or check the relevant file from the table above |
Bash tool hangs after open ... |
~/bin/open wrapper is missing — re-run the installer |
| Snapshot files blow up context | Tell the agent not to Read .playwright-cli/page-*.yml |
| Zombie chrome processes | node $PW kill-all, then pkill -9 -f cloakbrowser if needed |
| Site still blocks in headed mode | See CloakBrowser's README on Xvfb |
See docs/troubleshooting.md for the full list.
- Stealth failure (a site detects the browser) → file at CloakBrowser. That is not this repo's layer.
- Playwright CLI/daemon bug → Microsoft Playwright.
- Harness-specific behavior (the agent ignores its own rules, etc.) → file at the harness repo first.
- Installer, configs, shell wrappers, or docs in this repo → file here.
| Component | Role | License |
|---|---|---|
| CloakBrowser | Stealth Chromium engine. All bypass capability is theirs. | MIT |
| Playwright | Browser automation CLI and daemon | Apache-2.0 |
| pi-playwright | Playwright wrapped as a pi skill (optional but recommended for pi users) | MIT |
| Supported harnesses | See table above | various |
| This repo | Install script, shared config, per-harness adapters, shell wrappers, docs | MIT |
If the installer, the per-harness adapters, or the docs in this repo saved you setup time, supporting this project directly accelerates maintenance:
- Your support helps: new harness adapters, cross-distro install testing, screenshot updates as upstream Chromium ships new versions, and faster issue response.
- Transparency: funds go to maintenance time, infra for testing on multiple distros / WSL setups, and small-dollar Sponsors stay one-time donations — no obligations.
- One-time sponsors are credited in the README (opt-out available).
- Monthly sponsors ($3/mo via GitHub Sponsors) also get best-effort priority triage for "Sponsor Request" issues.
Upstream projects (CloakBrowser, Playwright, pi-playwright, each harness) are listed in Credits — please support them through their own channels.
Intended for personal automation, internal tooling, QA, and local agent workflows on sites you own or are authorized to test against. Not intended for:
- mass scraping in violation of site terms,
- account creation farms, credential stuffing, or any abuse automation,
- bypassing access controls on content you do not have rights to,
- any use that would violate a target site's ToS at scale.
When in doubt, ask the site operator or use their official API. The maintainers of this repo and of the upstream components do not endorse or support abusive use.






