chrome-relay
Original:🇺🇸 English
Translated
Use when an agent needs to operate the user's real Chrome session — listing tabs, reading the page, clicking, filling, typing into rich editors, pressing keys, evaluating JS, capturing screenshots, and reading console/network buffers. All actions go through CDP and run on backgrounded tabs without stealing focus.
9installs
Sourcekiluazen/kstack
Added on
NPX Install
npx skill4agent add kiluazen/kstack chrome-relayTags
Translated version includes tags in frontmatterSKILL.md Content
View Translation Comparison →Chrome Relay
Drives the user's real Chrome through a Chrome extension + local native host. Prefer it when logged-in browser state (auth cookies, sessions, installed extensions) matters.
Setup
- Chrome extension
- CLI:
sh
pnpm add -g chrome-relay chrome-relay install chrome-relay doctor
Verify CLI ≥ 0.5.20 — earlier versions have a silent click bug on Radix/React-Aria UIs:
sh
chrome-relay --versionTool surface
| Command | What it does |
|---|---|
| List windows + tabs with their |
| Open in current tab. |
| Interaction map: visible interactive elements with selectors, text, role, bounds. Pipe to file. |
| Accessibility tree — ~30× smaller than |
| Trusted hover + press + release at element center (CDP |
| Coordinate-mode click. Selector optional. |
| Click an element resolved from a prior |
| Pointer move only — fires |
| Atomic value write into |
| CDP |
| Single key or chord: |
| |
| PNG. |
| Record a tab via CDP (paint-driven). Requires an active tab. |
| HTTP request/response ring buffer, last 200 per tab. |
| |
| Emulate device viewport, DPR, mobile flag, touch, UA. |
| Manage named windows / tab-groups so multiple agents can drive separate windows. |
| Activate or close tabs |
| Restart the extension's service worker after a rebuild |
| Queryable changelog; agent-readable JSON. |
| Raw pass-through for any internal tool. |
Picking the right text tool
| Target element | Tool |
|---|---|
| |
| |
| Submit, navigate menus, modifier shortcuts | |
| Combobox / autocomplete option selection | |
| Shadow DOM, framework-internal pokes, scraping, custom widgets | |
Workflow
- Find the tab —
chrome-relay tabs - Open the page — (background by default)
chrome-relay navigate "https://example.com" --new - Read structure — pipe to a file, don't dump 100KB into context:
For dense apps (LinkedIn, Notion), prefersh
chrome-relay read --tab 1234 -i > /tmp/page.json jq '.elements[] | select(.text | test("Compose"; "i"))' /tmp/page.json— way smaller payload.ax - Act on the selectors:
sh
chrome-relay click "<selector>" --tab 1234 chrome-relay fill "<selector>" "value" --tab 1234 chrome-relay type "tweet body" --tab 1234 -s "[data-testid=tweetTextarea_0]" chrome-relay keys "Enter" --tab 1234 - Drop to when the DOM doesn't expose what you need:
jsshchrome-relay js --tab 1234 "return document.title" chrome-relay js --tab 1234 "const r = await fetch('/api/me'); return await r.json()" - Capture proof —
chrome-relay screenshot --tab 1234 -o /tmp/evidence.png
Top gotchas
- appends — it inserts at the caret. If the input had a value (autosaved draft, default text), clear it first via
typeorjs(Cmd+A then Backspace).keys - Coords go stale fast — read , scroll/reflow, then click → you hit the wrong element. For autocomplete popups especially, use keyboard nav, not coord clicks.
getBoundingClientRect - Click "succeeded" but nothing happened — first diagnostic: . If it returns a wrapper or form background, your coords are wrong. If it returns the right element but state didn't change, you're likely on chrome-relay <0.5.20 — upgrade.
document.elementFromPoint(x, y)
More recipes: references/patterns.md
Failure modes: references/troubleshooting.md
Operational guidance
- Don't give up early. A failing click is information, not a stop signal. Attach a document-level listener with and watch what fires:
capture:trueshchrome-relay js --tab 1234 " ['pointerdown','mousedown','click'].forEach(t => document.addEventListener(t, e => console.log(t, e.target.tagName, e.target.className), {capture:true}) ); return 'listening' " # do the action, then: chrome-relay console --tab 1234 - Don't echo secrets. When extracting tokens / API keys via , write the result directly to a file. Never
jsor interpolate into shell strings — it ends up in scrollback, logs, and tool transcripts.echo $TOKEN - Capture before irreversible actions (form submit, send message, account change). Save the screenshot path.
Guardrails
- Pipe to a file and grep/jq it. Don't paste the full element map into chat.
read -i - If a flag is unclear, is authoritative — these docs lag.
chrome-relay <command> --help