Dev Browser
SkillWeb & browsingLets your agent control a Chrome browser with saved logins and sessions when other browser tools are blocked.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Dev Browser skill
About this capability
Fallback browser automation with persistent Chrome state. Use only when Browser Use is unavailable or blocked.
What this skill tells your AI
The instructions your AI receives, as published by udecode/plate in .agents/skills/dev-browser/SKILL.md and read by ahel’s review.
Use this only as the fallback browser path when [@browser-use](plugin://browser-use@openai-bundled) is unavailable or blocked.
Do not substitute Puppeteer, standalone Playwright, or raw Chrome DevTools for this fallback path.
Installation
npm install -g dev-browser
dev-browser install
Run dev-browser --help to learn more.
Plate Defaults
- Use
dev-browser --connect http://127.0.0.1:9222by default. Do not preflight9222first. - Only inspect
9222after a directdev-browser --connect http://127.0.0.1:9222attempt fails. - Reuse one persistent debug Chrome on
127.0.0.1:9222. Do not spin up disposable browser instances unless the user asks. - Use a dedicated Chrome
--user-data-dirfor that debug browser, not the user's normal daily Chrome data dir. - Clone the signed-in Chrome profile into the dedicated debug dir, then launch the debug browser from that clone.
- On macOS, launch the debug browser with
open -na "Google Chrome" --args ... --remote-debugging-port=9222so it opens as a separate Chrome instance without hijacking the user's normal window. - Do not close or stop the user's connected debug browser. Leave that debug window open and reuse it. Close named pages only when needed.
- Keep scripts small and direct. Prefer
browser.getPage("persistent-main")for the main app. - Use
dev-browserinstead ofagent-browseror next-devtoolsbrowser_eval. - For Plate registry/browser proof, prefer
/blocks/[id]-demoover docs wrappers when that standalone demo route exists. - If
dev-browsergets blocked by a human prompt or loops on the same step, stop and ask the user to unblock.
Fallback Setup
Use this only after dev-browser --connect http://127.0.0.1:9222 fails because no reusable debug Chrome is available or the CDP endpoint is broken.
Rules
- Prefer one permanent debug browser/profile over disposable automation browsers.
- Treat a custom
--user-data-diras mandatory, not optional. Chrome 136+ expects remote debugging to happen from a dedicated profile. - Keep auth in that profile. Do not fall back to cookie dumps or state files unless the user asks.
- Use a separate signed-in Chrome profile for browser work, like
dev. Do not use the user's normal dailyDefaultprofile as the source profile. - Clone that separate signed-in Chrome profile into the dedicated debug
--user-data-dir; do not point9222straight at the user's daily Chrome data dir. - On macOS, use
open -na "Google Chrome" --args ...for the debug browser. That starts a separate Chrome instance with the dedicated debug profile without touching the user's normal Chrome window.
Preferred Shape
Use a dedicated browser/profile with:
--remote-debugging-address=127.0.0.1--remote-debugging-port=9222- a persistent
--user-data-dir=<debug-profile-dir>
Sign in once in that dedicated browser and keep reusing it for agent work.
Quick sanity check:
curl -sS http://127.0.0.1:9222/json/version
Healthy output includes a JSON object with webSocketDebuggerUrl. Empty output or 404 means the wrong process owns 9222.
Then verify:
dev-browser --connect http://127.0.0.1:9222 <<'EOF'
const page = await browser.getPage("persistent-main");
console.log(await page.title());
EOF
If direct connect still cannot resolve CDP even though /json/version is healthy, connect with the exact websocket URL:
WS=$(curl -sS http://127.0.0.1:9222/json/version | jq -r '.webSocketDebuggerUrl')
dev-browser --connect "$WS" <<'EOF'
const page = await browser.getPage("persistent-main");
console.log(await page.title());
EOF
Google Chrome Path
Default setup on macOS:
- Pick a separate signed-in Chrome profile for agent work, like
dev, not the dailyDefaultprofile. - Map that human-facing Chrome profile name to the real folder in
Local State. - Clone that profile into the dedicated debug dir.
- Launch a separate Chrome instance on
9222. - Leave that debug window open and reuse it.
python3 - <<'PY'
import json, pathlib
p = pathlib.Path('~/Library/Application Support/Google/Chrome/Local State').expanduser()
obj = json.loads(p.read_text())
for key, val in obj.get('profile', {}).get('info_cache', {}).items():
print(f"{key}\tname={val.get('name')}\tgaia_name={val.get('gaia_name')}")
PY
# Example: if `dev` maps to `Profile 1`, clone `Profile 1`.
mkdir -p "$HOME/.config/google-chrome-debug-profile/Default"
rsync -a --delete \
--exclude='Singleton*' \
--exclude='DevToolsActivePort' \
--exclude='lockfile' \
"$HOME/Library/Application Support/Google/Chrome/Profile 1/" \
"$HOME/.config/google-chrome-debug-profile/Default/"
cp "$HOME/Library/Application Support/Google/Chrome/Local State" \
"$HOME/.config/google-chrome-debug-profile/Local State"
open -na "Google Chrome" --args \
--user-data-dir="$HOME/.config/google-chrome-debug-profile" \
--profile-directory="Default" \
--remote-debugging-address=127.0.0.1 \
--remote-debugging-port=9222
Do not point 9222 at the normal daily Default Chrome profile.
If the wrong Chrome steals 9222, identify it with:
lsof -nP -iTCP:9222 -sTCP:LISTEN
Kill that listener and relaunch the dedicated debug browser. Do not keep debugging against a stale 404 or empty /json/version owner.
Signals
- GitHub stars
- 17k
- Forks
- 996
- Last commit
- Sep 2026
- Hacker News mentions
- 1
ahel review
K1binfo
installs-packages
Automated review, not a security audit. Ruleset v1+k2.
Others that do the same job
Advanced
- Catalog kind
- skill
- Gateway key
dev-browser-udecode- Source
- github.com/udecode/plate