patchright-cli 0.9.1__py3-none-any.whl → 0.11.0__py3-none-any.whl
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.
- patchright_cli/__init__.py +1 -1
- patchright_cli/__main__.py +1 -1
- patchright_cli/_entry.py +26 -0
- patchright_cli/_skills/patchright-cli/SKILL.md +247 -48
- patchright_cli/_skills/patchright-cli/references/snapshot-refs.md +73 -60
- patchright_cli/_skills/patchright-cli/references/storage-state.md +1 -1
- patchright_cli/agent_hooks.py +470 -0
- patchright_cli/cli.py +1652 -298
- patchright_cli/daemon.py +1629 -358
- patchright_cli/daemon_pid.py +168 -0
- patchright_cli/debugger.py +240 -0
- patchright_cli/mcp_server.py +264 -12
- patchright_cli/snapshot.py +26 -19
- patchright_cli/snapshot_text.py +535 -0
- patchright_cli/toon.py +281 -0
- patchright_cli/values.py +316 -0
- {patchright_cli-0.9.1.dist-info → patchright_cli-0.11.0.dist-info}/METADATA +107 -16
- patchright_cli-0.11.0.dist-info/RECORD +27 -0
- {patchright_cli-0.9.1.dist-info → patchright_cli-0.11.0.dist-info}/WHEEL +1 -1
- patchright_cli-0.11.0.dist-info/entry_points.txt +2 -0
- patchright_cli/ref_registry.py +0 -339
- patchright_cli-0.9.1.dist-info/RECORD +0 -21
- patchright_cli-0.9.1.dist-info/entry_points.txt +0 -2
- {patchright_cli-0.9.1.dist-info → patchright_cli-0.11.0.dist-info}/licenses/LICENSE +0 -0
patchright_cli/__init__.py
CHANGED
patchright_cli/__main__.py
CHANGED
patchright_cli/_entry.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"""Console-script entry point with a `--version` fast path.
|
|
2
|
+
|
|
3
|
+
Agents probe `--version` constantly, so a bare version flag is answered here
|
|
4
|
+
from the leaf `patchright_cli/__init__.py`, before cli.py pulls in click and
|
|
5
|
+
the daemon (and with it Patchright). Everything else goes to cli.main().
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import sys
|
|
9
|
+
|
|
10
|
+
_VERSION_FLAGS = ("-v", "-V", "--version")
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def main() -> None:
|
|
14
|
+
if len(sys.argv) == 2 and sys.argv[1] in _VERSION_FLAGS:
|
|
15
|
+
from patchright_cli import __version__
|
|
16
|
+
|
|
17
|
+
sys.stdout.write(__version__ + "\n")
|
|
18
|
+
return
|
|
19
|
+
|
|
20
|
+
from patchright_cli.cli import main as cli_main
|
|
21
|
+
|
|
22
|
+
cli_main()
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
if __name__ == "__main__":
|
|
26
|
+
main()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: patchright-cli
|
|
3
|
-
description: Anti-detect browser automation using Patchright (undetected Playwright fork). Use when you need to interact with websites that block regular Playwright/Chrome DevTools, such as Akamai/Cloudflare-protected sites.
|
|
3
|
+
description: Anti-detect browser automation using Patchright (undetected Playwright fork). Use when you need to interact with websites that block regular Playwright/Chrome DevTools, such as Akamai/Cloudflare-protected sites. Uses playwright-cli style commands (not a drop-in replacement) but bypasses bot detection. Use this skill whenever the user asks to automate a browser, scrape a website, fill forms, log into sites, take screenshots, or do anything involving Chrome automation — especially if the target site has bot protection like Cloudflare or Akamai.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Anti-Detect Browser Automation with patchright-cli
|
|
@@ -28,7 +28,7 @@ patchright-cli screenshot # capture the page
|
|
|
28
28
|
patchright-cli close # done
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
Every interaction follows: **open -> snapshot -> read refs -> interact -> snapshot again -> repeat**. Refs are
|
|
31
|
+
Every interaction follows: **open -> snapshot -> read refs -> interact -> snapshot again -> repeat**. A ref (`e5`, or `f3e5` inside an iframe and after a navigation) names one element until it leaves the page; a ref whose element is gone fails fast with `no longer matches an element` -- re-snapshot then. Refs are per tab: after `tab-select`, use the snapshot it prints. A click that opens a popup makes the popup current, and the popup's first-document refs (`e1`, `e2`, ...) can reuse numbers from the opener, so use the snapshot printed after the click.
|
|
32
32
|
|
|
33
33
|
## Command chaining
|
|
34
34
|
|
|
@@ -101,6 +101,8 @@ These go before the command:
|
|
|
101
101
|
--show-port=9322 # Dashboard port (default: 9322)
|
|
102
102
|
--raw # Strip page/snapshot decorations from output
|
|
103
103
|
--json # Wrap full response as JSON ({success, output, ...})
|
|
104
|
+
--toon # TOON for results with structured data (list, tab-list, cookie-list,
|
|
105
|
+
# find, console, network, url, title, ...); others print as usual
|
|
104
106
|
```
|
|
105
107
|
|
|
106
108
|
These go *after* the command instead:
|
|
@@ -147,9 +149,9 @@ snapshot <ref> # Subtree of a specific element
|
|
|
147
149
|
snapshot --selector="#main" # Subtree of a CSS selector -- must match exactly
|
|
148
150
|
# one element. No ref needed, so
|
|
149
151
|
# this works before the first snapshot
|
|
150
|
-
snapshot --depth=N #
|
|
151
|
-
snapshot -i # Interactive elements
|
|
152
|
-
snapshot --boxes # Append [box=x,y,w,h]
|
|
152
|
+
snapshot --depth=N # Levels 0..N; a cut node ends in `# +N refs`
|
|
153
|
+
snapshot -i # Interactive elements (and named landmarks around them)
|
|
154
|
+
snapshot --boxes # Append [box=x,y,w,h] (page coordinates, iframes too)
|
|
153
155
|
```
|
|
154
156
|
|
|
155
157
|
### Searching instead of snapshotting
|
|
@@ -163,8 +165,14 @@ patchright-cli find --regex "sign (in|up)" # regex, case-insensitive
|
|
|
163
165
|
patchright-cli find --regex "/Sign In/" # slash form carries flags (i, m, s)
|
|
164
166
|
patchright-cli find "price" --all # include text/paragraph nodes
|
|
165
167
|
patchright-cli find "hide" --limit=50 # default limit is 20
|
|
168
|
+
patchright-cli find --role=button --description="Deletes" # role + accessible description
|
|
166
169
|
```
|
|
167
170
|
|
|
171
|
+
The snapshot never shows accessible descriptions (`aria-describedby`,
|
|
172
|
+
`aria-description`, a `title` that is not the name). To target an element by
|
|
173
|
+
one, use `find --role=<role>` with `--name` and/or `--description`: substring
|
|
174
|
+
and case-insensitive, `/regex/i`, or whole with `--exact`. It returns refs.
|
|
175
|
+
|
|
168
176
|
`find` searches links, buttons, inputs and headings by default — the things
|
|
169
177
|
you can act on. Use `--all` when you are looking for page *content* rather
|
|
170
178
|
than a control.
|
|
@@ -174,13 +182,13 @@ controls stay distinguishable:
|
|
|
174
182
|
|
|
175
183
|
```
|
|
176
184
|
# table > rowgroup > cell "407 points by pluc 4 hours ago | hide | 321 ..."
|
|
177
|
-
- link "hide"
|
|
185
|
+
- link "hide" [ref=e49]:
|
|
178
186
|
- /url: hide?id=49489982
|
|
179
187
|
```
|
|
180
188
|
|
|
181
|
-
Refs from `find` are
|
|
182
|
-
usable with `click`, `fill`, and the rest.
|
|
183
|
-
`
|
|
189
|
+
Refs from `find` are the same refs `snapshot` prints and are immediately
|
|
190
|
+
usable with `click`, `fill`, and the rest. A hit with no ref of its own (a
|
|
191
|
+
`text:` line or an `option`) names the element to act on as `[in=e12]`.
|
|
184
192
|
|
|
185
193
|
When output says `Found 20 of 340 matches`, narrow the query rather than
|
|
186
194
|
raising `--limit`.
|
|
@@ -198,6 +206,8 @@ drop <ref> --path=./file.png # Drop file onto element (HTML5 drop from outside)
|
|
|
198
206
|
drop <ref> --data="text/plain=hello" # Drop arbitrary MIME data
|
|
199
207
|
```
|
|
200
208
|
|
|
209
|
+
`drop` fails (exit 1) when the target does not accept drops, meaning its `dragover` handler does not call `preventDefault()`. Before, it reported success without anything being dropped. Drop onto the element that handles the drop, not onto a wrapper around it.
|
|
210
|
+
|
|
201
211
|
### Form input
|
|
202
212
|
|
|
203
213
|
```bash
|
|
@@ -235,14 +245,6 @@ press <key> # Keypress (Enter, ArrowDown, etc.)
|
|
|
235
245
|
keydown <key> / keyup <key> # Hold/release key
|
|
236
246
|
```
|
|
237
247
|
|
|
238
|
-
### Mouse
|
|
239
|
-
|
|
240
|
-
```bash
|
|
241
|
-
mousemove <x> <y> # Move to coordinates
|
|
242
|
-
mousedown / mouseup # Button down/up
|
|
243
|
-
mousewheel <dx> <dy> # Scroll wheel
|
|
244
|
-
```
|
|
245
|
-
|
|
246
248
|
### Tabs
|
|
247
249
|
|
|
248
250
|
```bash
|
|
@@ -306,7 +308,7 @@ dialog-dismiss # Dismiss next dialog
|
|
|
306
308
|
### DevTools
|
|
307
309
|
|
|
308
310
|
```bash
|
|
309
|
-
console #
|
|
311
|
+
console # Start capture / show captured console messages
|
|
310
312
|
console warning # Filter by level
|
|
311
313
|
network # Show network requests (each line is `#<id> METHOD STATUS URL`)
|
|
312
314
|
requests # Alias for `network`
|
|
@@ -318,6 +320,38 @@ highlight <ref> # Persistent overlay on element [--style=CSS]
|
|
|
318
320
|
highlight <ref> --hide # Remove overlay; `highlight --hide` clears all
|
|
319
321
|
```
|
|
320
322
|
|
|
323
|
+
The first `console` call starts CDP Runtime capture across this session's existing
|
|
324
|
+
and future pages, including popups. Earlier messages are unavailable: call it
|
|
325
|
+
before reproducing an issue, then again to read messages. Capture makes CDP
|
|
326
|
+
detectable until the session closes; `console --clear` only clears the buffer.
|
|
327
|
+
|
|
328
|
+
A highlight is page-visible while shown (an `<x-pw-glass>` element under `<html>`);
|
|
329
|
+
`--hide` removes the element once no highlight is left. `pick-locator` refuses to
|
|
330
|
+
run without `--detectable`: Playwright's recorder then stays in every page of the
|
|
331
|
+
session (`window.playwright`, `__pw_*` globals, an `<x-pw-glass>` element it
|
|
332
|
+
re-adds) until the session closes, so use a throwaway session for it.
|
|
333
|
+
|
|
334
|
+
### Debugger (step through a command's browser calls)
|
|
335
|
+
|
|
336
|
+
```bash
|
|
337
|
+
debugger-pause # Arm: the next page action, navigation or eval pauses
|
|
338
|
+
click e3 # Replies at once: "Paused before: Evaluate (held: `click e3`)"
|
|
339
|
+
snapshot # Other commands still run while paused, actions included
|
|
340
|
+
debugger-step # Run that call, pause before the next ("Click ...")
|
|
341
|
+
debugger-resume # Let the held command finish, turn the debugger off
|
|
342
|
+
debugger-status # off | armed | paused + call title and held command
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
This is Playwright's action debugger, not a JavaScript debugger: it holds
|
|
346
|
+
patchright-cli's own calls in the driver, sends nothing to Chrome, and page
|
|
347
|
+
scripts keep running, so pages cannot detect it. Only page actions, navigation,
|
|
348
|
+
`eval` and element getters pause; `snapshot`, `title`, cookies, `state-save`,
|
|
349
|
+
`tab-new` and `highlight` run straight through (the reply says so) and leave it
|
|
350
|
+
armed. While one call is held, other commands, actions included, run at once,
|
|
351
|
+
so their side effects can land before the held one's. After `debugger-step` the
|
|
352
|
+
debugger stays armed until `debugger-resume`, which also cancels an armed pause
|
|
353
|
+
nothing has hit. `close` while paused resumes and closes.
|
|
354
|
+
|
|
321
355
|
### Recording and capture
|
|
322
356
|
|
|
323
357
|
```bash
|
|
@@ -352,36 +386,201 @@ set-media print # screen | print
|
|
|
352
386
|
clear-media
|
|
353
387
|
```
|
|
354
388
|
|
|
355
|
-
###
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
389
|
+
### Network mocking
|
|
390
|
+
|
|
391
|
+
`route "<pattern>"` mocks matching requests (`--status`, `--body`,
|
|
392
|
+
`--content-type`, `--header`); `route-list` and `unroute` manage them, and
|
|
393
|
+
`network-state-set offline|online` simulates connectivity.
|
|
394
|
+
|
|
395
|
+
### Passkeys (WebAuthn)
|
|
396
|
+
|
|
397
|
+
Run a `passkey-*` command, such as `passkey-list`, BEFORE the page calls
|
|
398
|
+
`navigator.credentials.create()` or `.get()`. The first one installs a virtual
|
|
399
|
+
authenticator in the session; until then the page gets Chrome's native OS
|
|
400
|
+
passkey dialog and the ceremony hangs. Then `passkey-list` shows what the page
|
|
401
|
+
registered, `passkey-add <rp-id>` seeds one, and `passkey-export` /
|
|
402
|
+
`passkey-import` keep passkeys across sessions (the export holds private keys).
|
|
403
|
+
|
|
404
|
+
## Command reference
|
|
405
|
+
|
|
406
|
+
Every command, its flags and what it does. `patchright-cli <command> --help`
|
|
407
|
+
shows one command's flag defaults and examples; `patchright-cli` with no
|
|
408
|
+
arguments shows whether the daemon is up and which sessions are open.
|
|
409
|
+
|
|
410
|
+
<!-- BEGIN GENERATED: commands (scripts/gen_skill.py from COMMAND_SPECS; do not edit by hand) -->
|
|
411
|
+
```bash
|
|
412
|
+
# Core
|
|
413
|
+
open [url] [--block-networks] [--headed] [--webmcp] # Open browser (starts daemon if needed)
|
|
414
|
+
attach --cdp=<url> [--cdp-headers] [--cdp-timeout] [--block-networks] # Attach to running Chrome via CDP
|
|
415
|
+
goto <url> # Navigate to URL
|
|
416
|
+
click <ref> [button] [--modifiers] [--scroll] # Click element
|
|
417
|
+
dblclick <ref> [button] [--modifiers] # Double-click element
|
|
418
|
+
fill <ref> <value> [--submit] # Fill text into element
|
|
419
|
+
type <text> [--submit] # Type text via keyboard
|
|
420
|
+
hover <ref> [--scroll] # Hover over element
|
|
421
|
+
select <ref> <value> # Select dropdown option
|
|
422
|
+
check <ref> [--scroll] # Check checkbox/radio
|
|
423
|
+
uncheck <ref> # Uncheck checkbox/radio
|
|
424
|
+
snapshot [ref] [--selector] [--filename] [--depth] [--interactive] [--boxes] # Take accessibility snapshot
|
|
425
|
+
find <text> [--regex] [--all] [--limit] [--role] [--name] [--description] [--exact] # Search the snapshot for matching elements
|
|
426
|
+
eval <expr> [ref] [--file] # Evaluate JavaScript (expression, --file or stdin)
|
|
427
|
+
text <ref|selector> # Get text content of element
|
|
428
|
+
html [ref] [--selector] [--include-shadow] [--filename] [--max-chars] # Print page HTML, or one element's outerHTML
|
|
429
|
+
screenshot [ref] [--full-page] [--hires] [--filename] # Save screenshot
|
|
430
|
+
drag <from> <to> [--scroll] # Drag element to target
|
|
431
|
+
drop <ref> [--path] [--data] # Drop file/data onto element (fails if it does not accept drops)
|
|
432
|
+
close # Close browser session (or the --tab it is addressed to)
|
|
433
|
+
detach # Detach attached session (keep external browser running)
|
|
434
|
+
|
|
435
|
+
# Navigation
|
|
436
|
+
go-back # Go back
|
|
437
|
+
go-forward # Go forward
|
|
438
|
+
reload # Reload page
|
|
439
|
+
url # Print current URL
|
|
440
|
+
title # Print page title
|
|
441
|
+
|
|
442
|
+
# Keyboard
|
|
443
|
+
press <key> # Press key
|
|
444
|
+
keydown <key> # Key down
|
|
445
|
+
keyup <key> # Key up
|
|
446
|
+
|
|
447
|
+
# Mouse
|
|
448
|
+
mousemove <x> <y> # Move mouse
|
|
449
|
+
mousedown [button] # Mouse button down
|
|
450
|
+
mouseup [button] # Mouse button up
|
|
451
|
+
mousewheel <dx> <dy> # Scroll mouse wheel
|
|
452
|
+
|
|
453
|
+
# Scroll & Wait
|
|
454
|
+
scroll <dx> <dy> # Scroll by pixel offset
|
|
455
|
+
scroll-to <ref> # Scroll element into view
|
|
456
|
+
wait [ms] [--url] # Wait for milliseconds, or for a URL
|
|
457
|
+
wait-for <ref> [--state] # Wait for element to reach a state
|
|
458
|
+
|
|
459
|
+
# Tabs
|
|
460
|
+
tab-list # List tabs
|
|
461
|
+
tab-new [url] # Open new tab
|
|
462
|
+
tab-close [index] # Close tab
|
|
463
|
+
tab-select <index> # Switch to tab (default tab only)
|
|
464
|
+
|
|
465
|
+
# Dialog
|
|
466
|
+
dialog-accept [text] # Accept next dialog
|
|
467
|
+
dialog-dismiss # Dismiss next dialog
|
|
468
|
+
|
|
469
|
+
# Upload/Resize
|
|
470
|
+
upload <file> [ref] # Upload file to input
|
|
471
|
+
resize <w> <h> # Resize viewport
|
|
472
|
+
|
|
473
|
+
# Emulation
|
|
474
|
+
set-color-scheme <dark|light|no-preference> # Emulate prefers-color-scheme
|
|
475
|
+
clear-color-scheme # Stop emulating prefers-color-scheme
|
|
476
|
+
set-reduced-motion <reduce|no-preference> # Emulate prefers-reduced-motion
|
|
477
|
+
clear-reduced-motion # Stop emulating prefers-reduced-motion
|
|
478
|
+
set-forced-colors <active|none> # Emulate forced-colors
|
|
479
|
+
clear-forced-colors # Stop emulating forced-colors
|
|
480
|
+
set-contrast <more|no-preference> # Emulate prefers-contrast
|
|
481
|
+
clear-contrast # Stop emulating prefers-contrast
|
|
482
|
+
set-media <screen|print> # Emulate CSS media type
|
|
483
|
+
clear-media # Stop emulating the CSS media type
|
|
484
|
+
|
|
485
|
+
# State
|
|
486
|
+
state-save [file] # Save cookies+storage to JSON
|
|
487
|
+
state-load <file> # Load saved state
|
|
488
|
+
|
|
489
|
+
# Storage
|
|
490
|
+
cookie-list [--domain] [--path] # List cookies
|
|
491
|
+
cookie-get <name> # Get cookie
|
|
492
|
+
cookie-set <name> <value> [--domain] [--path] [--expires] [--httpOnly] [--secure] [--sameSite] # Set cookie
|
|
493
|
+
cookie-delete <name> # Delete cookie
|
|
494
|
+
cookie-clear # Clear all cookies
|
|
495
|
+
cookie-import <file> # Import cookies from JSON
|
|
496
|
+
cookie-export [file] # Export cookies to JSON
|
|
497
|
+
localstorage-list # List localStorage
|
|
498
|
+
localstorage-get <key> # Get localStorage item
|
|
499
|
+
localstorage-set <key> <value> # Set localStorage item
|
|
500
|
+
localstorage-delete <key> # Delete localStorage item
|
|
501
|
+
localstorage-clear # Clear localStorage
|
|
502
|
+
sessionstorage-list # List sessionStorage
|
|
503
|
+
sessionstorage-get <key> # Get sessionStorage item
|
|
504
|
+
sessionstorage-set <key> <value> # Set sessionStorage item
|
|
505
|
+
sessionstorage-delete <key> # Delete sessionStorage item
|
|
506
|
+
sessionstorage-clear # Clear sessionStorage
|
|
507
|
+
|
|
508
|
+
# Passkeys
|
|
509
|
+
passkey-list [--rp-id] [--id] # List virtual passkeys; run before the page uses WebAuthn
|
|
510
|
+
passkey-add <rp-id> [--id] [--user-handle] [--private-key] [--public-key] [--sign-count] # Seed a virtual passkey
|
|
511
|
+
passkey-delete <id> # Delete a virtual passkey by credential id
|
|
512
|
+
passkey-clear [--rp-id] # Delete all virtual passkeys
|
|
513
|
+
passkey-export [file] [--rp-id] # Export virtual passkeys with private keys to an owner-only JSON
|
|
514
|
+
passkey-import <file> # Seed virtual passkeys from a passkey-export file
|
|
515
|
+
|
|
516
|
+
# Permissions
|
|
517
|
+
grant-permissions <perms> [--origin] # Grant comma-separated permissions
|
|
518
|
+
|
|
519
|
+
# Route
|
|
520
|
+
route <pattern> [--status] [--body] [--content-type] [--header] [--remove-header] # Mock requests matching a URL pattern
|
|
521
|
+
route-list # List active routes
|
|
522
|
+
unroute [pattern] # Remove route(s)
|
|
523
|
+
network-state-set <online|offline> # Set online/offline
|
|
524
|
+
|
|
525
|
+
# Code
|
|
526
|
+
run-code <code> [--file] # Run raw JS in page context (code, --file or stdin)
|
|
527
|
+
|
|
528
|
+
# Tracing
|
|
529
|
+
tracing-start # Start Playwright tracing
|
|
530
|
+
tracing-stop # Stop tracing and save
|
|
531
|
+
|
|
532
|
+
# Video
|
|
533
|
+
video-start [--fps] # Start video recording
|
|
534
|
+
video-stop [--filename] # Stop recording and save
|
|
535
|
+
video-chapter <title> # Add chapter marker to video
|
|
536
|
+
video-show-actions [--duration] [--position] # Annotate actions in the recording
|
|
537
|
+
video-hide-actions # Stop annotating actions
|
|
538
|
+
|
|
539
|
+
# PDF
|
|
540
|
+
pdf [--filename] # Save page as PDF
|
|
541
|
+
|
|
542
|
+
# DevTools
|
|
543
|
+
console [level] [--clear] # Start session-wide CDP capture and show messages; earlier messages are unavailable (detectable)
|
|
544
|
+
network [--static] [--clear] # Show network requests
|
|
545
|
+
requests [--static] [--clear] # Alias for `network`
|
|
546
|
+
request <id> [--body] # Show full detail for a network request
|
|
547
|
+
generate-locator <ref> # Emit Playwright locator expression for a ref
|
|
548
|
+
pick-locator [--detectable] [--wait] [--cancel] # Wait for a person to click an element; print its locator (page-detectable: needs --detectable)
|
|
549
|
+
highlight <ref> [--style] [--hide] # Show overlay on element (page-detectable while shown; removed on --hide)
|
|
550
|
+
|
|
551
|
+
# Debugger
|
|
552
|
+
debugger-pause # Pause before the next page action, navigation or eval; that command replies at once, held
|
|
553
|
+
debugger-step # Run the paused call and pause before the next one; prints the held command's result
|
|
554
|
+
debugger-resume # Let the held command finish and print its result (or cancel an unhit pause)
|
|
555
|
+
debugger-status # Show the debugger state: off, armed, or the paused call and held command
|
|
556
|
+
|
|
557
|
+
# WebMCP
|
|
558
|
+
webmcp-list # List the WebMCP tools the page registers
|
|
559
|
+
webmcp-call <name> [json] [--params] # Call a WebMCP tool the page registers
|
|
560
|
+
|
|
561
|
+
# Session
|
|
562
|
+
list # List sessions
|
|
563
|
+
close-all # Close all sessions
|
|
564
|
+
kill-all [--force] # Kill all sessions and stop the daemon
|
|
565
|
+
delete-data # Delete this session's profile
|
|
566
|
+
|
|
567
|
+
# Profiles
|
|
568
|
+
profile-list # List profiles, their size and which session uses them
|
|
569
|
+
profile-delete <name> # Delete a named profile
|
|
570
|
+
|
|
571
|
+
# Dashboard
|
|
572
|
+
show [--annotate] [--wait] [--no-open] # Open session dashboard
|
|
573
|
+
|
|
574
|
+
# Codegen
|
|
575
|
+
codegen [file] # Start recording interactions
|
|
576
|
+
codegen-stop [file] # Stop recording and save script
|
|
577
|
+
|
|
578
|
+
# Setup
|
|
579
|
+
install --skills | --hooks [--uninstall] # Install agent skill files, or session-start hooks
|
|
580
|
+
mcp [--http] [--host=HOST] [--port=N] # Start MCP server (stdio by default)
|
|
581
|
+
daemon-info --json # Show daemon client protocol and token path without starting it
|
|
582
|
+
```
|
|
583
|
+
<!-- END GENERATED -->
|
|
385
584
|
|
|
386
585
|
---
|
|
387
586
|
|
|
@@ -2,97 +2,108 @@
|
|
|
2
2
|
|
|
3
3
|
## How the snapshot system works
|
|
4
4
|
|
|
5
|
-
patchright-cli
|
|
5
|
+
patchright-cli takes Playwright's AI-mode accessibility snapshot of the whole
|
|
6
|
+
page, iframes included, and saves it as YAML. Elements carry Playwright's own
|
|
7
|
+
refs, like `e5` or `f3e5`. You use these refs to target elements in commands
|
|
8
|
+
like `click`, `fill`, `hover`, etc.
|
|
6
9
|
|
|
7
10
|
```
|
|
8
11
|
open browser -> snapshot -> read refs -> interact -> snapshot again -> repeat
|
|
9
12
|
```
|
|
10
13
|
|
|
11
|
-
|
|
14
|
+
## What a ref is
|
|
15
|
+
|
|
16
|
+
- A ref names **one element** for as long as that element stays on the page.
|
|
17
|
+
Taking another snapshot, or acting, does not renumber it; new elements get
|
|
18
|
+
new numbers.
|
|
19
|
+
- `e5` is an element of the tab's first page. After a navigation (`goto`, a
|
|
20
|
+
link, `reload`) the page's refs gain a frame prefix, `f3e5`, and refs inside
|
|
21
|
+
an iframe always have one. Copy refs exactly as printed.
|
|
22
|
+
- A ref whose element was removed or replaced fails at once:
|
|
23
|
+
`Ref e7 no longer matches an element (removed or changed since the snapshot). Run snapshot.`
|
|
24
|
+
A ref from a page the tab has left fails with `is from a page this tab has left`.
|
|
25
|
+
Nothing falls back to "an element with the same role and name", so a stale
|
|
26
|
+
ref never clicks the wrong element.
|
|
27
|
+
- Refs are **per tab**. A ref that is not in this tab's last snapshot is refused:
|
|
28
|
+
`e2 is not from a snapshot of this tab; run snapshot (...)`. An element whose role
|
|
29
|
+
or name changes (a button relabelled "Saved") gets a new ref, so the old one is refused too.
|
|
30
|
+
After `tab-select`, use the snapshot it prints. A click that opens a popup makes
|
|
31
|
+
the popup current, and the popup's first-document refs (`e1`, `e2`, ...) can reuse
|
|
32
|
+
numbers from the opener, so use the snapshot printed after the click.
|
|
33
|
+
- `e5`, `@e5`, `ref=e5` and `[ref=e5]` all work. Anything else is a usage error (exit 2).
|
|
12
34
|
|
|
13
35
|
## Snapshot commands
|
|
14
36
|
|
|
15
37
|
```bash
|
|
16
38
|
patchright-cli snapshot # Full page snapshot
|
|
17
39
|
patchright-cli snapshot e3 # Subtree rooted at ref e3
|
|
18
|
-
patchright-cli snapshot --
|
|
40
|
+
patchright-cli snapshot --selector="#main" # Subtree under a CSS selector (exactly one match)
|
|
41
|
+
patchright-cli snapshot --depth=2 # Levels 0..2 only
|
|
42
|
+
patchright-cli snapshot -i # Interactive elements only
|
|
43
|
+
patchright-cli snapshot --boxes # [box=x,y,w,h] on each element
|
|
19
44
|
patchright-cli snapshot --filename=snap.yml # Save to custom filename
|
|
20
|
-
patchright-cli snapshot -i # Interactive-only elements
|
|
21
|
-
patchright-cli snapshot --interactive # Same as -i
|
|
22
45
|
```
|
|
23
46
|
|
|
24
|
-
### Options
|
|
25
|
-
|
|
26
47
|
| Flag | Effect |
|
|
27
48
|
|------|--------|
|
|
28
49
|
| `[ref]` | Show only the subtree rooted at the given ref |
|
|
29
|
-
| `--selector=<css>` | Show only the subtree under a CSS selector. Must match exactly one element |
|
|
30
|
-
| `--depth=N` |
|
|
31
|
-
| `-i` / `--interactive` |
|
|
50
|
+
| `--selector=<css>` | Show only the subtree under a CSS selector. Must match exactly one element that is in the accessibility tree |
|
|
51
|
+
| `--depth=N` | Show levels 0..N. A node whose children were cut ends in `# +N refs` (or `# +more`) |
|
|
52
|
+
| `-i` / `--interactive` | Interactive elements, clickable `generic [cursor=pointer]` nodes, a combobox's options, and the named landmarks and iframes around them. `text:` and `/url:` lines are dropped |
|
|
53
|
+
| `--boxes` | Append `[box=x,y,w,h]`: viewport coordinates in CSS pixels, converted to page coordinates inside iframes |
|
|
32
54
|
| `--filename=F` | Save snapshot to a custom file path |
|
|
33
55
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
56
|
+
Every view is cut from one full-page snapshot, so the refs it shows are the
|
|
57
|
+
page's refs: a ref from `snapshot e3`, `--depth` or `-i` works with every
|
|
58
|
+
command, and refs outside the printed part keep working too.
|
|
37
59
|
|
|
38
|
-
|
|
39
|
-
- After `click` that triggers navigation or DOM changes
|
|
40
|
-
- After form submission
|
|
41
|
-
- After `wait` / `wait-for` for dynamic content
|
|
42
|
-
- After `eval` / `run-code` that modifies the DOM
|
|
60
|
+
## When to re-snapshot
|
|
43
61
|
|
|
44
|
-
Most state-changing commands (click, fill, goto, etc.) **auto-snapshot** and
|
|
62
|
+
Most state-changing commands (click, fill, goto, etc.) **auto-snapshot** and
|
|
63
|
+
return the new snapshot. Re-snapshot yourself when the page changes on its own
|
|
64
|
+
(timers, AJAX), after `eval` / `run-code` that changes the DOM, or when a ref
|
|
65
|
+
reports `no longer matches an element`.
|
|
45
66
|
|
|
46
67
|
## Reading the snapshot
|
|
47
68
|
|
|
48
|
-
The snapshot is a YAML tree. Each element shows:
|
|
49
|
-
- Its **ref** (e.g., `e5`)
|
|
50
|
-
- Its **role** (button, link, textbox, heading, etc.)
|
|
51
|
-
- Its **name** or text content
|
|
52
|
-
- Child elements nested underneath
|
|
53
|
-
|
|
54
|
-
Example output:
|
|
55
69
|
```yaml
|
|
56
|
-
- heading "Welcome" [
|
|
57
|
-
|
|
58
|
-
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
-
|
|
62
|
-
-
|
|
63
|
-
-
|
|
70
|
+
- heading "Welcome" [level=1] [ref=e2]
|
|
71
|
+
- navigation "Main" [ref=e3]:
|
|
72
|
+
- link "Home" [ref=e4]:
|
|
73
|
+
- /url: /
|
|
74
|
+
- main [ref=e6]:
|
|
75
|
+
- textbox "Search" [ref=e7]
|
|
76
|
+
- button "Go" [ref=e8]
|
|
77
|
+
- generic [ref=e9] [cursor=pointer]: Open card
|
|
78
|
+
- combobox "Size" [ref=e10]:
|
|
79
|
+
- option "Small" [selected]
|
|
80
|
+
- option "Large"
|
|
81
|
+
- iframe [ref=e11]:
|
|
82
|
+
- button "Pay" [ref=f2e4]
|
|
64
83
|
```
|
|
65
84
|
|
|
66
|
-
|
|
85
|
+
- `[active]` marks the focused element, `[cursor=pointer]` a node that looks
|
|
86
|
+
clickable though its role does not say so.
|
|
87
|
+
- Wrapper `generic` nodes with nothing of their own are not printed; their
|
|
88
|
+
children move up a level.
|
|
89
|
+
- `text:` lines and `option`s have no ref. Select an option by its label:
|
|
90
|
+
`select e10 Large`.
|
|
67
91
|
|
|
68
|
-
|
|
69
|
-
The page has changed since the last snapshot. Run `snapshot` to get fresh refs and retry.
|
|
92
|
+
## Troubleshooting
|
|
70
93
|
|
|
71
94
|
### Element not visible or not interactive
|
|
72
|
-
Some elements are hidden or overlapped. Try:
|
|
73
95
|
- `scroll-to <ref>` to bring the element into view
|
|
74
|
-
- `wait-for <ref>` to wait until
|
|
75
|
-
- `snapshot
|
|
76
|
-
- `snapshot <ref>` to inspect a subtree for nested elements
|
|
77
|
-
- `snapshot --selector="#main"` to scope by CSS when you have no ref yet
|
|
78
|
-
|
|
79
|
-
### Refs from a scoped snapshot
|
|
80
|
-
|
|
81
|
-
A scoped snapshot -- `snapshot <ref>` or `snapshot --selector=<css>` -- numbers
|
|
82
|
-
its refs from `e1` within that subtree, and those refs resolve inside the same
|
|
83
|
-
subtree. They are not the numbers a full-page `snapshot` would give, so do not
|
|
84
|
-
mix refs from a scoped snapshot with refs from a full one: take a fresh
|
|
85
|
-
snapshot at the scope you intend to work in.
|
|
96
|
+
- `wait-for <ref>` to wait until it is visible (`--state=hidden` to wait until it goes)
|
|
97
|
+
- `snapshot <ref>` to inspect a subtree
|
|
86
98
|
|
|
87
99
|
### Too many elements in snapshot
|
|
88
|
-
Use `--depth=N
|
|
100
|
+
Use `find`, `--depth=N`, `-i`, or `snapshot <ref>`.
|
|
89
101
|
|
|
90
|
-
###
|
|
91
|
-
SPAs and pages with AJAX calls update the DOM without navigation. After triggering dynamic content (e.g., clicking a "Load more" button), wait briefly and re-snapshot:
|
|
102
|
+
### Elements that appear later
|
|
92
103
|
```bash
|
|
93
|
-
patchright-cli click e5 # Triggers dynamic load
|
|
104
|
+
patchright-cli click e5 # Triggers a dynamic load
|
|
94
105
|
patchright-cli wait 1000 # Wait for content
|
|
95
|
-
patchright-cli snapshot #
|
|
106
|
+
patchright-cli snapshot # Refs for the new elements
|
|
96
107
|
```
|
|
97
108
|
|
|
98
109
|
## `find` — searching the snapshot
|
|
@@ -103,14 +114,15 @@ find --regex <pattern> Regex match; bare patterns are case-insensitive
|
|
|
103
114
|
find --regex "/p/ims" Slash form; supported flags are i, m, s
|
|
104
115
|
find --all Search every node, not just interactive roles + heading
|
|
105
116
|
find --limit=N Cap rendered hits (default 20)
|
|
117
|
+
find --role=<role> Elements get_by_role matches (--name, --description, --exact)
|
|
106
118
|
```
|
|
107
119
|
|
|
108
120
|
### What gets searched
|
|
109
121
|
|
|
110
|
-
By default,
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
122
|
+
By default, every interactive role plus `heading`. This is deliberate: role
|
|
123
|
+
filtering is the single biggest lever on output size. Measured across 13
|
|
124
|
+
queries on four real pages it cut hits 4.3x (729 to 168); on one Wikipedia
|
|
125
|
+
query, 442 hits became 53.
|
|
114
126
|
|
|
115
127
|
Matching runs against a node's accessible name. For unnamed nodes such as
|
|
116
128
|
`- text: Star 95.3k`, the value after the colon is used instead. Property
|
|
@@ -120,7 +132,8 @@ lines like `- /url: ...` are not nodes and never match.
|
|
|
120
132
|
|
|
121
133
|
Per hit: a ` # ancestor > ancestor > parent` breadcrumb (3 deep, names cut at
|
|
122
134
|
45 characters, repeated names collapsed), then the matched node with its ref,
|
|
123
|
-
then its subtree.
|
|
135
|
+
then its subtree. A hit without a ref of its own (an `option`, or a `text:`
|
|
136
|
+
line under `--all`) shows the nearest element you can act on as `[in=e12]`.
|
|
124
137
|
|
|
125
138
|
`find` prints inline and writes no `.yml` file. `snapshot` still writes one.
|
|
126
139
|
|
|
@@ -80,7 +80,7 @@ patchright-cli state-save auth.json # Save cookies + localSt
|
|
|
80
80
|
patchright-cli state-load auth.json # Restore state
|
|
81
81
|
```
|
|
82
82
|
|
|
83
|
-
|
|
83
|
+
`state-load` replaces the session's state: it first clears the existing cookies, localStorage, IndexedDB and OPFS data, then applies the file. localStorage is applied to every origin in the file; you do not need to visit an origin first.
|
|
84
84
|
|
|
85
85
|
## Cookie persistence login pattern
|
|
86
86
|
|