pawbrowse 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +298 -0
- package/extension/background.js +833 -0
- package/extension/icons/icon-128.png +0 -0
- package/extension/icons/icon-16.png +0 -0
- package/extension/icons/icon-32.png +0 -0
- package/extension/icons/icon-48.png +0 -0
- package/extension/manifest.json +34 -0
- package/extension/options.html +25 -0
- package/extension/options.js +36 -0
- package/mcp/broker.mjs +222 -0
- package/mcp/server.mjs +271 -0
- package/package.json +40 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 pawbrowse contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="assets/hero.png" alt="PawBrowse — Claude Code drives your real Chrome" width="100%">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<h1 align="center">
|
|
6
|
+
<img src="extension/icons/icon-48.png" width="28" align="top" alt=""> PawBrowse
|
|
7
|
+
</h1>
|
|
8
|
+
|
|
9
|
+
<p align="center"><strong>Let Claude Code drive your real, logged-in Chrome — open source, no keys, no second model.</strong></p>
|
|
10
|
+
|
|
11
|
+
<p align="center">
|
|
12
|
+
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-green.svg" alt="MIT"></a>
|
|
13
|
+
<a href="CONTRIBUTING.md"><img src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg" alt="PRs welcome"></a>
|
|
14
|
+
<a href="package.json"><img src="https://img.shields.io/badge/node-%3E%3D18-brightgreen.svg" alt="Node >=18"></a>
|
|
15
|
+
<img src="https://img.shields.io/badge/deps-zero-brightgreen.svg" alt="zero dependencies">
|
|
16
|
+
<a href="https://claude.com/claude-code"><img src="https://img.shields.io/badge/for-Claude%20Code-8A63D2.svg" alt="for Claude Code"></a>
|
|
17
|
+
<a href="https://modelcontextprotocol.io"><img src="https://img.shields.io/badge/MCP-server-blue.svg" alt="MCP"></a>
|
|
18
|
+
</p>
|
|
19
|
+
|
|
20
|
+
PawBrowse is a **Chrome MV3 extension + a tiny zero-dependency MCP server** that lets your local
|
|
21
|
+
AI coding agent (like **Claude Code**) read and act on your **actual, logged-in browser tabs** —
|
|
22
|
+
your profile, your sessions, your open pages — with **no remote-debug port, no browser relaunch,
|
|
23
|
+
and no separate AI model or API key.**
|
|
24
|
+
|
|
25
|
+
It's the open, self-owned answer to "I wish my agent could just use my real browser": the same
|
|
26
|
+
capability as the first-party Claude-in-Chrome extension, but **yours, auditable, MCP-native, and
|
|
27
|
+
faster per action** (see the [benchmark](#benchmark) below).
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
Claude Code ──stdio (MCP)──▶ mcp/server.mjs ─┐
|
|
31
|
+
Cursor ──stdio (MCP)──▶ mcp/server.mjs ─┼─IPC─▶ broker ──ws://127.0.0.1:10577──▶ Chrome extension ──CDP──▶ your real tabs
|
|
32
|
+
VS Code ──stdio (MCP)──▶ mcp/server.mjs ─┘ │
|
|
33
|
+
each session ⇒ its own 🐾 tab group
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**Run as many sessions as you want.** The first one starts a shared *broker* that owns the port
|
|
37
|
+
and the extension; every other session just connects to it. Each session gets its **own tab group**
|
|
38
|
+
(named `🐾 PawBrowse`, its own color) and drives only its own tab, so several editors/agents can
|
|
39
|
+
automate the browser at once without fighting over a port or a tab. Close a session and its tabs are
|
|
40
|
+
cleaned up; the broker reaps itself when the last session ends. Nothing to configure — no ports, no
|
|
41
|
+
"already in use."
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Getting started
|
|
46
|
+
|
|
47
|
+
Two one-time steps, about 30 seconds. PawBrowse is a **Chrome extension** (the hands + eyes in
|
|
48
|
+
your browser) plus a tiny **local server** your AI client runs — both install with a click.
|
|
49
|
+
|
|
50
|
+
### 1 — Add the extension to Chrome
|
|
51
|
+
|
|
52
|
+
[](https://chromewebstore.google.com/detail/ppfdoledneneiaflggcfogecfnhkmloe)
|
|
53
|
+
|
|
54
|
+
> Live on the **[Chrome Web Store](https://chromewebstore.google.com/detail/ppfdoledneneiaflggcfogecfnhkmloe)** — one click, done.
|
|
55
|
+
> Prefer to run from source (contributors, or the very latest)? Clone this repo, open
|
|
56
|
+
> `chrome://extensions`, turn on **Developer mode**, **Load unpacked**, and pick the `extension/` folder.
|
|
57
|
+
|
|
58
|
+
### 2 — Connect your AI client (one time)
|
|
59
|
+
|
|
60
|
+
<p>
|
|
61
|
+
<a href="cursor://anysphere.cursor-deeplink/mcp/install?name=pawbrowse&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsInBhd2Jyb3dzZUBsYXRlc3QiXX0="><img src="https://img.shields.io/badge/Add%20to-Cursor-000000?logo=cursor&logoColor=white&style=for-the-badge" alt="Add to Cursor"></a>
|
|
62
|
+
<a href="https://insiders.vscode.dev/redirect/mcp/install?name=pawbrowse&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22pawbrowse%40latest%22%5D%7D"><img src="https://img.shields.io/badge/Install%20in-VS%20Code-007ACC?logo=visualstudiocode&logoColor=white&style=for-the-badge" alt="Install in VS Code"></a>
|
|
63
|
+
<a href="https://github.com/ItaiZeilig/pawbrowse/raw/main/dist/pawbrowse.mcpb"><img src="https://img.shields.io/badge/Add%20to-Claude%20Desktop-D97757?logo=anthropic&logoColor=white&style=for-the-badge" alt="Add to Claude Desktop"></a>
|
|
64
|
+
</p>
|
|
65
|
+
|
|
66
|
+
**Claude Desktop** — click the button above to download `pawbrowse.mcpb`, then **double-click it**
|
|
67
|
+
(or drag it into **Settings → Extensions**) and click **Install**. No command, no config.
|
|
68
|
+
|
|
69
|
+
**Claude Code** — one line (the CLI has no click-to-install, so paste this):
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
claude mcp add --scope user pawbrowse -- npx -y pawbrowse@latest
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Then **fully restart your client** and ask: *"use pawbrowse: what's my browser status?"* — you
|
|
76
|
+
should see `extension_connected: true`, and the extension badge turns **green ●**.
|
|
77
|
+
|
|
78
|
+
> Needs **Node.js ≥ 18**. Works with Claude Code, Cursor, VS Code, or any MCP client — the one
|
|
79
|
+
> button/line just tells your client to run `npx -y pawbrowse@latest`; nothing to clone or build.
|
|
80
|
+
|
|
81
|
+
<details>
|
|
82
|
+
<summary>From source (contributors, or before the Web Store listing is live)</summary>
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
git clone https://github.com/ItaiZeilig/pawbrowse.git
|
|
86
|
+
```
|
|
87
|
+
1. **Load the extension:** `chrome://extensions` → **Developer mode** → **Load unpacked** → pick
|
|
88
|
+
the `pawbrowse/extension` folder.
|
|
89
|
+
2. **Run Claude Code from the clone.** The repo ships a project [`.mcp.json`](.mcp.json), so Claude
|
|
90
|
+
Code offers to enable `pawbrowse` (running the local `mcp/server.mjs`) automatically — just
|
|
91
|
+
approve it. No npm, no manual `claude mcp add`.
|
|
92
|
+
Prefer to register it yourself? `claude mcp add --scope user pawbrowse -- node /full/path/to/pawbrowse/mcp/server.mjs`
|
|
93
|
+
3. **Fully restart Claude Code** (not just `/mcp`), then run the status check above.
|
|
94
|
+
</details>
|
|
95
|
+
|
|
96
|
+
## Using it
|
|
97
|
+
|
|
98
|
+
You don't call the tools yourself — you just **ask Claude Code in plain language**, and it uses
|
|
99
|
+
PawBrowse to drive whatever tab you point it at. Some things to try:
|
|
100
|
+
|
|
101
|
+
- *"Open news.ycombinator.com and give me the top 5 story titles."*
|
|
102
|
+
- *"On this tab, search for 'open source license' and open the first result."*
|
|
103
|
+
- *"Fill the signup form on the current page with my name and email, but don't submit."*
|
|
104
|
+
- *"Go to my GitHub notifications and tell me what's new."*
|
|
105
|
+
|
|
106
|
+
Tips:
|
|
107
|
+
- It acts on the **tab you have open and are logged into** — no separate window, no re-login.
|
|
108
|
+
- Point it at a specific tab by name, or it uses the active tab.
|
|
109
|
+
- It reads the page as a list of controls and clicks/types precisely — no screenshots needed.
|
|
110
|
+
|
|
111
|
+
## Troubleshooting
|
|
112
|
+
|
|
113
|
+
| Symptom | Fix |
|
|
114
|
+
| --- | --- |
|
|
115
|
+
| Badge never turns green | The server isn't running — make sure you **fully restarted** Claude Code after `claude mcp add` (a `/mcp` reconnect alone won't relaunch it). |
|
|
116
|
+
| "No extension connected" | Reload the extension at `chrome://extensions`, then re-run `browser_status`. |
|
|
117
|
+
| "Another debugger is already attached" | That tab has DevTools open or another extension driving it — close DevTools or switch tabs. |
|
|
118
|
+
| A `chrome://` / Web Store page won't drive | Those are browser pages Chrome blocks from automation — use a normal web page. |
|
|
119
|
+
| Changed the port | Set the same port in the extension's **Options** and in `--env PAWBROWSE_PORT=…`. |
|
|
120
|
+
|
|
121
|
+
> Requires **Node ≥ 18** (≥ 22 to run the test suite). Works on Chrome, Edge, and Brave.
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## Highlights
|
|
126
|
+
|
|
127
|
+
- **Your real browser.** Uses Chrome's built-in `chrome.debugger` (CDP) on tabs you already have
|
|
128
|
+
open and logged into — no `--remote-debugging-port`, no relaunch, no separate profile.
|
|
129
|
+
- **The agent is the policy.** No second model, no `TYPESAFE_API_KEY`, no OpenRouter — *you*
|
|
130
|
+
(Claude) decide every action. Page content flows to your agent as normal tool results and
|
|
131
|
+
**never leaves for any third-party server.**
|
|
132
|
+
- **Reads pages as an element table, not screenshots.** A compact, numbered list of the actionable
|
|
133
|
+
controls in view — cheap in tokens, fast to reason over, precise to act on.
|
|
134
|
+
- **Fast.** Stable element refs let it act in one round trip — **~2.2× faster per action** than the
|
|
135
|
+
closed alternative in testing.
|
|
136
|
+
- **Zero dependencies, MIT, extensible.** The whole server is one auditable `.mjs` file; the
|
|
137
|
+
extension is plain JS. Add a tool or an op in minutes.
|
|
138
|
+
|
|
139
|
+
## Benchmark
|
|
140
|
+
|
|
141
|
+
<p align="center">
|
|
142
|
+
<img src="assets/pawbrowse-vs-claude-in-chrome.gif" alt="Real side-by-side recording: PawBrowse vs Claude-in-Chrome on the same task" width="100%">
|
|
143
|
+
</p>
|
|
144
|
+
|
|
145
|
+
<p align="center"><em>Real side-by-side screen recording — same task (3 Wikipedia section jumps), same brain (Claude). PawBrowse acts in one call per click and finishes first; Claude-in-Chrome perceives-then-clicks. Measured numbers below.</em></p>
|
|
146
|
+
|
|
147
|
+
Because PawBrowse keeps **stable element refs** and its `navigate`/`act` already return the fresh
|
|
148
|
+
table, the agent clicks a known target in **one** round trip. Screenshot/accessibility-tree drivers
|
|
149
|
+
do **perceive-then-act** — a read (or screenshot) *then* a click — paying an extra agent round trip
|
|
150
|
+
and a larger payload every action.
|
|
151
|
+
|
|
152
|
+
Measured task: click 5 different section links on the same Wikipedia page, averaged, same machine,
|
|
153
|
+
same agent (Claude):
|
|
154
|
+
|
|
155
|
+
| | PawBrowse | Claude-in-Chrome |
|
|
156
|
+
| --- | --- | --- |
|
|
157
|
+
| Calls per click | **1** (`act` by stable ref) | 2 (`read_page` → click) |
|
|
158
|
+
| Avg wall-clock per click | **~7.6 s** | ~17.0 s |
|
|
159
|
+
| Perception payload | compact, viewport-only | full a11y tree w/ URLs (up to 50 KB) |
|
|
160
|
+
|
|
161
|
+
> **Honest caveat:** with Claude as the shared brain, absolute wall-clock is dominated by agent
|
|
162
|
+
> latency and is noisy — treat the **~2.2× ratio** as the signal, not the exact seconds. The win is
|
|
163
|
+
> *structural* (fewer round trips + smaller payloads), which also means fewer tokens per step. It's
|
|
164
|
+
> **not** the sub-second speed of a small, dedicated click-picking model — PawBrowse trades that
|
|
165
|
+
> raw speed for a smart, general brain (Claude) with no keys and no per-click cost.
|
|
166
|
+
|
|
167
|
+
## How it compares
|
|
168
|
+
|
|
169
|
+
| | Claude-in-Chrome | **PawBrowse** |
|
|
170
|
+
| --- | --- | --- |
|
|
171
|
+
| Drives your real, logged-in Chrome | ✅ | ✅ (`chrome.debugger`, no port) |
|
|
172
|
+
| Decision model | Claude | **Claude — no second model, no key** |
|
|
173
|
+
| Perception | screenshots + a11y tree | **compact element table** |
|
|
174
|
+
| Round trips per action | 2 (perceive → act) | **1** (stable refs) |
|
|
175
|
+
| Page data to a third party | no | **no** |
|
|
176
|
+
| Per-site permission gate | yes (allowlist) | no |
|
|
177
|
+
| Open source / self-owned | ❌ | **✅ MIT, zero-dep** |
|
|
178
|
+
| Works with any MCP client | ❌ | **✅** |
|
|
179
|
+
|
|
180
|
+
## The element table
|
|
181
|
+
|
|
182
|
+
Every observation returns a compact, numbered table of the **in-viewport, actionable** controls —
|
|
183
|
+
with proper accessible names, current values, and state flags — instead of a screenshot:
|
|
184
|
+
|
|
185
|
+
```
|
|
186
|
+
Web browser - Wikipedia — https://en.wikipedia.org/wiki/Web_browser
|
|
187
|
+
scroll 0/6361 · 83 controls
|
|
188
|
+
e2 fill "Search Wikipedia"
|
|
189
|
+
e6 click "Log in"
|
|
190
|
+
e10 click "2 History"
|
|
191
|
+
e13 click ▾ "Toggle Browser market subsection"
|
|
192
|
+
e9 click✓ "Remember me"
|
|
193
|
+
e3 select "Country" opts{US | UK | ...}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Flags after the kind: `✓`/`·` checked/unchecked · `▾`/`▸` expanded/collapsed (open vs closed menu,
|
|
197
|
+
combobox, accordion) · `◉` selected (active tab/option). Refs like `e10` derive from a **stable node
|
|
198
|
+
identity**, so the agent can act on a control by ref in **one round trip**.
|
|
199
|
+
|
|
200
|
+
## Tools
|
|
201
|
+
|
|
202
|
+
| Tool | Purpose |
|
|
203
|
+
| --- | --- |
|
|
204
|
+
| `browser_status` | Connection + attached-tab diagnostics. Call first if anything's off. |
|
|
205
|
+
| `browser_tabs` | List open tabs (`id`, `title`, `url`, `active`). |
|
|
206
|
+
| `browser_navigate` | `{ url, tabId? }` → element table after load. |
|
|
207
|
+
| `browser_observe` | `{ tabId? }` → the element table. |
|
|
208
|
+
| `browser_read` | `{ tabId?, max_chars? }` → the page's readable prose (articles, docs, rules). |
|
|
209
|
+
| `browser_act` | `{ ops: [...], tabId? }` → runs ops in order, returns a fresh table + a "page changed?" signal. |
|
|
210
|
+
| `browser_assert` | `{ contains? \| url_includes? \| ref_visible?, tabId? }` → prove an outcome (pass/fail). |
|
|
211
|
+
|
|
212
|
+
**Ops for `browser_act`:** `{op:"click",ref:"e12"}` · `{op:"click_text",text:"..."}` (for custom
|
|
213
|
+
widgets/menus not in the table) · `{op:"type",ref:"e7",text:"..."}` · `{op:"select",ref:"e8",value:"..."}`
|
|
214
|
+
· `{op:"key",key:"Enter"}` · `{op:"scroll",dy:600}` · `{op:"wait",ms:500}`.
|
|
215
|
+
|
|
216
|
+
## Reliability & safety engineering
|
|
217
|
+
|
|
218
|
+
PawBrowse was hardened through two multi-agent code audits **and** live testing on real sites:
|
|
219
|
+
|
|
220
|
+
- **Hit-tested clicks.** Before every click it re-resolves the element live and verifies the center
|
|
221
|
+
isn't covered (`elementFromPoint`), so it never clicks a stale, moved, or occluded target.
|
|
222
|
+
- **Semantic freshness guard.** An element's role + accessible name is fingerprinted at observe time
|
|
223
|
+
and re-checked before acting — a silently relabeled target is rejected ("observe again") instead
|
|
224
|
+
of mis-clicked.
|
|
225
|
+
- **Robust fill.** Select-all + `insertText`, which works with React/controlled inputs; typed
|
|
226
|
+
comboboxes wait for their autocomplete options to actually render.
|
|
227
|
+
- **Background-tab safe.** Uses `Emulation.setFocusEmulationEnabled` and `setTimeout`-based waits
|
|
228
|
+
(never `requestAnimationFrame`, which Chrome pauses in background tabs) so driving a tab you aren't
|
|
229
|
+
looking at doesn't hang.
|
|
230
|
+
- **No double-execution.** If a post-action read fails because the page is navigating, the ops are
|
|
231
|
+
reported as executed ("call observe next") rather than surfaced as a failure to retry.
|
|
232
|
+
- **Serialized, unwedgeable command queue** — overlapping calls can't race the debugger, and one
|
|
233
|
+
hung command can't block the rest.
|
|
234
|
+
|
|
235
|
+
## Security & privacy
|
|
236
|
+
|
|
237
|
+
- **No data leaves your machine.** There's no model and no API key; page content goes only to the
|
|
238
|
+
agent you run locally. `password`, `file`, and `hidden` inputs are excluded and never exposed.
|
|
239
|
+
(Other visible fields — e.g. text inputs — *are* part of the element table, so treat what's on
|
|
240
|
+
screen as visible to your agent.)
|
|
241
|
+
- **Local-only bridge.** The WebSocket binds to `127.0.0.1`, rejects non-`chrome-extension://`
|
|
242
|
+
origins (so a web page can't connect), trusts only the current extension socket, caps inbound
|
|
243
|
+
frame size, and rejects malformed/oversized frames. **Trust model:** the bridge trusts any
|
|
244
|
+
*local* process on `127.0.0.1` (there's no shared token yet), so it assumes other software on
|
|
245
|
+
your machine is trusted — the same assumption as most localhost dev tools. A per-pair token is
|
|
246
|
+
planned hardening.
|
|
247
|
+
- **One powerful permission, no host permissions.** The extension declares `debugger` (plus `tabs`,
|
|
248
|
+
`storage`, `alarms`) and **no** host permissions — `chrome.debugger` doesn't need them. That's the
|
|
249
|
+
same capability class as any real-browser agent; use it deliberately.
|
|
250
|
+
- **Fully auditable.** The server is one zero-dependency file; the extension is plain JS.
|
|
251
|
+
|
|
252
|
+
Found a vulnerability? See **[SECURITY.md](SECURITY.md)** — please don't open a public issue.
|
|
253
|
+
|
|
254
|
+
## Privacy policy
|
|
255
|
+
|
|
256
|
+
PawBrowse is built to collect nothing. Full policy: **[PRIVACY.md](PRIVACY.md)**. In short:
|
|
257
|
+
|
|
258
|
+
- **Collection / use:** PawBrowse has no AI model, no account, no API key, and **no telemetry or
|
|
259
|
+
analytics**. Page content it reads (element tables, page text) is returned only to the local AI
|
|
260
|
+
client you run, to fulfill your request.
|
|
261
|
+
- **Storage:** the only thing stored is your **bridge port number**, in `chrome.storage.local` on
|
|
262
|
+
your machine. Page content is not persisted by the extension beyond the current operation.
|
|
263
|
+
- **Sharing:** nothing is sent to the developer or any third-party server. All traffic stays on
|
|
264
|
+
`127.0.0.1` (localhost) between the extension and the server on your own computer.
|
|
265
|
+
- **Retention:** none — there is no server-side data, so there is nothing to retain or delete.
|
|
266
|
+
- **Contact:** questions or requests via [GitHub issues](https://github.com/ItaiZeilig/pawbrowse/issues).
|
|
267
|
+
|
|
268
|
+
## Notes & limits
|
|
269
|
+
|
|
270
|
+
- Attaching shows Chrome's "PawBrowse is debugging this browser" banner — expected.
|
|
271
|
+
- One debugger client per tab: a tab with DevTools open (or driven by another extension) can't be
|
|
272
|
+
attached — switch tabs or close DevTools.
|
|
273
|
+
- `chrome://`, the Chrome Web Store, and other browser pages can't be driven.
|
|
274
|
+
- **One active client at a time.** The bridge is a single localhost port, so PawBrowse can be driven
|
|
275
|
+
by one client at a time (e.g. Claude Code *or* Claude Desktop). A second client reports the port
|
|
276
|
+
is in use via `browser_status` rather than failing hard; set a different `PAWBROWSE_PORT` per
|
|
277
|
+
client if you need both.
|
|
278
|
+
- **Shadow DOM and same-origin iframes are enumerated** (v0.4.0): controls inside open shadow roots
|
|
279
|
+
(web components) and same-origin iframes appear in the element table and are clickable/typable by
|
|
280
|
+
ref. **Not yet:** cross-origin iframes (the browser blocks JS access to them), canvas, and file
|
|
281
|
+
uploads.
|
|
282
|
+
|
|
283
|
+
## Contributing
|
|
284
|
+
|
|
285
|
+
Contributions welcome — see **[CONTRIBUTING.md](CONTRIBUTING.md)** for dev setup, tests (`npm test`),
|
|
286
|
+
and the PR process. By participating you agree to the **[Code of Conduct](CODE_OF_CONDUCT.md)**.
|
|
287
|
+
Questions? **[SUPPORT.md](SUPPORT.md)**.
|
|
288
|
+
|
|
289
|
+
## Credits
|
|
290
|
+
|
|
291
|
+
Built with [Claude Code](https://claude.com/claude-code). Some of the page-perception and
|
|
292
|
+
action-execution techniques are adapted from
|
|
293
|
+
[browser-use/jev-ultrafast](https://github.com/browser-use/jev-ultrafast) (MIT); this credit is kept
|
|
294
|
+
as required by that project's license.
|
|
295
|
+
|
|
296
|
+
## License
|
|
297
|
+
|
|
298
|
+
[MIT](LICENSE) © PawBrowse contributors.
|