drissionpage-cli 0.1.0__tar.gz → 0.1.2__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.
- {drissionpage_cli-0.1.0 → drissionpage_cli-0.1.2}/PKG-INFO +54 -26
- {drissionpage_cli-0.1.0 → drissionpage_cli-0.1.2}/README.md +53 -25
- {drissionpage_cli-0.1.0 → drissionpage_cli-0.1.2}/drissionpage_cli/__init__.py +60 -15
- {drissionpage_cli-0.1.0 → drissionpage_cli-0.1.2}/drissionpage_cli/skills/drissionpage-cli/SKILL.md +3 -1
- {drissionpage_cli-0.1.0 → drissionpage_cli-0.1.2}/drissionpage_cli/skills/drissionpage-cli/references/session-management.md +4 -1
- {drissionpage_cli-0.1.0 → drissionpage_cli-0.1.2}/drissionpage_cli.egg-info/PKG-INFO +54 -26
- {drissionpage_cli-0.1.0 → drissionpage_cli-0.1.2}/pyproject.toml +1 -1
- {drissionpage_cli-0.1.0 → drissionpage_cli-0.1.2}/tests/test_unit.py +63 -1
- {drissionpage_cli-0.1.0 → drissionpage_cli-0.1.2}/LICENSE +0 -0
- {drissionpage_cli-0.1.0 → drissionpage_cli-0.1.2}/drissionpage_cli/skills/drissionpage-cli/references/dual-mode.md +0 -0
- {drissionpage_cli-0.1.0 → drissionpage_cli-0.1.2}/drissionpage_cli/skills/drissionpage-cli/references/element-locators.md +0 -0
- {drissionpage_cli-0.1.0 → drissionpage_cli-0.1.2}/drissionpage_cli/skills/drissionpage-cli/references/network-listening.md +0 -0
- {drissionpage_cli-0.1.0 → drissionpage_cli-0.1.2}/drissionpage_cli/skills/drissionpage-cli/references/running-code.md +0 -0
- {drissionpage_cli-0.1.0 → drissionpage_cli-0.1.2}/drissionpage_cli/skills/drissionpage-cli/references/screenshots-pdf.md +0 -0
- {drissionpage_cli-0.1.0 → drissionpage_cli-0.1.2}/drissionpage_cli/skills/drissionpage-cli/references/storage-state.md +0 -0
- {drissionpage_cli-0.1.0 → drissionpage_cli-0.1.2}/drissionpage_cli.egg-info/SOURCES.txt +0 -0
- {drissionpage_cli-0.1.0 → drissionpage_cli-0.1.2}/drissionpage_cli.egg-info/dependency_links.txt +0 -0
- {drissionpage_cli-0.1.0 → drissionpage_cli-0.1.2}/drissionpage_cli.egg-info/entry_points.txt +0 -0
- {drissionpage_cli-0.1.0 → drissionpage_cli-0.1.2}/drissionpage_cli.egg-info/requires.txt +0 -0
- {drissionpage_cli-0.1.0 → drissionpage_cli-0.1.2}/drissionpage_cli.egg-info/top_level.txt +0 -0
- {drissionpage_cli-0.1.0 → drissionpage_cli-0.1.2}/setup.cfg +0 -0
- {drissionpage_cli-0.1.0 → drissionpage_cli-0.1.2}/tests/test_integration.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: drissionpage-cli
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
4
4
|
Summary: DrissionPage CLI - Token-efficient browser automation for coding agents
|
|
5
5
|
Author: DrissionPage-MCP Contributors
|
|
6
6
|
License: Apache-2.0
|
|
@@ -25,11 +25,15 @@ Requires-Dist: DrissionPage>=4.0.0
|
|
|
25
25
|
Dynamic: license-file
|
|
26
26
|
|
|
27
27
|
# DrissionPage-cli
|
|
28
|
-
|
|
29
28
|
Token-efficient browser automation CLI for coding agents, powered by [DrissionPage](https://DrissionPage.cn).
|
|
30
29
|
|
|
31
30
|
Mirrors the architecture of [playwright-cli](https://github.com/microsoft/playwright-cli) but uses DrissionPage as the backend — pure Python, no Node.js required.
|
|
32
31
|
|
|
32
|
+
## Why use drissionpage-cli
|
|
33
|
+
|
|
34
|
+
If you know, you know. If you don't, go use playwright-cli.
|
|
35
|
+
|
|
36
|
+
|
|
33
37
|
## Why CLI + Skills over MCP
|
|
34
38
|
|
|
35
39
|
Modern coding agents (Claude Code, GitHub Copilot, etc.) increasingly favour CLI-based workflows exposed as **SKILLs** over MCP because CLI invocations are more token-efficient: they avoid loading large tool schemas and verbose accessibility trees into the model context. This makes CLI + SKILLs better suited for high-throughput agents that must balance browser automation with large codebases within limited context windows.
|
|
@@ -41,18 +45,18 @@ Modern coding agents (Claude Code, GitHub Copilot, etc.) increasingly favour CLI
|
|
|
41
45
|
|
|
42
46
|
## Installation
|
|
43
47
|
|
|
44
|
-
### From
|
|
48
|
+
### From PyPI (recommended)
|
|
45
49
|
|
|
46
50
|
```bash
|
|
47
|
-
|
|
48
|
-
cd DrissionPage-MCP/DrissionPage-cli
|
|
49
|
-
pip install -e .
|
|
51
|
+
pip install drissionpage-cli
|
|
50
52
|
```
|
|
51
53
|
|
|
52
|
-
###
|
|
54
|
+
### From source (development)
|
|
53
55
|
|
|
54
56
|
```bash
|
|
55
|
-
|
|
57
|
+
git clone https://github.com/nicekate/DrissionPage-MCP.git
|
|
58
|
+
cd DrissionPage-MCP/DrissionPage-cli
|
|
59
|
+
pip install -e .
|
|
56
60
|
```
|
|
57
61
|
|
|
58
62
|
After installation the `drissionpage-cli` command is available globally:
|
|
@@ -70,6 +74,29 @@ drissionpage-cli install --skills
|
|
|
70
74
|
|
|
71
75
|
This copies the SKILL.md and reference guides into `.claude/skills/drissionpage-cli/` so that Claude Code (or any compatible agent) can discover them automatically.
|
|
72
76
|
|
|
77
|
+
**One-liner** — install the package and set up Claude Code skills in a single command:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
pip install drissionpage-cli && drissionpage-cli install --skills
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
#### What gets installed
|
|
84
|
+
|
|
85
|
+
The `install --skills` command copies the following into `.claude/skills/drissionpage-cli/`:
|
|
86
|
+
|
|
87
|
+
| File | Purpose |
|
|
88
|
+
|------|---------|
|
|
89
|
+
| `SKILL.md` | Skill definition & quick-start guide for the agent |
|
|
90
|
+
| `references/element-locators.md` | CSS, XPath, text, and attribute locator syntax |
|
|
91
|
+
| `references/running-code.md` | Custom DrissionPage Python code execution |
|
|
92
|
+
| `references/session-management.md` | Multiple concurrent browser sessions |
|
|
93
|
+
| `references/storage-state.md` | Cookies, localStorage, sessionStorage management |
|
|
94
|
+
| `references/screenshots-pdf.md` | Visual capture and PDF generation |
|
|
95
|
+
| `references/network-listening.md` | Network request monitoring |
|
|
96
|
+
| `references/dual-mode.md` | Browser + HTTP request mode switching |
|
|
97
|
+
|
|
98
|
+
Once installed, Claude Code automatically discovers the skill and can use `drissionpage-cli` commands for browser automation tasks.
|
|
99
|
+
|
|
73
100
|
## Quick Start
|
|
74
101
|
|
|
75
102
|
```bash
|
|
@@ -276,28 +303,29 @@ python3 -m pytest tests/ -v
|
|
|
276
303
|
|
|
277
304
|
```
|
|
278
305
|
DrissionPage-cli/
|
|
279
|
-
drissionpage_cli
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
306
|
+
drissionpage_cli/ # Main package
|
|
307
|
+
__init__.py # CLI entry point (59 commands)
|
|
308
|
+
skills/drissionpage-cli/ # Bundled skill files
|
|
309
|
+
SKILL.md
|
|
310
|
+
references/
|
|
311
|
+
element-locators.md
|
|
312
|
+
running-code.md
|
|
313
|
+
session-management.md
|
|
314
|
+
storage-state.md
|
|
315
|
+
screenshots-pdf.md
|
|
316
|
+
network-listening.md
|
|
317
|
+
dual-mode.md
|
|
318
|
+
pyproject.toml # Python packaging
|
|
319
|
+
requirements.txt # DrissionPage>=4.0.0
|
|
320
|
+
pytest.ini # Test configuration
|
|
283
321
|
README.md
|
|
284
322
|
LICENSE
|
|
285
323
|
scripts/
|
|
286
|
-
update.py
|
|
287
|
-
skills/drissionpage-cli/
|
|
288
|
-
SKILL.md # Agent skill definition
|
|
289
|
-
references/
|
|
290
|
-
element-locators.md # CSS, XPath, text, attribute locators
|
|
291
|
-
running-code.md # run-code for custom automation
|
|
292
|
-
session-management.md # Multiple browser sessions
|
|
293
|
-
storage-state.md # Cookies, localStorage, sessionStorage
|
|
294
|
-
screenshots-pdf.md # Visual capture
|
|
295
|
-
network-listening.md # Network monitoring
|
|
296
|
-
dual-mode.md # Browser + HTTP requests mode
|
|
324
|
+
update.py # Skill update script
|
|
297
325
|
tests/
|
|
298
|
-
conftest.py
|
|
299
|
-
test_unit.py
|
|
300
|
-
test_integration.py
|
|
326
|
+
conftest.py # Shared fixtures
|
|
327
|
+
test_unit.py # 92 unit tests (mocked, no browser)
|
|
328
|
+
test_integration.py # 30+ integration tests (real browser)
|
|
301
329
|
```
|
|
302
330
|
|
|
303
331
|
## Environment Variables
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
# DrissionPage-cli
|
|
2
|
-
|
|
3
2
|
Token-efficient browser automation CLI for coding agents, powered by [DrissionPage](https://DrissionPage.cn).
|
|
4
3
|
|
|
5
4
|
Mirrors the architecture of [playwright-cli](https://github.com/microsoft/playwright-cli) but uses DrissionPage as the backend — pure Python, no Node.js required.
|
|
6
5
|
|
|
6
|
+
## Why use drissionpage-cli
|
|
7
|
+
|
|
8
|
+
If you know, you know. If you don't, go use playwright-cli.
|
|
9
|
+
|
|
10
|
+
|
|
7
11
|
## Why CLI + Skills over MCP
|
|
8
12
|
|
|
9
13
|
Modern coding agents (Claude Code, GitHub Copilot, etc.) increasingly favour CLI-based workflows exposed as **SKILLs** over MCP because CLI invocations are more token-efficient: they avoid loading large tool schemas and verbose accessibility trees into the model context. This makes CLI + SKILLs better suited for high-throughput agents that must balance browser automation with large codebases within limited context windows.
|
|
@@ -15,18 +19,18 @@ Modern coding agents (Claude Code, GitHub Copilot, etc.) increasingly favour CLI
|
|
|
15
19
|
|
|
16
20
|
## Installation
|
|
17
21
|
|
|
18
|
-
### From
|
|
22
|
+
### From PyPI (recommended)
|
|
19
23
|
|
|
20
24
|
```bash
|
|
21
|
-
|
|
22
|
-
cd DrissionPage-MCP/DrissionPage-cli
|
|
23
|
-
pip install -e .
|
|
25
|
+
pip install drissionpage-cli
|
|
24
26
|
```
|
|
25
27
|
|
|
26
|
-
###
|
|
28
|
+
### From source (development)
|
|
27
29
|
|
|
28
30
|
```bash
|
|
29
|
-
|
|
31
|
+
git clone https://github.com/nicekate/DrissionPage-MCP.git
|
|
32
|
+
cd DrissionPage-MCP/DrissionPage-cli
|
|
33
|
+
pip install -e .
|
|
30
34
|
```
|
|
31
35
|
|
|
32
36
|
After installation the `drissionpage-cli` command is available globally:
|
|
@@ -44,6 +48,29 @@ drissionpage-cli install --skills
|
|
|
44
48
|
|
|
45
49
|
This copies the SKILL.md and reference guides into `.claude/skills/drissionpage-cli/` so that Claude Code (or any compatible agent) can discover them automatically.
|
|
46
50
|
|
|
51
|
+
**One-liner** — install the package and set up Claude Code skills in a single command:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
pip install drissionpage-cli && drissionpage-cli install --skills
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
#### What gets installed
|
|
58
|
+
|
|
59
|
+
The `install --skills` command copies the following into `.claude/skills/drissionpage-cli/`:
|
|
60
|
+
|
|
61
|
+
| File | Purpose |
|
|
62
|
+
|------|---------|
|
|
63
|
+
| `SKILL.md` | Skill definition & quick-start guide for the agent |
|
|
64
|
+
| `references/element-locators.md` | CSS, XPath, text, and attribute locator syntax |
|
|
65
|
+
| `references/running-code.md` | Custom DrissionPage Python code execution |
|
|
66
|
+
| `references/session-management.md` | Multiple concurrent browser sessions |
|
|
67
|
+
| `references/storage-state.md` | Cookies, localStorage, sessionStorage management |
|
|
68
|
+
| `references/screenshots-pdf.md` | Visual capture and PDF generation |
|
|
69
|
+
| `references/network-listening.md` | Network request monitoring |
|
|
70
|
+
| `references/dual-mode.md` | Browser + HTTP request mode switching |
|
|
71
|
+
|
|
72
|
+
Once installed, Claude Code automatically discovers the skill and can use `drissionpage-cli` commands for browser automation tasks.
|
|
73
|
+
|
|
47
74
|
## Quick Start
|
|
48
75
|
|
|
49
76
|
```bash
|
|
@@ -250,28 +277,29 @@ python3 -m pytest tests/ -v
|
|
|
250
277
|
|
|
251
278
|
```
|
|
252
279
|
DrissionPage-cli/
|
|
253
|
-
drissionpage_cli
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
280
|
+
drissionpage_cli/ # Main package
|
|
281
|
+
__init__.py # CLI entry point (59 commands)
|
|
282
|
+
skills/drissionpage-cli/ # Bundled skill files
|
|
283
|
+
SKILL.md
|
|
284
|
+
references/
|
|
285
|
+
element-locators.md
|
|
286
|
+
running-code.md
|
|
287
|
+
session-management.md
|
|
288
|
+
storage-state.md
|
|
289
|
+
screenshots-pdf.md
|
|
290
|
+
network-listening.md
|
|
291
|
+
dual-mode.md
|
|
292
|
+
pyproject.toml # Python packaging
|
|
293
|
+
requirements.txt # DrissionPage>=4.0.0
|
|
294
|
+
pytest.ini # Test configuration
|
|
257
295
|
README.md
|
|
258
296
|
LICENSE
|
|
259
297
|
scripts/
|
|
260
|
-
update.py
|
|
261
|
-
skills/drissionpage-cli/
|
|
262
|
-
SKILL.md # Agent skill definition
|
|
263
|
-
references/
|
|
264
|
-
element-locators.md # CSS, XPath, text, attribute locators
|
|
265
|
-
running-code.md # run-code for custom automation
|
|
266
|
-
session-management.md # Multiple browser sessions
|
|
267
|
-
storage-state.md # Cookies, localStorage, sessionStorage
|
|
268
|
-
screenshots-pdf.md # Visual capture
|
|
269
|
-
network-listening.md # Network monitoring
|
|
270
|
-
dual-mode.md # Browser + HTTP requests mode
|
|
298
|
+
update.py # Skill update script
|
|
271
299
|
tests/
|
|
272
|
-
conftest.py
|
|
273
|
-
test_unit.py
|
|
274
|
-
test_integration.py
|
|
300
|
+
conftest.py # Shared fixtures
|
|
301
|
+
test_unit.py # 92 unit tests (mocked, no browser)
|
|
302
|
+
test_integration.py # 30+ integration tests (real browser)
|
|
275
303
|
```
|
|
276
304
|
|
|
277
305
|
## Environment Variables
|
|
@@ -15,7 +15,7 @@ import time
|
|
|
15
15
|
import traceback
|
|
16
16
|
from pathlib import Path
|
|
17
17
|
|
|
18
|
-
__version__ = "0.1.
|
|
18
|
+
__version__ = "0.1.2"
|
|
19
19
|
|
|
20
20
|
# Session storage directory
|
|
21
21
|
CLI_DIR = Path(os.environ.get("DRISSIONPAGE_CLI_DIR", ".drissionpage-cli"))
|
|
@@ -108,7 +108,13 @@ def _get_page(session_name, create=False, options=None):
|
|
|
108
108
|
|
|
109
109
|
# Create new session
|
|
110
110
|
co = ChromiumOptions()
|
|
111
|
-
|
|
111
|
+
|
|
112
|
+
use_system_user_path = options and options.get("system_user_path")
|
|
113
|
+
if use_system_user_path:
|
|
114
|
+
# use_system_user_path is incompatible with auto_port (auto_port creates a temp profile)
|
|
115
|
+
co.use_system_user_path(True)
|
|
116
|
+
else:
|
|
117
|
+
co.auto_port() # pick a free port to avoid conflicts with stale browsers
|
|
112
118
|
|
|
113
119
|
if options:
|
|
114
120
|
if options.get("headless") is not None:
|
|
@@ -182,6 +188,32 @@ def _find_element(page, ref):
|
|
|
182
188
|
# Command handlers
|
|
183
189
|
# ---------------------------------------------------------------------------
|
|
184
190
|
|
|
191
|
+
_CONSOLE_CAPTURE_JS = """
|
|
192
|
+
if (!window.__dp_console_capture_installed) {
|
|
193
|
+
window.__dp_console_logs = window.__dp_console_logs || [];
|
|
194
|
+
['log', 'info', 'warn', 'error', 'debug'].forEach(function(t) {
|
|
195
|
+
var orig = console[t];
|
|
196
|
+
console[t] = function() {
|
|
197
|
+
var text = Array.prototype.slice.call(arguments).map(function(a) {
|
|
198
|
+
try { return (typeof a === 'object') ? JSON.stringify(a) : String(a); }
|
|
199
|
+
catch(e) { return String(a); }
|
|
200
|
+
}).join(' ');
|
|
201
|
+
window.__dp_console_logs.push({type: t === 'warn' ? 'warning' : t, text: text});
|
|
202
|
+
orig.apply(console, arguments);
|
|
203
|
+
};
|
|
204
|
+
});
|
|
205
|
+
window.__dp_console_capture_installed = true;
|
|
206
|
+
}
|
|
207
|
+
"""
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def _inject_console_capture(page):
|
|
211
|
+
"""Inject console capture script into the page if not already installed."""
|
|
212
|
+
try:
|
|
213
|
+
page.run_js(_CONSOLE_CAPTURE_JS)
|
|
214
|
+
except Exception:
|
|
215
|
+
pass
|
|
216
|
+
|
|
185
217
|
|
|
186
218
|
def cmd_open(args):
|
|
187
219
|
"""Open a browser, optionally navigate to a URL."""
|
|
@@ -190,6 +222,7 @@ def cmd_open(args):
|
|
|
190
222
|
"headless": not getattr(args, "headed", False),
|
|
191
223
|
"user_data_path": getattr(args, "profile", None),
|
|
192
224
|
"port": getattr(args, "port", None),
|
|
225
|
+
"system_user_path": getattr(args, "system_user_path", False),
|
|
193
226
|
}
|
|
194
227
|
page = _get_page(session, create=True, options=options)
|
|
195
228
|
|
|
@@ -197,6 +230,7 @@ def cmd_open(args):
|
|
|
197
230
|
if url:
|
|
198
231
|
page.get(url)
|
|
199
232
|
|
|
233
|
+
_inject_console_capture(page)
|
|
200
234
|
print(_format_snapshot(page))
|
|
201
235
|
|
|
202
236
|
|
|
@@ -205,6 +239,7 @@ def cmd_goto(args):
|
|
|
205
239
|
session = _get_session_name(args)
|
|
206
240
|
page = _get_page(session)
|
|
207
241
|
page.get(args.url)
|
|
242
|
+
_inject_console_capture(page)
|
|
208
243
|
print(_format_snapshot(page))
|
|
209
244
|
|
|
210
245
|
|
|
@@ -448,7 +483,13 @@ def cmd_pdf(args):
|
|
|
448
483
|
ensure_cli_dir()
|
|
449
484
|
filename = str(CLI_DIR / f"page-{timestamp}.pdf")
|
|
450
485
|
|
|
451
|
-
|
|
486
|
+
# Use CDP directly to avoid DrissionPage bug: open(..., 'wb', newline='\n')
|
|
487
|
+
# is invalid since binary mode doesn't accept a newline argument.
|
|
488
|
+
from base64 import b64decode
|
|
489
|
+
r = page._run_cdp('Page.printToPDF', transferMode='ReturnAsBase64', printBackground=True)
|
|
490
|
+
pdf_bytes = b64decode(r['data'])
|
|
491
|
+
with open(filename, 'wb') as f:
|
|
492
|
+
f.write(pdf_bytes)
|
|
452
493
|
print(f"PDF saved to {filename}")
|
|
453
494
|
|
|
454
495
|
|
|
@@ -529,7 +570,7 @@ def cmd_mousemove(args):
|
|
|
529
570
|
"""Move mouse to coordinates."""
|
|
530
571
|
session = _get_session_name(args)
|
|
531
572
|
page = _get_page(session)
|
|
532
|
-
page.actions.move_to(args.x, args.y)
|
|
573
|
+
page.actions.move_to((args.x, args.y))
|
|
533
574
|
print("Mouse moved to", args.x, args.y)
|
|
534
575
|
|
|
535
576
|
|
|
@@ -651,7 +692,7 @@ def cmd_cookie_list(args):
|
|
|
651
692
|
"""List cookies."""
|
|
652
693
|
session = _get_session_name(args)
|
|
653
694
|
page = _get_page(session)
|
|
654
|
-
cookies = page.cookies(
|
|
695
|
+
cookies = page.cookies(all_info=True)
|
|
655
696
|
domain = getattr(args, "domain", None)
|
|
656
697
|
if domain:
|
|
657
698
|
cookies = [c for c in cookies if domain in c.get("domain", "")]
|
|
@@ -663,7 +704,7 @@ def cmd_cookie_get(args):
|
|
|
663
704
|
"""Get a cookie by name."""
|
|
664
705
|
session = _get_session_name(args)
|
|
665
706
|
page = _get_page(session)
|
|
666
|
-
cookies = page.cookies(
|
|
707
|
+
cookies = page.cookies(all_info=True)
|
|
667
708
|
for c in cookies:
|
|
668
709
|
if c.get("name") == args.name:
|
|
669
710
|
print(json.dumps(c, indent=2, ensure_ascii=False))
|
|
@@ -813,6 +854,8 @@ def cmd_console(args):
|
|
|
813
854
|
"""List console messages."""
|
|
814
855
|
session = _get_session_name(args)
|
|
815
856
|
page = _get_page(session)
|
|
857
|
+
# Ensure the interceptor is installed (no-op if already installed)
|
|
858
|
+
_inject_console_capture(page)
|
|
816
859
|
result = page.run_js("""
|
|
817
860
|
return JSON.stringify(
|
|
818
861
|
(window.__dp_console_logs || []).map(e => ({
|
|
@@ -820,17 +863,17 @@ def cmd_console(args):
|
|
|
820
863
|
}))
|
|
821
864
|
)
|
|
822
865
|
""")
|
|
823
|
-
if result
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
866
|
+
logs = json.loads(result) if result else []
|
|
867
|
+
min_level = getattr(args, "level", None)
|
|
868
|
+
levels = ["error", "warning", "info", "debug"]
|
|
869
|
+
if min_level and min_level in levels:
|
|
870
|
+
allowed = set(levels[: levels.index(min_level) + 1])
|
|
871
|
+
logs = [l for l in logs if l.get("type", "info") in allowed]
|
|
872
|
+
if logs:
|
|
830
873
|
for log in logs:
|
|
831
874
|
print(f"[{log.get('type', 'info')}] {log.get('text', '')}")
|
|
832
875
|
else:
|
|
833
|
-
print("No console messages captured.
|
|
876
|
+
print("No console messages captured yet. Console interceptor is now active — any future console.log/warn/error calls will be recorded.")
|
|
834
877
|
|
|
835
878
|
|
|
836
879
|
def cmd_network(args):
|
|
@@ -961,7 +1004,7 @@ def cmd_state_save(args):
|
|
|
961
1004
|
ensure_cli_dir()
|
|
962
1005
|
filename = str(CLI_DIR / f"state-{timestamp}.json")
|
|
963
1006
|
|
|
964
|
-
cookies = page.cookies(
|
|
1007
|
+
cookies = page.cookies(all_info=True)
|
|
965
1008
|
local_storage = page.run_js(
|
|
966
1009
|
"return JSON.stringify(Object.entries(localStorage))"
|
|
967
1010
|
)
|
|
@@ -1069,6 +1112,8 @@ def build_parser():
|
|
|
1069
1112
|
p.add_argument("url", nargs="?", help="URL to navigate to")
|
|
1070
1113
|
p.add_argument("--headed", action="store_true", help="Run in headed mode")
|
|
1071
1114
|
p.add_argument("--profile", help="User data directory path")
|
|
1115
|
+
p.add_argument("--system-user-path", action="store_true", dest="system_user_path",
|
|
1116
|
+
help="Use system default Chrome profile (inherits login sessions)")
|
|
1072
1117
|
p.add_argument("--port", type=int, help="CDP debugging port")
|
|
1073
1118
|
p.set_defaults(func=cmd_open)
|
|
1074
1119
|
|
{drissionpage_cli-0.1.0 → drissionpage_cli-0.1.2}/drissionpage_cli/skills/drissionpage-cli/SKILL.md
RENAMED
|
@@ -146,7 +146,9 @@ drissionpage-cli run-code --filename=script.py
|
|
|
146
146
|
```bash
|
|
147
147
|
# Run in headed mode (browser window visible)
|
|
148
148
|
drissionpage-cli open --headed
|
|
149
|
-
# Use
|
|
149
|
+
# Use system default Chrome profile (inherits all login sessions)
|
|
150
|
+
drissionpage-cli open --system-user-path
|
|
151
|
+
# Use a specific user profile directory
|
|
150
152
|
drissionpage-cli open --profile=/path/to/profile
|
|
151
153
|
# Use specific CDP port
|
|
152
154
|
drissionpage-cli open --port=9222
|
|
@@ -90,7 +90,10 @@ drissionpage-cli -s=variant-b screenshot
|
|
|
90
90
|
### Persistent Profile
|
|
91
91
|
|
|
92
92
|
```bash
|
|
93
|
-
# Use
|
|
93
|
+
# Use system default Chrome profile (inherits all login sessions)
|
|
94
|
+
drissionpage-cli open --system-user-path
|
|
95
|
+
|
|
96
|
+
# Use a specific profile directory
|
|
94
97
|
drissionpage-cli open https://example.com --profile=/path/to/profile
|
|
95
98
|
|
|
96
99
|
# Specific CDP port
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: drissionpage-cli
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
4
4
|
Summary: DrissionPage CLI - Token-efficient browser automation for coding agents
|
|
5
5
|
Author: DrissionPage-MCP Contributors
|
|
6
6
|
License: Apache-2.0
|
|
@@ -25,11 +25,15 @@ Requires-Dist: DrissionPage>=4.0.0
|
|
|
25
25
|
Dynamic: license-file
|
|
26
26
|
|
|
27
27
|
# DrissionPage-cli
|
|
28
|
-
|
|
29
28
|
Token-efficient browser automation CLI for coding agents, powered by [DrissionPage](https://DrissionPage.cn).
|
|
30
29
|
|
|
31
30
|
Mirrors the architecture of [playwright-cli](https://github.com/microsoft/playwright-cli) but uses DrissionPage as the backend — pure Python, no Node.js required.
|
|
32
31
|
|
|
32
|
+
## Why use drissionpage-cli
|
|
33
|
+
|
|
34
|
+
If you know, you know. If you don't, go use playwright-cli.
|
|
35
|
+
|
|
36
|
+
|
|
33
37
|
## Why CLI + Skills over MCP
|
|
34
38
|
|
|
35
39
|
Modern coding agents (Claude Code, GitHub Copilot, etc.) increasingly favour CLI-based workflows exposed as **SKILLs** over MCP because CLI invocations are more token-efficient: they avoid loading large tool schemas and verbose accessibility trees into the model context. This makes CLI + SKILLs better suited for high-throughput agents that must balance browser automation with large codebases within limited context windows.
|
|
@@ -41,18 +45,18 @@ Modern coding agents (Claude Code, GitHub Copilot, etc.) increasingly favour CLI
|
|
|
41
45
|
|
|
42
46
|
## Installation
|
|
43
47
|
|
|
44
|
-
### From
|
|
48
|
+
### From PyPI (recommended)
|
|
45
49
|
|
|
46
50
|
```bash
|
|
47
|
-
|
|
48
|
-
cd DrissionPage-MCP/DrissionPage-cli
|
|
49
|
-
pip install -e .
|
|
51
|
+
pip install drissionpage-cli
|
|
50
52
|
```
|
|
51
53
|
|
|
52
|
-
###
|
|
54
|
+
### From source (development)
|
|
53
55
|
|
|
54
56
|
```bash
|
|
55
|
-
|
|
57
|
+
git clone https://github.com/nicekate/DrissionPage-MCP.git
|
|
58
|
+
cd DrissionPage-MCP/DrissionPage-cli
|
|
59
|
+
pip install -e .
|
|
56
60
|
```
|
|
57
61
|
|
|
58
62
|
After installation the `drissionpage-cli` command is available globally:
|
|
@@ -70,6 +74,29 @@ drissionpage-cli install --skills
|
|
|
70
74
|
|
|
71
75
|
This copies the SKILL.md and reference guides into `.claude/skills/drissionpage-cli/` so that Claude Code (or any compatible agent) can discover them automatically.
|
|
72
76
|
|
|
77
|
+
**One-liner** — install the package and set up Claude Code skills in a single command:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
pip install drissionpage-cli && drissionpage-cli install --skills
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
#### What gets installed
|
|
84
|
+
|
|
85
|
+
The `install --skills` command copies the following into `.claude/skills/drissionpage-cli/`:
|
|
86
|
+
|
|
87
|
+
| File | Purpose |
|
|
88
|
+
|------|---------|
|
|
89
|
+
| `SKILL.md` | Skill definition & quick-start guide for the agent |
|
|
90
|
+
| `references/element-locators.md` | CSS, XPath, text, and attribute locator syntax |
|
|
91
|
+
| `references/running-code.md` | Custom DrissionPage Python code execution |
|
|
92
|
+
| `references/session-management.md` | Multiple concurrent browser sessions |
|
|
93
|
+
| `references/storage-state.md` | Cookies, localStorage, sessionStorage management |
|
|
94
|
+
| `references/screenshots-pdf.md` | Visual capture and PDF generation |
|
|
95
|
+
| `references/network-listening.md` | Network request monitoring |
|
|
96
|
+
| `references/dual-mode.md` | Browser + HTTP request mode switching |
|
|
97
|
+
|
|
98
|
+
Once installed, Claude Code automatically discovers the skill and can use `drissionpage-cli` commands for browser automation tasks.
|
|
99
|
+
|
|
73
100
|
## Quick Start
|
|
74
101
|
|
|
75
102
|
```bash
|
|
@@ -276,28 +303,29 @@ python3 -m pytest tests/ -v
|
|
|
276
303
|
|
|
277
304
|
```
|
|
278
305
|
DrissionPage-cli/
|
|
279
|
-
drissionpage_cli
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
306
|
+
drissionpage_cli/ # Main package
|
|
307
|
+
__init__.py # CLI entry point (59 commands)
|
|
308
|
+
skills/drissionpage-cli/ # Bundled skill files
|
|
309
|
+
SKILL.md
|
|
310
|
+
references/
|
|
311
|
+
element-locators.md
|
|
312
|
+
running-code.md
|
|
313
|
+
session-management.md
|
|
314
|
+
storage-state.md
|
|
315
|
+
screenshots-pdf.md
|
|
316
|
+
network-listening.md
|
|
317
|
+
dual-mode.md
|
|
318
|
+
pyproject.toml # Python packaging
|
|
319
|
+
requirements.txt # DrissionPage>=4.0.0
|
|
320
|
+
pytest.ini # Test configuration
|
|
283
321
|
README.md
|
|
284
322
|
LICENSE
|
|
285
323
|
scripts/
|
|
286
|
-
update.py
|
|
287
|
-
skills/drissionpage-cli/
|
|
288
|
-
SKILL.md # Agent skill definition
|
|
289
|
-
references/
|
|
290
|
-
element-locators.md # CSS, XPath, text, attribute locators
|
|
291
|
-
running-code.md # run-code for custom automation
|
|
292
|
-
session-management.md # Multiple browser sessions
|
|
293
|
-
storage-state.md # Cookies, localStorage, sessionStorage
|
|
294
|
-
screenshots-pdf.md # Visual capture
|
|
295
|
-
network-listening.md # Network monitoring
|
|
296
|
-
dual-mode.md # Browser + HTTP requests mode
|
|
324
|
+
update.py # Skill update script
|
|
297
325
|
tests/
|
|
298
|
-
conftest.py
|
|
299
|
-
test_unit.py
|
|
300
|
-
test_integration.py
|
|
326
|
+
conftest.py # Shared fixtures
|
|
327
|
+
test_unit.py # 92 unit tests (mocked, no browser)
|
|
328
|
+
test_integration.py # 30+ integration tests (real browser)
|
|
301
329
|
```
|
|
302
330
|
|
|
303
331
|
## Environment Variables
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "drissionpage-cli"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.2"
|
|
8
8
|
description = "DrissionPage CLI - Token-efficient browser automation for coding agents"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = {text = "Apache-2.0"}
|
|
@@ -26,7 +26,7 @@ import drissionpage_cli as cli
|
|
|
26
26
|
|
|
27
27
|
class TestVersionAndHelp:
|
|
28
28
|
def test_version_string(self):
|
|
29
|
-
assert cli.__version__ == "0.1.
|
|
29
|
+
assert cli.__version__ == "0.1.2"
|
|
30
30
|
|
|
31
31
|
def test_build_parser(self):
|
|
32
32
|
parser = cli.build_parser()
|
|
@@ -292,6 +292,17 @@ class TestVersionAndHelp:
|
|
|
292
292
|
assert args.command == "open"
|
|
293
293
|
assert args.profile == "/tmp/profile"
|
|
294
294
|
|
|
295
|
+
def test_parse_open_with_system_user_path(self):
|
|
296
|
+
parser = cli.build_parser()
|
|
297
|
+
args = parser.parse_args(["open", "--system-user-path"])
|
|
298
|
+
assert args.command == "open"
|
|
299
|
+
assert args.system_user_path is True
|
|
300
|
+
|
|
301
|
+
def test_parse_open_system_user_path_default_false(self):
|
|
302
|
+
parser = cli.build_parser()
|
|
303
|
+
args = parser.parse_args(["open"])
|
|
304
|
+
assert args.system_user_path is False
|
|
305
|
+
|
|
295
306
|
def test_parse_console_command(self):
|
|
296
307
|
parser = cli.build_parser()
|
|
297
308
|
args = parser.parse_args(["console", "warning"])
|
|
@@ -578,6 +589,57 @@ class TestStateSaveLoad:
|
|
|
578
589
|
assert any("sessionStorage.setItem" in str(call) for call in mock_page.run_js.call_args_list)
|
|
579
590
|
|
|
580
591
|
|
|
592
|
+
# ---------------------------------------------------------------------------
|
|
593
|
+
# _get_page options (mocked ChromiumOptions / ChromiumPage)
|
|
594
|
+
# ---------------------------------------------------------------------------
|
|
595
|
+
|
|
596
|
+
|
|
597
|
+
class TestGetPageOptions:
|
|
598
|
+
"""Test that _get_page passes options correctly to ChromiumOptions."""
|
|
599
|
+
|
|
600
|
+
def _make_mock_co(self):
|
|
601
|
+
return MagicMock()
|
|
602
|
+
|
|
603
|
+
def _run_get_page(self, options, tmp_path, mock_co, mock_page):
|
|
604
|
+
sessions_file = tmp_path / "sessions.json"
|
|
605
|
+
cli_dir_path = tmp_path / ".drissionpage-cli"
|
|
606
|
+
cli_dir_path.mkdir()
|
|
607
|
+
|
|
608
|
+
with patch.object(cli, "SESSIONS_FILE", sessions_file), \
|
|
609
|
+
patch.object(cli, "CLI_DIR", cli_dir_path), \
|
|
610
|
+
patch("DrissionPage.ChromiumOptions", return_value=mock_co), \
|
|
611
|
+
patch("DrissionPage.ChromiumPage", return_value=mock_page):
|
|
612
|
+
mock_page.address = "127.0.0.1:9333"
|
|
613
|
+
mock_page.process_id = 999
|
|
614
|
+
cli._get_page("default", create=True, options=options)
|
|
615
|
+
|
|
616
|
+
def test_system_user_path_calls_use_system_user_path(self, tmp_path):
|
|
617
|
+
mock_co = self._make_mock_co()
|
|
618
|
+
mock_page = MagicMock()
|
|
619
|
+
self._run_get_page({"system_user_path": True}, tmp_path, mock_co, mock_page)
|
|
620
|
+
mock_co.use_system_user_path.assert_called_once_with(True)
|
|
621
|
+
|
|
622
|
+
def test_system_user_path_skips_auto_port(self, tmp_path):
|
|
623
|
+
mock_co = self._make_mock_co()
|
|
624
|
+
mock_page = MagicMock()
|
|
625
|
+
self._run_get_page({"system_user_path": True}, tmp_path, mock_co, mock_page)
|
|
626
|
+
mock_co.auto_port.assert_not_called()
|
|
627
|
+
|
|
628
|
+
def test_no_system_user_path_calls_auto_port(self, tmp_path):
|
|
629
|
+
mock_co = self._make_mock_co()
|
|
630
|
+
mock_page = MagicMock()
|
|
631
|
+
self._run_get_page({"system_user_path": False}, tmp_path, mock_co, mock_page)
|
|
632
|
+
mock_co.auto_port.assert_called_once()
|
|
633
|
+
mock_co.use_system_user_path.assert_not_called()
|
|
634
|
+
|
|
635
|
+
def test_system_user_path_with_headed(self, tmp_path):
|
|
636
|
+
mock_co = self._make_mock_co()
|
|
637
|
+
mock_page = MagicMock()
|
|
638
|
+
self._run_get_page({"system_user_path": True, "headless": False}, tmp_path, mock_co, mock_page)
|
|
639
|
+
mock_co.use_system_user_path.assert_called_once_with(True)
|
|
640
|
+
mock_co.headless.assert_called_once_with(False)
|
|
641
|
+
|
|
642
|
+
|
|
581
643
|
# ---------------------------------------------------------------------------
|
|
582
644
|
# Command handlers (mocked browser)
|
|
583
645
|
# ---------------------------------------------------------------------------
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{drissionpage_cli-0.1.0 → drissionpage_cli-0.1.2}/drissionpage_cli.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{drissionpage_cli-0.1.0 → drissionpage_cli-0.1.2}/drissionpage_cli.egg-info/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|