patchright-cli 0.9.0__tar.gz → 0.9.1__tar.gz

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.
Files changed (60) hide show
  1. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/.claude-plugin/marketplace.json +1 -1
  2. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/.github/workflows/ci.yml +15 -5
  3. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/.github/workflows/publish-docker.yml +1 -1
  4. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/.github/workflows/publish.yml +8 -8
  5. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/Dockerfile +1 -1
  6. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/PKG-INFO +33 -1
  7. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/README.md +32 -0
  8. patchright_cli-0.9.1/docs/daemon-protocol.md +102 -0
  9. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/pyproject.toml +1 -1
  10. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/skills/patchright-cli/SKILL.md +34 -2
  11. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/src/patchright_cli/__init__.py +1 -1
  12. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/src/patchright_cli/cli.py +45 -2
  13. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/src/patchright_cli/daemon.py +109 -3
  14. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/src/patchright_cli/mcp_server.py +78 -0
  15. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/src/patchright_cli/ref_registry.py +35 -12
  16. patchright_cli-0.9.1/tests/test_daemon_info.py +53 -0
  17. patchright_cli-0.9.1/tests/test_daemon_read.py +118 -0
  18. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/tests/test_daemon_token.py +22 -0
  19. patchright_cli-0.9.1/tests/test_docker.py +112 -0
  20. patchright_cli-0.9.1/tests/test_emulation.py +203 -0
  21. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/tests/test_mcp.py +1 -1
  22. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/tests/test_ref_registry.py +87 -1
  23. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/uv.lock +1 -1
  24. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/.claude-plugin/skills/browser-automation.json +0 -0
  25. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/.github/dependabot.yml +0 -0
  26. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/.gitignore +0 -0
  27. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/.pre-commit-config.yaml +0 -0
  28. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/CLAUDE.md +0 -0
  29. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/CONTRIBUTING.md +0 -0
  30. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/GLOSSARY.md +0 -0
  31. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/LICENSE +0 -0
  32. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/Makefile +0 -0
  33. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/compose.yml +0 -0
  34. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/docs/installation.md +0 -0
  35. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/docs/mcp-architecture.svg +0 -0
  36. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/patchright-cli +0 -0
  37. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/patchright-cli.cmd +0 -0
  38. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/skills/patchright-cli/references/request-mocking.md +0 -0
  39. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/skills/patchright-cli/references/running-code.md +0 -0
  40. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/skills/patchright-cli/references/session-management.md +0 -0
  41. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/skills/patchright-cli/references/snapshot-refs.md +0 -0
  42. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/skills/patchright-cli/references/storage-state.md +0 -0
  43. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/skills/patchright-cli/references/tracing.md +0 -0
  44. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/skills/patchright-cli/references/video-recording.md +0 -0
  45. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/src/patchright_cli/__main__.py +0 -0
  46. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/src/patchright_cli/dashboard.py +0 -0
  47. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/src/patchright_cli/snapshot.py +0 -0
  48. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/tests/__init__.py +0 -0
  49. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/tests/fixture.html +0 -0
  50. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/tests/test_annotate.py +0 -0
  51. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/tests/test_attach.py +0 -0
  52. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/tests/test_cli_config.py +0 -0
  53. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/tests/test_daemon_handlers.py +0 -0
  54. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/tests/test_e2e.py +0 -0
  55. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/tests/test_navigation_policy.py +0 -0
  56. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/tests/test_network_guard.py +0 -0
  57. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/tests/test_packaging.py +0 -0
  58. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/tests/test_profiles.py +0 -0
  59. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/tests/test_supply_chain.py +0 -0
  60. {patchright_cli-0.9.0 → patchright_cli-0.9.1}/tests/test_tabs.py +0 -0
@@ -5,7 +5,7 @@
5
5
  },
6
6
  "metadata": {
7
7
  "description": "Anti-detect browser automation CLI & Skills for AI agents, powered by Patchright",
8
- "version": "0.9.0"
8
+ "version": "0.9.1"
9
9
  },
10
10
  "plugins": [
11
11
  {
@@ -10,8 +10,8 @@ jobs:
10
10
  lint:
11
11
  runs-on: ubuntu-latest
12
12
  steps:
13
- - uses: actions/checkout@v4
14
- - uses: astral-sh/setup-uv@v6
13
+ - uses: actions/checkout@v7
14
+ - uses: astral-sh/setup-uv@v7
15
15
  with:
16
16
  version: ">=0.7,<0.8"
17
17
  python-version: "3.12"
@@ -28,8 +28,8 @@ jobs:
28
28
  python-version: "3.12"
29
29
  runs-on: ${{ matrix.os }}
30
30
  steps:
31
- - uses: actions/checkout@v4
32
- - uses: astral-sh/setup-uv@v6
31
+ - uses: actions/checkout@v7
32
+ - uses: astral-sh/setup-uv@v7
33
33
  with:
34
34
  version: ">=0.7,<0.8"
35
35
  python-version: ${{ matrix.python-version }}
@@ -39,7 +39,7 @@ jobs:
39
39
  docker:
40
40
  runs-on: ubuntu-latest
41
41
  steps:
42
- - uses: actions/checkout@v4
42
+ - uses: actions/checkout@v7
43
43
  - run: docker build -t patchright-cli:ci .
44
44
  - run: docker run --rm patchright-cli:ci --help
45
45
  - name: Browser session inside the container
@@ -78,6 +78,16 @@ jobs:
78
78
  grep -q "refusing to start \`mcp --http\`" unprotected.log
79
79
  - name: compose.yml works without a token
80
80
  run: docker compose config -q
81
+ - uses: astral-sh/setup-uv@v7
82
+ with:
83
+ version: ">=0.7,<0.8"
84
+ python-version: "3.12"
85
+ - name: Image test suite
86
+ run: |
87
+ uv venv && uv pip install -e ".[dev]"
88
+ uv run pytest tests/test_docker.py -v
89
+ env:
90
+ PATCHRIGHT_CLI_DOCKER_IMAGE: patchright-cli:ci
81
91
  - if: failure()
82
92
  run: |
83
93
  docker logs cli || true
@@ -24,7 +24,7 @@ jobs:
24
24
 
25
25
  steps:
26
26
  - name: Checkout repository
27
- uses: actions/checkout@v6
27
+ uses: actions/checkout@v7
28
28
 
29
29
  - name: Set up Docker Buildx
30
30
  uses: docker/setup-buildx-action@v4
@@ -15,10 +15,10 @@ jobs:
15
15
  build:
16
16
  runs-on: ubuntu-latest
17
17
  steps:
18
- - uses: actions/checkout@v4
18
+ - uses: actions/checkout@v7
19
19
 
20
20
  - name: Install uv
21
- uses: astral-sh/setup-uv@v5
21
+ uses: astral-sh/setup-uv@v7
22
22
 
23
23
  - name: Set up Python
24
24
  run: uv python install 3.12
@@ -27,7 +27,7 @@ jobs:
27
27
  run: uv build
28
28
 
29
29
  - name: Upload artifacts
30
- uses: actions/upload-artifact@v4
30
+ uses: actions/upload-artifact@v7
31
31
  with:
32
32
  name: dist
33
33
  path: dist/
@@ -40,13 +40,13 @@ jobs:
40
40
  id-token: write
41
41
  steps:
42
42
  - name: Download artifacts
43
- uses: actions/download-artifact@v4
43
+ uses: actions/download-artifact@v8
44
44
  with:
45
45
  name: dist
46
46
  path: dist/
47
47
 
48
48
  - name: Install uv
49
- uses: astral-sh/setup-uv@v5
49
+ uses: astral-sh/setup-uv@v7
50
50
 
51
51
  - name: Publish to PyPI
52
52
  run: uv publish
@@ -59,16 +59,16 @@ jobs:
59
59
  permissions:
60
60
  contents: write
61
61
  steps:
62
- - uses: actions/checkout@v4
62
+ - uses: actions/checkout@v7
63
63
 
64
64
  - name: Download artifacts
65
- uses: actions/download-artifact@v4
65
+ uses: actions/download-artifact@v8
66
66
  with:
67
67
  name: dist
68
68
  path: dist/
69
69
 
70
70
  - name: Create GitHub Release
71
- uses: softprops/action-gh-release@v2
71
+ uses: softprops/action-gh-release@v3
72
72
  with:
73
73
  files: dist/*
74
74
  generate_release_notes: true
@@ -1,6 +1,6 @@
1
1
  # Base images are pinned by multi-arch index digest; Dependabot (.github/dependabot.yml) bumps them.
2
2
  # uv is a named stage because Dependabot only reads image references on FROM lines.
3
- FROM ghcr.io/astral-sh/uv:latest@sha256:32a7bb39b496babbd997b0a39a4d66c126bdaf5661b302bf6f06abda8deca6ff AS uv
3
+ FROM ghcr.io/astral-sh/uv:latest@sha256:af22a52f5eafef3d78e551599d405c02df61919d18028f0cea8eda93bc9986d0 AS uv
4
4
 
5
5
  FROM python:3.12-slim@sha256:5b8b1421ccb6a525860a77863c049eab5847076cda34e030c75a80c58faf3f3c
6
6
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: patchright-cli
3
- Version: 0.9.0
3
+ Version: 0.9.1
4
4
  Summary: Anti-detect browser automation CLI using Patchright (undetected Playwright fork)
5
5
  Project-URL: Homepage, https://github.com/AhaiMk01/patchright-cli
6
6
  Project-URL: Repository, https://github.com/AhaiMk01/patchright-cli
@@ -211,6 +211,16 @@ patchright-cli screenshot
211
211
  patchright-cli close
212
212
  ```
213
213
 
214
+ Quote URLs that contain `&`; unquoted, bash, PowerShell and cmd.exe all split the command there. On Windows two cases need more than quotes: in cmd.exe without quotes, escape it as `^&` (inside quotes the `^` stays in the URL, so use one or the other), and when PowerShell runs a `.cmd`/`.bat` wrapper such as the repo's `patchright-cli.cmd`, PowerShell drops the quotes and cmd.exe splits at `&`, so pass the rest verbatim with `--%`:
215
+
216
+ ```
217
+ patchright-cli goto "https://example.com/?a=1&b=2" # any shell, patchright-cli.exe
218
+ patchright-cli goto https://example.com/?a=1^&b=2 # cmd.exe, unquoted
219
+ .\patchright-cli.cmd --% goto "https://example.com/?a=1&b=2" # PowerShell, .cmd wrapper
220
+ ```
221
+
222
+ Don't use `--%` with the installed `patchright-cli.exe`: in PowerShell 7 the quotes after it reach the CLI and end up in the URL.
223
+
214
224
  ---
215
225
 
216
226
  ## Architecture
@@ -236,6 +246,12 @@ The daemon only listens on `127.0.0.1`, but any local process can reach that por
236
246
  - Run the CLI as the same user, with the same home directory, as the daemon. In Docker the MCP server and daemon share a user and `HOME`, so this holds.
237
247
  - An older CLI talking to a newer daemon gets an error saying the daemon requires an auth token: upgrade, or stop the daemon (`patchright-cli kill-all` from the newer install, or end the process). A newer CLI talking to an older daemon finds no token file and sends none, which the older daemon accepts.
238
248
 
249
+ ### Daemon client protocol
250
+
251
+ Third-party clients can use the daemon TCP interface directly. The
252
+ [client protocol reference](docs/daemon-protocol.md) defines discovery,
253
+ authentication, message framing, replies, and compatibility rules.
254
+
239
255
  ---
240
256
 
241
257
  <details>
@@ -322,6 +338,22 @@ patchright-cli upload ./file.pdf e5 # Upload to specific input
322
338
  patchright-cli resize 1920 1080 # Resize viewport
323
339
  ```
324
340
 
341
+ ### Emulation
342
+ ```bash
343
+ patchright-cli set-color-scheme dark # dark | light | no-preference
344
+ patchright-cli clear-color-scheme
345
+ patchright-cli set-reduced-motion reduce # reduce | no-preference
346
+ patchright-cli clear-reduced-motion
347
+ patchright-cli set-forced-colors active # active | none
348
+ patchright-cli clear-forced-colors
349
+ patchright-cli set-contrast more # more | no-preference
350
+ patchright-cli clear-contrast
351
+ patchright-cli set-media print # screen | print
352
+ patchright-cli clear-media
353
+ ```
354
+
355
+ Each setting holds for the whole session, including tabs and popups opened later; `clear-*` drops just that one, back to the browser default. A popup gets the setting just after it opens, so a script that reads media queries the instant the popup is created may still see the default.
356
+
325
357
  ### Tabs
326
358
  ```bash
327
359
  patchright-cli tab-list
@@ -174,6 +174,16 @@ patchright-cli screenshot
174
174
  patchright-cli close
175
175
  ```
176
176
 
177
+ Quote URLs that contain `&`; unquoted, bash, PowerShell and cmd.exe all split the command there. On Windows two cases need more than quotes: in cmd.exe without quotes, escape it as `^&` (inside quotes the `^` stays in the URL, so use one or the other), and when PowerShell runs a `.cmd`/`.bat` wrapper such as the repo's `patchright-cli.cmd`, PowerShell drops the quotes and cmd.exe splits at `&`, so pass the rest verbatim with `--%`:
178
+
179
+ ```
180
+ patchright-cli goto "https://example.com/?a=1&b=2" # any shell, patchright-cli.exe
181
+ patchright-cli goto https://example.com/?a=1^&b=2 # cmd.exe, unquoted
182
+ .\patchright-cli.cmd --% goto "https://example.com/?a=1&b=2" # PowerShell, .cmd wrapper
183
+ ```
184
+
185
+ Don't use `--%` with the installed `patchright-cli.exe`: in PowerShell 7 the quotes after it reach the CLI and end up in the URL.
186
+
177
187
  ---
178
188
 
179
189
  ## Architecture
@@ -199,6 +209,12 @@ The daemon only listens on `127.0.0.1`, but any local process can reach that por
199
209
  - Run the CLI as the same user, with the same home directory, as the daemon. In Docker the MCP server and daemon share a user and `HOME`, so this holds.
200
210
  - An older CLI talking to a newer daemon gets an error saying the daemon requires an auth token: upgrade, or stop the daemon (`patchright-cli kill-all` from the newer install, or end the process). A newer CLI talking to an older daemon finds no token file and sends none, which the older daemon accepts.
201
211
 
212
+ ### Daemon client protocol
213
+
214
+ Third-party clients can use the daemon TCP interface directly. The
215
+ [client protocol reference](docs/daemon-protocol.md) defines discovery,
216
+ authentication, message framing, replies, and compatibility rules.
217
+
202
218
  ---
203
219
 
204
220
  <details>
@@ -285,6 +301,22 @@ patchright-cli upload ./file.pdf e5 # Upload to specific input
285
301
  patchright-cli resize 1920 1080 # Resize viewport
286
302
  ```
287
303
 
304
+ ### Emulation
305
+ ```bash
306
+ patchright-cli set-color-scheme dark # dark | light | no-preference
307
+ patchright-cli clear-color-scheme
308
+ patchright-cli set-reduced-motion reduce # reduce | no-preference
309
+ patchright-cli clear-reduced-motion
310
+ patchright-cli set-forced-colors active # active | none
311
+ patchright-cli clear-forced-colors
312
+ patchright-cli set-contrast more # more | no-preference
313
+ patchright-cli clear-contrast
314
+ patchright-cli set-media print # screen | print
315
+ patchright-cli clear-media
316
+ ```
317
+
318
+ Each setting holds for the whole session, including tabs and popups opened later; `clear-*` drops just that one, back to the browser default. A popup gets the setting just after it opens, so a script that reads media queries the instant the popup is created may still see the default.
319
+
288
320
  ### Tabs
289
321
  ```bash
290
322
  patchright-cli tab-list
@@ -0,0 +1,102 @@
1
+ # Daemon client protocol
2
+
3
+ The TCP interface is a public interface for third-party clients. The current
4
+ protocol version is **1**, defined by `PROTOCOL_VERSION` in `daemon.py`.
5
+
6
+ ## Discovery
7
+
8
+ `patchright-cli daemon-info --json` prints one JSON object and exits without
9
+ starting a daemon or browser, connecting to the daemon, or reading the token.
10
+ For example, on a Unix installation with home directory `/home/alice`:
11
+
12
+ ```json
13
+ {"version": "0.9.0", "protocol": 1, "port": 9321, "token_path": "/home/alice/.patchright-cli/daemon-9321.token"}
14
+ ```
15
+
16
+ `version` is the installed package version. `protocol` describes that installed
17
+ version's wire contract, not a handshake with a running daemon. After upgrading,
18
+ restart any older daemon before using the new contract.
19
+
20
+ `--port=N` and `--port N`, before or after the command, select the port and its
21
+ token path. The default port is 9321. There is currently no port or token-path
22
+ environment override. `token_path` is absolute and follows the current user's
23
+ home directory. The file need not exist for discovery to succeed. Discovery
24
+ reports configuration, not daemon readiness, and never prints the token value.
25
+ Older installations without this command do not advertise a protocol version.
26
+
27
+ ## Transport and authentication
28
+
29
+ Connect to `127.0.0.1` on the discovered port. Each connection carries one
30
+ request and one reply, after which the daemon closes the connection. Both
31
+ messages use the same framing:
32
+
33
+ 1. Four bytes containing the unsigned payload byte length in big-endian order
34
+ (`struct.pack("!I", length)`).
35
+ 2. That many bytes of UTF-8 encoded JSON, with an object as the top-level value.
36
+
37
+ Reads must loop until the entire header and payload arrive. There is no newline
38
+ or other delimiter. An incomplete request can close without a reply.
39
+
40
+ The daemon reads a request before checking its token, so it bounds that read:
41
+
42
+ - The whole request must arrive within 30 seconds of connecting, or the daemon
43
+ closes the connection without a reply. Commands themselves and replies have
44
+ no time limit.
45
+ - A request whose header announces more than 64 MiB (67,108,864 bytes) gets a
46
+ `success: false` reply whose `output` starts with `Daemon error: request of`,
47
+ sent without reading the body, and the connection closes.
48
+
49
+ The daemon writes a new secret to `~/.patchright-cli/daemon-<port>.token` when
50
+ it starts and removes its token on clean shutdown. Read the discovered
51
+ `token_path` as UTF-8 text and strip surrounding whitespace before each request.
52
+ The token may change when the daemon restarts. Send it in the request's `token`
53
+ field. Keep the value private. The client must run as a user who can read this
54
+ file. A missing file can indicate that the daemon has not started or has stopped.
55
+
56
+ ## Request fields
57
+
58
+ | Field | JSON type | Meaning |
59
+ | --- | --- | --- |
60
+ | `command` | string | Command name, such as `list`, `open`, or `snapshot`. |
61
+ | `args` | array of strings | Positional command arguments. Defaults to `[]` if omitted. |
62
+ | `options` | object | Command options using CLI option names without leading `--`. Defaults to `{}`. Values are the JSON the CLI sends: a string for `--name=value`, `true` for a bare flag, and an object for a few structured options (for example `viewport` is `{"width": 1280, "height": 720}`). |
63
+ | `cwd` | string or null | Absolute caller working directory for relative paths and output files. Omitted or null uses the daemon's working directory. |
64
+ | `token` | string | Current authentication token read from `token_path`. Required. |
65
+
66
+ `options.session` and `options.tab` select a session and named tab; both default
67
+ to `default`. Command-specific arguments and options follow CLI help.
68
+
69
+ ## Reply fields
70
+
71
+ Every reply carries an explicit boolean `success` and a string `output`, on
72
+ both success and failure. `success: false` indicates authentication, command,
73
+ or daemon errors. `output` contains the result or a human-readable error.
74
+ Additional fields, such as `snapshot_path`, are command-specific. Clients must
75
+ ignore unknown fields. No structured error codes are currently provided.
76
+
77
+ Clients can detect these states in failed replies by matching these output
78
+ fragments. Surrounding context and recovery advice can vary. The fragments in
79
+ this table are part of the protocol:
80
+
81
+ | Output fragment | State |
82
+ | --- | --- |
83
+ | `Session '<name>' is not open` | The requested session is absent. |
84
+ | `Tab '<name>' is not open` | The requested named tab is absent from the session. |
85
+ | `requires an auth token` | The request omitted `token`. |
86
+ | `rejected the auth token` | The supplied token is invalid or stale. Read the token file fresh before retrying. |
87
+ | `Daemon error: request of` | The request exceeded the 64 MiB limit. |
88
+
89
+ Best effort, not covered by the compatibility rules below: a command on a page,
90
+ context or browser that has closed usually fails with Playwright's own message
91
+ containing `has been closed`. That text comes from Playwright and can change
92
+ with its version without a protocol increment.
93
+
94
+ ## Compatibility
95
+
96
+ `protocol` is independent of the package version. Any incompatible change to
97
+ framing, request limits, request fields (`command`, `args`, `options`, `cwd`,
98
+ `token`), reply fields (`success`, `output`), authentication, or the
99
+ state-detection fragments in the table above requires a protocol increment.
100
+ Raising a request limit is not incompatible. Optional additive fields and new
101
+ commands do not require an increment. Clients can reject unsupported protocol
102
+ versions before sending requests.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "patchright-cli"
3
- version = "0.9.0"
3
+ version = "0.9.1"
4
4
  description = "Anti-detect browser automation CLI using Patchright (undetected Playwright fork)"
5
5
  license = "Apache-2.0"
6
6
  requires-python = ">=3.10"
@@ -59,8 +59,21 @@ patchright-cli goto "https://example.com/search?q=cats&page=2"
59
59
  ```
60
60
 
61
61
  The same applies to `#` (a bash comment), spaces, and `%` (expanded by
62
- cmd.exe), and to any argument holding shell metacharacters. Quoting always
63
- works; leave it on.
62
+ cmd.exe), and to any argument holding shell metacharacters. Quoting works for
63
+ the installed `patchright-cli.exe` in bash, PowerShell and cmd.exe; leave it on.
64
+
65
+ On Windows, two cases need more than quotes:
66
+
67
+ ```
68
+ # cmd.exe without quotes: escape the & as ^&. Inside quotes ^ is kept
69
+ # literally, so use one or the other, never both.
70
+ patchright-cli goto https://example.com/search?q=cats^&page=2
71
+
72
+ # PowerShell calling a .cmd/.bat wrapper (such as the repo's patchright-cli.cmd):
73
+ # PowerShell drops the quotes and cmd.exe splits at &. Pass the rest verbatim
74
+ # with --%. Don't use --% with patchright-cli.exe: in PowerShell 7 the quotes end up in the URL.
75
+ .\patchright-cli.cmd --% goto "https://example.com/search?q=cats&page=2"
76
+ ```
64
77
 
65
78
  ## Global options
66
79
 
@@ -320,6 +333,25 @@ show # Live dashboard
320
333
  show --annotate # Ask a human to mark up the page and wait for it
321
334
  ```
322
335
 
336
+ ### Emulation
337
+
338
+ Each setting holds for the whole session: every open tab, and tabs and popups
339
+ opened later (a popup gets it just after it opens). `clear-*` drops just that
340
+ one, back to the browser default.
341
+
342
+ ```bash
343
+ set-color-scheme dark # dark | light | no-preference
344
+ clear-color-scheme
345
+ set-reduced-motion reduce # reduce | no-preference
346
+ clear-reduced-motion
347
+ set-forced-colors active # active | none
348
+ clear-forced-colors
349
+ set-contrast more # more | no-preference
350
+ clear-contrast
351
+ set-media print # screen | print
352
+ clear-media
353
+ ```
354
+
323
355
  ### Storage
324
356
 
325
357
  ```bash
@@ -1,3 +1,3 @@
1
1
  """patchright-cli — Undetected browser automation CLI using Patchright."""
2
2
 
3
- __version__ = "0.9.0"
3
+ __version__ = "0.9.1"
@@ -17,7 +17,7 @@ from pathlib import Path
17
17
  import click
18
18
 
19
19
  from patchright_cli import __version__
20
- from patchright_cli.daemon import DEFAULT_PORT, ensure_daemon_running, read_daemon_token
20
+ from patchright_cli.daemon import DEFAULT_PORT, PROTOCOL_VERSION, ensure_daemon_running, read_daemon_token, token_path
21
21
 
22
22
 
23
23
  def _soften_output_encoding(*streams) -> None:
@@ -497,6 +497,17 @@ COMMANDS_HELP = {
497
497
  # Upload / Resize
498
498
  "upload": "upload <file> [ref] Upload file to input",
499
499
  "resize": "resize <w> <h> Resize viewport",
500
+ # Emulation
501
+ "set-color-scheme": "set-color-scheme <dark|light|no-preference> Emulate prefers-color-scheme",
502
+ "clear-color-scheme": "clear-color-scheme Stop emulating prefers-color-scheme",
503
+ "set-reduced-motion": "set-reduced-motion <reduce|no-preference> Emulate prefers-reduced-motion",
504
+ "clear-reduced-motion": "clear-reduced-motion Stop emulating prefers-reduced-motion",
505
+ "set-forced-colors": "set-forced-colors <active|none> Emulate forced-colors",
506
+ "clear-forced-colors": "clear-forced-colors Stop emulating forced-colors",
507
+ "set-contrast": "set-contrast <more|no-preference> Emulate prefers-contrast",
508
+ "clear-contrast": "clear-contrast Stop emulating prefers-contrast",
509
+ "set-media": "set-media <screen|print> Emulate CSS media type",
510
+ "clear-media": "clear-media Stop emulating the CSS media type",
500
511
  # State
501
512
  "state-save": "state-save [file] Save cookies+storage to JSON",
502
513
  "state-load": "state-load <file> Load saved state",
@@ -547,6 +558,7 @@ COMMANDS_HELP = {
547
558
  # Setup
548
559
  "install": "install --skills Install skill files for AI agents",
549
560
  "mcp": "mcp [--http] [--host=HOST] [--port=N] Start MCP server (stdio by default)",
561
+ "daemon-info": "daemon-info --json Show daemon client protocol and token path without starting it",
550
562
  }
551
563
 
552
564
  ALL_COMMANDS = list(COMMANDS_HELP.keys())
@@ -619,6 +631,21 @@ def _print_help():
619
631
  ("Tabs", ["tab-list", "tab-new", "tab-close", "tab-select"]),
620
632
  ("Dialog", ["dialog-accept", "dialog-dismiss"]),
621
633
  ("Upload/Resize", ["upload", "resize"]),
634
+ (
635
+ "Emulation",
636
+ [
637
+ "set-color-scheme",
638
+ "clear-color-scheme",
639
+ "set-reduced-motion",
640
+ "clear-reduced-motion",
641
+ "set-forced-colors",
642
+ "clear-forced-colors",
643
+ "set-contrast",
644
+ "clear-contrast",
645
+ "set-media",
646
+ "clear-media",
647
+ ],
648
+ ),
622
649
  ("State", ["state-save", "state-load"]),
623
650
  (
624
651
  "Storage",
@@ -653,7 +680,7 @@ def _print_help():
653
680
  ("Profiles", ["profile-list", "profile-delete"]),
654
681
  ("Dashboard", ["show"]),
655
682
  ("Codegen", ["codegen", "codegen-stop"]),
656
- ("Setup", ["install", "mcp"]),
683
+ ("Setup", ["install", "mcp", "daemon-info"]),
657
684
  ]
658
685
  for cat_name, cmds in categories:
659
686
  click.echo(f"\n {cat_name}:")
@@ -823,6 +850,22 @@ def main():
823
850
  _print_help()
824
851
  sys.exit(1)
825
852
 
853
+ if command == "daemon-info":
854
+ if not as_json or args or extra_opts:
855
+ click.echo("Usage: patchright-cli daemon-info --json [--port=N]", err=True)
856
+ sys.exit(1)
857
+ click.echo(
858
+ json.dumps(
859
+ {
860
+ "version": __version__,
861
+ "protocol": PROTOCOL_VERSION,
862
+ "port": port,
863
+ "token_path": str(token_path(port).resolve()),
864
+ }
865
+ )
866
+ )
867
+ return
868
+
826
869
  if command == "install":
827
870
  _handle_install(args + [k if v is True else f"{k}={v}" for k, v in extra_opts.items()])
828
871
  sys.exit(0)