iframer-toolkit 0.10.6 → 0.11.0

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/skills/iframer.md CHANGED
@@ -10,9 +10,12 @@ You are an expert at using the iframer browser automation toolkit. The user want
10
10
  - `iframer.credentials` — list or store login credentials (NEVER re-store as recovery)
11
11
  - `iframer.execute` — run a browser pipeline (navigate, login, screenshot, snapshot, etc.)
12
12
  - `iframer.browse` — fast headless page fetch (no pipeline needed)
13
- - `iframer.session` — stop (save state) or clear session data
13
+ - `iframer.session` — stop (save state, close the browser), clear (wipe session data), restart (recover from a freeze or crash), capture-start / capture-stop (record XHR/fetch), get-cookies, get-auth
14
14
  - `iframer.status` — system health, modes, stored credentials
15
15
  - `iframer.reverse-engineer` — capture API calls a site makes
16
+ - `iframer.tabs` — list/open tabs in the user's REAL Chrome (needs the extension)
17
+ - `iframer.remember` — per-domain element anchors, targeted as `@a:<name>` in any selector
18
+ - `iframer.clipboard` — read/write the machine's clipboard (same one the user's Chrome uses)
16
19
 
17
20
  ## Core rules
18
21
 
@@ -22,6 +25,8 @@ You are an expert at using the iframer browser automation toolkit. The user want
22
25
  4. **NEVER pass explicit selectors to the login step** unless the auto-detect failed AND you took a snapshot to find the right ones. The login step auto-detects email, password, submit, and OTP fields.
23
26
  5. If headless detects Imperva or Akamai, immediately stop headless and pivot to headed in the same run; do not wait for a block, retry headless, or defer the switch to a future request. Use headed from the outset when the provider is already known in the current task. On detection, switch to headed and use respectful pacing (at least 3 seconds between top-level actions; no parallel bursts or repeated blocked retries). Do not announce the provider or explain the switch unless the user asks why. Only when asked, explain that the site is covered by Imperva or Akamai and iframer adjusts its browser mode and pacing to respect it.
24
27
  6. **Let iframer handle mode escalation.** Don't hardcode modes. If you must pick one, prefer no mode (auto-select) or `binary-headful` for sites known to block headless.
28
+ 7. **"My browser" / "my tabs" / "I'm already logged in there" means extension mode, never a launched browser.** See the section below. A launched browser has none of the user's logins and opening one is a visible, unwanted window on their desktop.
29
+ 8. **Every browser you open is yours to close.** Call `session stop` when the work is done, and if a call opened a browser by mistake, close it immediately instead of leaving it. `status` lists live windows.
25
30
 
26
31
  ## How to build pipelines
27
32
 
@@ -33,27 +38,34 @@ The `execute` tool takes a `steps` array. Each step is an object with a `type` f
33
38
  |------|--------|-------------|
34
39
  | `navigate` | `url`, `waitUntil?` | Go to URL |
35
40
  | `login` | `domain` | Auto-detect form, fill stored credentials, handle 2FA. Handles email-first flows (Slack, Microsoft, Google) and standard email+password flows. |
36
- | `snapshot` | — | Get interactive elements as structured list with @e refs. **Do this BEFORE interacting.** |
41
+ | `snapshot` | — | Get interactive elements as structured list with @e refs. **Do this BEFORE interacting.** Fields no human can reach (honeypots pushed offscreen/clipped/transparent by an ancestor) are omitted; bait-looking ones (`website`, `fax`, tabindex=-1) are marked `[honeypot?]` — leave those empty unless the task clearly needs them. |
37
42
  | `find` | `role?`, `name?`, `text?`, `placeholder?`, `label?` | Find a specific element, returns a ref |
38
43
  | `screenshot` | `annotate?` | Take a screenshot. `annotate: true` overlays numbered badges. |
39
- | `click` | `selector` | Click element (use @e refs from snapshot) |
40
- | `fill` | `selector`, `value` | Fill input (use @e refs) |
44
+ | `click` | `selector` | Click element (use @e refs from snapshot/find). Text selectors (`text=`, `:has-text()`, `:text-is()`, `>>`) are rejected: `find` by text, then click the ref. |
45
+ | `right-click` | `selector` or `x`, `y` | Right-click an element or coordinates |
46
+ | `fill` | `selector`, `value`, `force?` | Fill input (use @e refs). Refuses honeypot fields (unreachable by a human) with an explanatory error — skip the field. `force: true` bypasses, only when you are certain it is real. |
41
47
  | `human-click` | `selector` or `x`, `y` | Human-like click with random offset |
42
- | `human-type` | `selector`, `value` | Human-like typing with variable delays |
48
+ | `human-type` | `selector`, `value`, `clear?` | Human-like typing with variable delays. Appends by default; `clear: true` replaces the existing text. |
43
49
  | `scroll` | `deltaY?` | Scroll the page |
44
50
  | `wait` | `ms` | Wait N milliseconds |
45
51
  | `wait-for` | `selector`, `timeout?` | Wait for element to appear |
46
52
  | `evaluate` | `expression` | Run JS, return result |
47
53
  | `extract` | `expression` | Run JS, include result in response |
48
- | `keyboard` | `key` | Press a key (Enter, Escape, Tab, etc.) |
49
- | `solve-captcha` | — | Auto-detect and solve reCAPTCHA or hCaptcha |
54
+ | `keyboard` | `key`, `meta?`, `ctrl?` | Press a key (Enter, Escape, Tab, etc.). Cmd/Ctrl+A selects all everywhere; other Cmd/Ctrl shortcuts are refused in extension mode. |
55
+ | `select` | `selector`, `value` | Pick an option in a native `<select>`, with real change events. Never set `.value` via `evaluate`. |
56
+ | `type-code` | `value`, `selector?` | Type a verification code digit by digit. Default target: `input[type="tel"]`. |
57
+ | `upload` | `selector`, `files` | Set absolute local file paths on an `<input type=file>` |
58
+ | `paste` | `selector?` | Paste the OS clipboard into a field, or the focused element if omitted. More reliable than a ⌘V `keyboard` step. |
59
+ | `download` | `url`, `path?` | Fetch a file with the browser's cookies and save it server-side, no Save-As dialog. Default path: `~/.iframer/downloads/<name>`. |
60
+ | `solve-captcha` | — | Best-effort reCAPTCHA or hCaptcha solve with vision AI. Works in any mode; needs `ANTHROPIC_API_KEY`. Fails the run with `captcha-unsolvable` if it can't solve it. |
61
+ | `recaptcha` | `action`, `tiles?` | Manual captcha control: `info`, `click`, `answer`, `select`, `verify`, `solve`. The full workflow arrives in the result when a captcha blocks a run. |
50
62
 
51
63
  ### Pipeline options
52
64
 
53
65
  | Option | Default | Description |
54
66
  |--------|---------|-------------|
55
- | `mode` | auto | `headless`, `binary-headful`, `docker-headful`. Omit for auto-select + auto-escalation. |
56
- | `captureApi` | false | Record all XHR/fetch requests. Use for reverse-engineering. |
67
+ | `mode` | auto | `headless`, `binary-headful`. Omit for auto-select + auto-escalation. |
68
+ | `captureApi` | false | Record all XHR/fetch requests. Use for reverse-engineering, and when a form submit fails with only a vague on-page message: every HTTP >= 400 response is reported per step, so you read the server's real answer (e.g. `POST /api/apply → 422: {"error":"..."}`) instead of guessing. |
57
69
  | `staleTimeoutMs` | 20000 | Per-step stale-state timeout |
58
70
  | `continueOnError` | false | Don't abort pipeline on step failure |
59
71
  | `screenshotAfterEach` | false | Screenshot after every step (expensive) |
@@ -154,6 +166,24 @@ execute: steps: [{ type: "click", selector: "@e3" }, { type: "screenshot" }]
154
166
 
155
167
  The more interactions (scroll, click tabs, navigate sub-pages), the more API calls get captured. Results feed into the knowledge cache automatically.
156
168
 
169
+ ### Reverse-engineer inside a browser iframer doesn't control (T3 Code, Playwright MCP, ...)
170
+
171
+ When you already drive a browser through your own tools (a T3 Code preview tab, Playwright MCP, Chrome DevTools MCP), don't launch iframer's browser: load the in-page kit into that tab. It records the page's own calls on the user's real session and exports shapes, never values. Use the CLI for this, not the MCP tools.
172
+
173
+ ```
174
+ 1. iframer kit --for t3 # or --for playwright-mcp / --for any. Prints the exact tool calls.
175
+ 2. Follow the printed install steps (upload the kit file, stash it, top-level eval). Never paste the kit's source.
176
+ 3. Drive the site with your normal tools. After EVERY full page load, re-run the printed eval step (step 4).
177
+ 4. window.__ifk.dump(), then: iframer ingest --latest --typed
178
+ -> ./<host>-api/api.json, client.js, client.d.ts, plus the knowledge cache. The capture file is deleted.
179
+ ```
180
+
181
+ - Replays run IN the page: `window.__ifk.call('GET','/path')`, or load the generated `client.js` (`iframer kit --for t3 --client ./<host>-api/client.js` prints the steps). HttpOnly cookies never leave the browser, so curl replays fail.
182
+ - Writes need `{approved:true}`: ask the user first. Replays stop for good on 403, 429 or a captcha page. Do not retry or work around it.
183
+ - Sites that detect tampering: `iframer kit --mode passive` (no patching; URLs and form posts only).
184
+ - Report coverage as the kit states it. It is never complete: workers, redirect hops and cross-origin iframes are invisible.
185
+ - `ingest` refuses (exit 2) if anything value-like slipped into the capture. Don't edit the file to force it through; tell the user what was found.
186
+
157
187
  ### Handle captchas
158
188
 
159
189
  Captcha handling depends on the browser mode:
@@ -168,16 +198,13 @@ Captcha handling depends on the browser mode:
168
198
  execute: steps: [{ type: "screenshot" }] // verify captcha is gone, then continue
169
199
  ```
170
200
 
171
- **Docker-headful** (remote browser via noVNC):
172
- - Use the `solve-captcha` step — it auto-detects and solves reCAPTCHA/hCaptcha via vision AI.
201
+ **Headless, or nobody at the screen**:
202
+ - If you hit a captcha in headless, iframer auto-escalates to binary-headful.
203
+ - If nobody can solve it by hand, try the `solve-captcha` step. It's best effort: it uses vision AI, needs `ANTHROPIC_API_KEY`, and fails on many challenges.
173
204
  ```
174
205
  execute: steps: [{ type: "solve-captcha" }, { type: "screenshot" }]
175
206
  ```
176
207
 
177
- **Headless**:
178
- - Captchas can't be solved in headless. If you hit one, iframer auto-escalates to binary-headful.
179
- - If it still fails, switch to docker-headful and use `solve-captcha`.
180
-
181
208
  ### Handle OTP / 2FA codes
182
209
 
183
210
  If the login step encounters a code field and no TOTP secret is stored:
@@ -198,7 +225,7 @@ When the browser crashes, freezes, or you get connection errors:
198
225
  ```
199
226
  session: { action: "restart" }
200
227
  ```
201
- This kills ALL running browser instances (local + Docker) and resets state. Credentials and knowledge cache are NOT affected. The next `execute` call launches a fresh browser automatically.
228
+ This kills ALL running browser instances and resets state. Credentials and knowledge cache are NOT affected. The next `execute` call launches a fresh browser automatically.
202
229
 
203
230
  **The execute tool also auto-recovers:** if it detects a *connection-level* crash (connection closed, ECONNREFUSED/ECONNRESET/EPIPE, socket hang up), it restarts the browser server and retries once before reporting failure. Timeouts are deliberately NOT auto-retried — a slow-but-healthy pipeline that hit the client timeout must not be re-run, or non-idempotent steps (form submits, purchases) would double-execute. If auto-recovery fails, or a step timed out, call `session restart` manually and continue from where you left off (don't blindly re-run the whole pipeline).
204
231
 
@@ -229,11 +256,11 @@ knowledge: { action: "clear", domain: "example.com" }
229
256
 
230
257
  If an `execute` call takes a very long time (30s+), it's probably stuck on one of:
231
258
 
232
- 1. **Captcha blocking progress** — the login/navigate step can't proceed because a captcha appeared. In binary-headful mode, tell the user to solve it in the visible window. In docker-headful mode, add a `solve-captcha` step.
259
+ 1. **Captcha blocking progress** — the login/navigate step can't proceed because a captcha appeared. In binary-headful mode, tell the user to solve it in the visible window. If nobody can, add a `solve-captcha` step.
233
260
 
234
261
  2. **Waiting for a page transition that never happens** — the site didn't redirect after form submission. Take a screenshot to see the current state, then decide what to do (wrong button clicked, error message on page, etc.).
235
262
 
236
- 3. **Stale-state timeout** — iframer's stale monitor will abort after `staleTimeoutMs` (default 20s). The error will say "stale-state" and include a screenshot. Read the screenshot to understand what the page looks like.
263
+ 3. **Stale-state timeout** — iframer's stale monitor will abort after `staleTimeoutMs` (default 20s). The error will say "stale-state" and include a screenshot. Read the screenshot to understand what the page looks like. If the step targeted a selector that no longer exists, the error is reported as `element-not-found` instead ("No element matches …"): the page re-rendered it away. Re-snapshot right before acting and retry — do not change styles or theorise about visibility.
237
264
 
238
265
  **Recovery pattern for all stalls:**
239
266
  ```
@@ -242,7 +269,7 @@ If an `execute` call takes a very long time (30s+), it's probably stuck on one o
242
269
 
243
270
  2. If captcha visible:
244
271
  - binary-headful → ask user to solve it in the visible window
245
- - docker-headful → execute: steps: [{ type: "solve-captcha" }]
272
+ - nobody at the screen → execute: steps: [{ type: "solve-captcha" }]
246
273
 
247
274
  3. If the page shows an error or unexpected state:
248
275
  - Take a snapshot to get element refs
@@ -253,11 +280,9 @@ If an `execute` call takes a very long time (30s+), it's probably stuck on one o
253
280
 
254
281
  **CRITICAL: Don't restart from scratch.** The browser session persists between execute calls (same daemon, same page context). If you were mid-login and hit a captcha, you don't need to navigate back to the login page — you're still there. Just solve the captcha and continue.
255
282
 
256
- **Timeouts:** Docker-headful is slower than local modes — Xvfb + VNC + Chrome share one container. Heavy SPAs (Slack, Figma) can take 30+ seconds to load. If an execute call times out:
283
+ **Timeouts:** Heavy SPAs (Slack, Figma) can take 30+ seconds to load. If an execute call times out:
257
284
  1. Use `staleTimeoutMs: 60000` or higher for heavy sites
258
- 2. Check `status` to confirm Docker is still running
259
- 3. Take a screenshot to see where the browser is — the session is likely still alive
260
- 4. If the container crashed, `docker compose up -d` restarts it; stored sessions/credentials survive since they're in the host's SQLite
285
+ 2. Take a screenshot to see where the browser is — the session is likely still alive
261
286
 
262
287
  ## Multi-step flows (email → code, OAuth, etc.)
263
288
 
@@ -292,7 +317,6 @@ Instead:
292
317
  **Your progress is NOT lost.** Credentials, sessions, and knowledge cache are in the SQLite database on disk — they survive MCP server restarts. You don't need to re-login or re-store anything.
293
318
 
294
319
  If the MCP disconnects repeatedly on the same operation, the site is probably too heavy for the current mode. Switch to a lighter approach:
295
- - If using `docker-headful` → switch to `binary-headful` (less overhead)
296
320
  - If doing a complex multi-step pipeline → break it into smaller execute calls
297
321
  - If just trying to capture APIs → you probably already have enough from previous runs. Check `knowledge get <domain>` before retrying.
298
322
 
@@ -302,7 +326,7 @@ If the MCP disconnects repeatedly on the same operation, the site is probably to
302
326
  |---------|-----------------|
303
327
  | Guessing CSS selectors like `button[data-qa='submit']` | Use `snapshot` → read refs → use `@e` refs |
304
328
  | Passing `usernameSelector`/`passwordSelector` to login step | Omit them — auto-detect handles it |
305
- | Re-storing credentials when login fails | Retry with stronger mode (`binary-headful` or `docker-headful`) |
329
+ | Re-storing credentials when login fails | Retry with stronger mode (`binary-headful`) |
306
330
  | Launching browser without checking knowledge cache | Always call `knowledge get <domain>` first |
307
331
  | Using `browse` for a page that needs interaction | Use `execute` with a pipeline |
308
332
  | Running a huge pipeline without snapshots | Split into navigate+snapshot, then interact based on refs |
@@ -314,6 +338,56 @@ If the MCP disconnects repeatedly on the same operation, the site is probably to
314
338
  | Not passing `mode` consistently across execute calls in the same flow | Always pass the same `options.mode` for all steps in a multi-call flow |
315
339
  | Panicking when MCP disconnects (running `claude mcp`, inspecting source, giving up) | Just wait 2-3 seconds, call `status` to verify reconnect, then `session restart` and retry |
316
340
 
341
+ ## Driving the user's real Chrome (extension mode)
342
+
343
+ Use this whenever the user says "my browser", "my tabs", "the page I have open", or the task
344
+ needs accounts they are already signed into. A launched browser has a fresh, logged-out profile.
345
+
346
+ 1. `tabs` with `action: "list"` — returns open tabs as `[id <n>] title / url`. If it reports the
347
+ extension is not connected, tell the user to open Chrome / check the extension; do NOT fall
348
+ back to launching a browser.
349
+ 2. `execute` with `options.mode: "extension"` AND `options.tabId: <n>` from that list. Both are
350
+ required: `mode` alone is refused and launches nothing.
351
+ 3. Need a different page? `tabs` with `action: "open"` returns the new tab id. Do NOT use a
352
+ navigate-only pipeline in a launched browser to "get there".
353
+
354
+ Rules while in extension mode:
355
+
356
+ - **Do not call `session get-cookies` / `get-auth` / `capture-start` without a mode.** They default
357
+ to launching a separate window. The tab you are driving already has the auth; read it there.
358
+ - **Do not call `session stop`.** There is nothing to stop, and it is the user's own browser.
359
+ - `execute` never escalates in extension mode. If it fails, report why (extension disconnected,
360
+ tab closed) instead of retrying in a launched mode, which would silently use a logged-out profile.
361
+
362
+ Driving a live single-page app (most dashboards) in extension mode:
363
+
364
+ - **Act only on `@e` refs** from a `find`/`snapshot` in the same execute call. Never CSS you
365
+ guessed, never text selectors.
366
+ - **Give steps that can wedge the tab their own execute call:** `navigate`, anything that opens or
367
+ closes a modal, and `evaluate`. If one hangs, the steps around it are not lost.
368
+ - **If a step reports the tab stopped responding,** run a lone `read` or `snapshot` to confirm it
369
+ recovered, then continue. Don't resend the same step unchanged.
370
+ - **Route changes:** `navigate` first. If the page never leaves, use `evaluate` with
371
+ `location.assign("<url>")`, or click the site's own link.
372
+ - **Custom dropdowns (MUI, react-select, comboboxes):** click the field or its arrow button, `find`
373
+ the option (`role: "option", name: "Texas"`), click that `@e` ref. To filter first, `fill` the
374
+ field (it stays focused so the list stays open), then `find` and click the option. Don't type
375
+ with Cmd+A/Backspace tricks.
376
+ - **Don't scroll with `evaluate` (`scrollIntoView`).** `click` scrolls its target into view itself.
377
+
378
+ ## Cleaning up after yourself
379
+
380
+ A browser opened by mistake is a real, visible window sitting on the user's desktop. It is your
381
+ job to close it, not theirs.
382
+
383
+ - Any pipeline that opens a browser must end with `session stop` once the task is done.
384
+ - If you opened a browser you did not need (wrong mode, wrong call, task turned out not to need
385
+ one), call `session stop` right away, in the same turn you noticed.
386
+ - `status` lists live windows with their `instanceId`. If you see one you do not recognise from
387
+ your own work in this conversation, say so rather than silently leaving it.
388
+ - A pipeline with no `navigate` step is refused unless a live browser already holds that
389
+ `instanceId`. If you get that error, you probably meant extension mode — go get a `tabId`.
390
+
317
391
  ## Mode selection guide
318
392
 
319
393
  | Scenario | Recommended mode |
@@ -321,15 +395,13 @@ If the MCP disconnects repeatedly on the same operation, the site is probably to
321
395
  | Simple data extraction, no login | Omit mode (auto-select, starts headless) |
322
396
  | Site with login | Omit mode (auto-escalation if headless is blocked) |
323
397
  | Known bot-detection (Cloudflare, etc.) | `binary-headful` |
324
- | Heavy SPA (Slack, Figma, Linear, etc.) | `binary-headful` — Docker often stalls on heavy pages |
398
+ | Heavy SPA (Slack, Figma, Linear, etc.) | `binary-headful` |
325
399
  | Interactive session (browsing, clicking around) | `binary-headful` — most stable for long flows |
326
- | Need automated captcha solving | `docker-headful` (uses vision AI to solve) |
327
- | Need to watch the browser remotely / headless server | `docker-headful` |
400
+ | Nobody available to solve a captcha | Any mode, with a best-effort `solve-captcha` step (needs `ANTHROPIC_API_KEY`) |
328
401
  | Reverse-engineering after login | Same mode that login succeeded in |
402
+ | "Use my browser" / user's own logins / their open tab | `extension` + `tabId` from the `tabs` tool |
329
403
 
330
- **Prefer `binary-headful` over `docker-headful` for most tasks.** Binary-headful runs Chrome directly on the user's machine — it's faster, more stable for long sessions, and the user can solve captchas manually. Docker-headful adds overhead (Xvfb, VNC, container networking) and heavy SPAs frequently stall or timeout inside the container.
331
-
332
- Use `docker-headful` only when: (a) automated captcha solving is needed, (b) the user asks for it explicitly, or (c) it's a remote/headless server with no display.
404
+ **Prefer `binary-headful` for sites that block headless.** It runs Chrome directly on the user's machine, is stable for long sessions, and the user can solve captchas manually.
333
405
 
334
406
  ## Response handling
335
407