iframer-toolkit 0.9.0 → 0.10.5
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/README.md +65 -16
- package/dist/cli.js +9060 -2950
- package/dist/local-server.cjs +2420 -1135
- package/dist/mcp-server.cjs +1296 -828
- package/extension/README.md +134 -0
- package/extension/background.js +639 -0
- package/extension/manifest.json +32 -0
- package/extension/native-host.cjs +91 -0
- package/extension/popup.html +72 -0
- package/extension/popup.js +108 -0
- package/package.json +12 -6
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# iframer browser extension (extension mode)
|
|
2
|
+
|
|
3
|
+
Let iframer drive **a tab you already have open in your real Chrome** — no
|
|
4
|
+
relaunch, no remote-debugging port, on your real logged-in session. While a run
|
|
5
|
+
is in progress Chrome shows its yellow "iframer started debugging this browser"
|
|
6
|
+
bar; it disappears when the run finishes.
|
|
7
|
+
|
|
8
|
+
## How it works
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
Claude (agent) ──MCP──▶ iframer server ──connectOverCDP──▶ CDP relay ──WS──▶ this extension ──chrome.debugger──▶ your tab
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
- The extension **dials out** to iframer's local server (extensions can't listen
|
|
15
|
+
on a port). It authenticates with a first `{type:"auth"}` message — the token
|
|
16
|
+
never appears in a URL.
|
|
17
|
+
- For discovery (`tabs`), the extension uses `chrome.tabs`.
|
|
18
|
+
- To **drive** a tab, the extension attaches `chrome.debugger` to it and **relays
|
|
19
|
+
the CDP protocol** to iframer's server, which connects with
|
|
20
|
+
`connectOverCDP` and runs the **exact same pipeline** (find/click/snapshot/
|
|
21
|
+
navigate/obstacle-handling/API-capture) it uses in every other mode. Nothing is
|
|
22
|
+
reimplemented — your live tab is driven by the real, proven engine, with real
|
|
23
|
+
trusted input.
|
|
24
|
+
|
|
25
|
+
Once paired, iframer can see and drive **any** of your open tabs — the agent lists
|
|
26
|
+
them (`tabs` tool), finds the one you meant, and drives it. One pipeline drives a
|
|
27
|
+
given tab at a time; different tabs can run concurrently.
|
|
28
|
+
|
|
29
|
+
## Multiple profiles / browsers
|
|
30
|
+
|
|
31
|
+
You can run the extension in as many Chrome profiles (or browsers) as you want at
|
|
32
|
+
once. Each install identifies itself with a stable random **profile id** and a
|
|
33
|
+
**profile name** (the signed-in account's email, or set one in the popup —
|
|
34
|
+
"Work", "Personal", …). The server keeps every connection separate, aggregates
|
|
35
|
+
tabs across all of them (each tab tagged with its profile), and routes every
|
|
36
|
+
`execute`/`reverse-engineer` to the profile that owns the target tab. If two
|
|
37
|
+
browsers happen to report the same numeric tab id, iframer refuses to guess and
|
|
38
|
+
asks for the tab's `clientId`. A service-worker restart replaces that profile's
|
|
39
|
+
own connection instead of piling up. The server stays alive while any profile is
|
|
40
|
+
connected and idle-exits once none are.
|
|
41
|
+
|
|
42
|
+
The extension is an **optional** add-on (Chrome/Chromium today; Firefox and
|
|
43
|
+
others later). You opt in explicitly — nothing installs it for you.
|
|
44
|
+
|
|
45
|
+
## Install (opt-in, Chrome)
|
|
46
|
+
|
|
47
|
+
```sh
|
|
48
|
+
iframer install extension chrome
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
That installs the pairing (native-messaging) host and prints the folder to load.
|
|
52
|
+
Then finish the one manual step it tells you:
|
|
53
|
+
|
|
54
|
+
1. Open `chrome://extensions`.
|
|
55
|
+
2. Turn on **Developer mode** (top right).
|
|
56
|
+
3. **Load unpacked** → select the printed folder — the `extension/` dir **inside
|
|
57
|
+
the installed package** (get it again with `iframer extension path`).
|
|
58
|
+
|
|
59
|
+
Loading from that path is what lets `iframer update` refresh it in place. The
|
|
60
|
+
pinned `key` keeps the extension ID — and pairing — stable across updates.
|
|
61
|
+
|
|
62
|
+
## Updating (npm is the update channel)
|
|
63
|
+
|
|
64
|
+
The extension ships inside the `iframer-toolkit` npm package, so npm *is* the
|
|
65
|
+
update channel — no Chrome Web Store. When a newer version is published, the
|
|
66
|
+
extension notices (the running extension is older than the files on disk) and
|
|
67
|
+
shows a **↑ Update available** badge + a popup notice. To apply it:
|
|
68
|
+
|
|
69
|
+
```sh
|
|
70
|
+
iframer update # npm-updates, reloads the extension, restarts the server
|
|
71
|
+
iframer update --check # just report whether a newer version exists
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
`iframer update` runs `npm install -g iframer-toolkit@latest` (which overwrites
|
|
75
|
+
the extension files in place at the path above), tells the running extension to
|
|
76
|
+
`chrome.runtime.reload()` so it re-reads the new files, and retires the old
|
|
77
|
+
server. The only manual step is ever the *first* **Load unpacked** — after that,
|
|
78
|
+
updates are one command. (Dev/linked checkouts update via `git pull && bun run
|
|
79
|
+
build` instead; `iframer update` detects that and says so.)
|
|
80
|
+
|
|
81
|
+
## Pair it (one time, zero copying)
|
|
82
|
+
|
|
83
|
+
```sh
|
|
84
|
+
iframer install extension
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
then restart the browser. That installs a Chrome **native-messaging host**
|
|
88
|
+
(locked to this extension's pinned ID) that hands the extension the pairing
|
|
89
|
+
token straight from `~/.iframer/secret` — every profile and every Chromium-family
|
|
90
|
+
browser (Chrome, Brave, Edge, …) pairs itself, and re-pairs automatically after
|
|
91
|
+
a reinstall or a rotated secret. No copying, ever.
|
|
92
|
+
|
|
93
|
+
Manual fallback (host not installed): click the iframer toolbar icon → paste the
|
|
94
|
+
token from `cat ~/.iframer/secret` → **Save & connect**.
|
|
95
|
+
|
|
96
|
+
Either way the dot turns green when it finds the running iframer server (it
|
|
97
|
+
scans ports 3022–3042 on `127.0.0.1`; the server allocates its port from the
|
|
98
|
+
same window). The token is the same machine-local secret the iframer CLI/MCP
|
|
99
|
+
already use. It is only ever sent to `127.0.0.1`.
|
|
100
|
+
|
|
101
|
+
## Use it
|
|
102
|
+
|
|
103
|
+
Just tell your agent, e.g. *"use my Gmail tab and archive everything from X."*
|
|
104
|
+
The agent calls the `tabs` tool to list your open tabs, finds the one you meant,
|
|
105
|
+
then `execute`s with `mode: "extension"` and that tab's id. No per-tab step —
|
|
106
|
+
once the extension is connected, every open tab is reachable.
|
|
107
|
+
|
|
108
|
+
Because runs go through iframer's real engine, **every pipeline step works
|
|
109
|
+
exactly as in the other modes** — same selectors, same `@e` refs, same
|
|
110
|
+
screenshots, same knowledge cache.
|
|
111
|
+
|
|
112
|
+
## Reverse-engineering
|
|
113
|
+
|
|
114
|
+
Extension mode captures the API too. Run `reverse-engineer` (or `execute` with
|
|
115
|
+
`options.captureApi: true`) with `mode: "extension"` + `tabId`. Capture happens
|
|
116
|
+
in the server's normal network layer over the CDP relay, so you get everything
|
|
117
|
+
the other modes get — parameterized paths, protocol/verb classification,
|
|
118
|
+
`functionName`, ready-to-run `curl`, extracted auth, **including response
|
|
119
|
+
bodies**. Captured endpoints also feed the knowledge cache automatically.
|
|
120
|
+
|
|
121
|
+
## Limitations
|
|
122
|
+
|
|
123
|
+
- **The debug bar.** `chrome.debugger` is what makes trusted input and the full
|
|
124
|
+
engine possible; Chrome always shows the yellow bar while it's attached.
|
|
125
|
+
- **The tab becomes active in its window while driven.** An inactive tab
|
|
126
|
+
doesn't render, so the extension activates it — but it does NOT steal your OS
|
|
127
|
+
focus: the window stays in the background and the page is driven with CDP
|
|
128
|
+
focus emulation, so you can keep working. A minimized window is auto-restored
|
|
129
|
+
(without focus — it stays behind your other windows), and screenshots fall
|
|
130
|
+
back to renderer capture if the compositor produces no frame. If a site still
|
|
131
|
+
ignores background input, pass `options.focus: true` to restore the old
|
|
132
|
+
raise-the-window behavior.
|
|
133
|
+
- **No session inject/extract.** Your real profile owns its cookies; iframer
|
|
134
|
+
doesn't copy sessions in or out of extension mode.
|