chromectl 0.1.0__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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Enes Bayram
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,3 @@
1
+ include LICENSE
2
+ include README.md
3
+ include chromectl/protocol.json
@@ -0,0 +1,248 @@
1
+ Metadata-Version: 2.4
2
+ Name: chromectl
3
+ Version: 0.1.0
4
+ Summary: A friendly CLI for driving Chrome over the DevTools Protocol — for agents and humans.
5
+ Author: Enes Bayram
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/0xenesbayram/chromectl
8
+ Project-URL: Repository, https://github.com/0xenesbayram/chromectl
9
+ Project-URL: Issues, https://github.com/0xenesbayram/chromectl/issues
10
+ Keywords: chrome,chromium,cdp,devtools,automation,agent,cli,playwright,lighthouse,headless
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Internet :: WWW/HTTP :: Browsers
21
+ Classifier: Topic :: Software Development :: Testing
22
+ Classifier: Topic :: Software Development :: Quality Assurance
23
+ Classifier: Topic :: Utilities
24
+ Requires-Python: >=3.10
25
+ Description-Content-Type: text/markdown
26
+ License-File: LICENSE
27
+ Requires-Dist: websocket-client>=1.7
28
+ Requires-Dist: rich>=13
29
+ Requires-Dist: playwright>=1.40
30
+ Requires-Dist: readability-lxml>=0.8
31
+ Requires-Dist: markdownify>=0.11
32
+ Requires-Dist: lxml_html_clean>=0.1
33
+ Provides-Extra: dev
34
+ Requires-Dist: build; extra == "dev"
35
+ Requires-Dist: twine; extra == "dev"
36
+ Requires-Dist: pipx; extra == "dev"
37
+ Dynamic: license-file
38
+
39
+ # chromectl — a friendly CLI for the Chrome DevTools Protocol
40
+
41
+ Drive a Chrome/Chromium instance from the shell over its remote debugging port.
42
+ Everything is the Chrome DevTools Protocol (CDP) under the hood; this wraps it in
43
+ ergonomic subcommands with nice output. Not just network — JS execution, console
44
+ logs/errors, screenshots, PDFs, cookies, SEO audits, page-reading, form flows,
45
+ Core Web Vitals / Lighthouse, and a raw escape hatch.
46
+
47
+ ## Install
48
+
49
+ ```bash
50
+ pipx install chromectl # from PyPI
51
+ pipx upgrade chromectl # pull later releases
52
+ npm i -g lighthouse # optional — only for `lighthouse`
53
+ ```
54
+
55
+ Bleeding edge, straight from the repo:
56
+
57
+ ```bash
58
+ pipx install git+https://github.com/0xenesbayram/chromectl.git
59
+ # or, from a local clone: pipx install .
60
+ ```
61
+
62
+ pipx puts `chromectl` on your PATH in an isolated env and pulls all Python deps
63
+ (`websocket-client`, `rich`, `playwright`, `readability-lxml`, `markdownify`).
64
+ **No `playwright install` needed** — the interaction commands *attach* to your Chrome
65
+ over CDP rather than launching their own browser. Playwright and the read/markdown
66
+ libs are imported lazily, so the core commands stay fast.
67
+
68
+ ## 1. Launch Chrome
69
+
70
+ ```bash
71
+ chromectl start # headless, port 9222, PERSISTENT profile
72
+ chromectl start --headful --port 9223 # visible window, custom port
73
+ chromectl start --profile ~/.cache/chromectl # custom profile dir
74
+ chromectl start --ephemeral # throwaway profile in /tmp (no persistence)
75
+ chromectl start --copy-profile # copy your REAL Chrome profile (logins!) then launch
76
+ chromectl start --from-profile /path/to/profile # copy from a specific profile dir
77
+ ```
78
+
79
+ `--copy-profile` auto-detects your default Chrome user-data-dir (per-OS), copies it into
80
+ `--profile` (skipping caches), and launches from the copy — so you debug **with your real
81
+ logins** without touching/using the original profile. Close Chrome using that profile first
82
+ so its files aren't mid-write. Security: the copy holds your live cookies/sessions — anyone
83
+ who reaches the debug port can act as you, so keep it local and delete it when done.
84
+
85
+ ### Multiple instances
86
+ Run and manage several browsers at once, each on its own port, addressed by name:
87
+
88
+ ```bash
89
+ chromectl start --name work # instance on 9222
90
+ chromectl start --name scratch --auto-port # a second, on the next free port
91
+ chromectl instances # list them + up/down status (--json, --prune)
92
+
93
+ chromectl -i scratch open https://example.com # target by name (or --port 9223)
94
+ chromectl -i work read --json
95
+
96
+ chromectl stop scratch # stop one by name/port
97
+ chromectl stop --all # stop every managed instance
98
+ ```
99
+
100
+ `-i NAME` (or `--port N`) selects which browser every command talks to. The registry lives
101
+ at `~/.chromectl/instances.json`.
102
+
103
+ Notes:
104
+ - **Profiles persist by default.** Each instance gets a stable dir at
105
+ `~/.chromectl/profiles/<name>` that's **reused every time you start that name**, so
106
+ cookies/logins survive restarts. Use `--profile PATH` for a custom location,
107
+ `--ephemeral` for a throwaway `/tmp` profile, or `stop <name> --purge` to delete it.
108
+ - A **non-default profile is mandatory** since Chrome 136 — the real default profile
109
+ refuses the debug port (anti-cookie-theft). `start`'s profile is non-default; to reuse
110
+ your logins, copy your real one first: `cp -r ~/.config/google-chrome /tmp/prof` then
111
+ `chromectl start --profile /tmp/prof`.
112
+ - `start` sets `--remote-allow-origins=*` so clients (incl. Playwright) can connect.
113
+ - Anyone who can reach the port has **full, unauthenticated control** of that browser
114
+ (read cookies/sessions, run JS, read traffic). Keep it on localhost; never forward it.
115
+
116
+ ## 2. Use it
117
+
118
+ ```bash
119
+ chromectl list # open tabs/targets
120
+ chromectl version # browser + protocol info
121
+ chromectl open https://example.com # open a tab
122
+ chromectl close example # close a tab (by url/title substring or id-prefix)
123
+
124
+ chromectl goto example https://news.ycombinator.com # navigate
125
+ chromectl eval example "document.title" # run JS, get the value back
126
+ chromectl eval example "({t: document.title, links: document.links.length})"
127
+ chromectl html example --out page.html # dump HTML
128
+ chromectl text example # visible text
129
+ chromectl cookies example # cookie table (--json for raw)
130
+ chromectl screenshot example --full --out shot.png # full-page screenshot
131
+ chromectl pdf example --out page.pdf # print to PDF
132
+
133
+ chromectl console example # tail console.* + JS errors (Ctrl-C)
134
+ chromectl watch example # live one-line-per-request network tail
135
+
136
+ chromectl capture https://github.com --print 3 # Burp-style full req/resp capture
137
+ chromectl capture https://api.github.com/ --type xhr --har out.har # filter + HAR export
138
+ chromectl capture --attach example --reload # capture an existing tab from reload
139
+
140
+ chromectl seo https://example.com # on-page SEO audit (open+audit+close)
141
+ chromectl seo example # audit an already-loaded tab
142
+
143
+ # --- run a whole flow in ONE process (script/batch) ---
144
+ chromectl run steps.txt # one command per line (# comments ok)
145
+ chromectl run --step "open https://site/login" \
146
+ --step "wait --selector #user" \
147
+ --step "fill-form --set #user=ada --set #pass=pw --submit #go" \
148
+ --step "wait --url /dashboard" \
149
+ --step "read --json"
150
+ # opened tab auto-becomes the target for later steps; one connection; state persists; --keep-going to continue on error
151
+
152
+ # --- read & extract (turn pages into data) ---
153
+ chromectl read example # main content as clean Markdown
154
+ chromectl read example --json # {url,title,markdown,chars}
155
+ chromectl extract example --field "title=h1" --field "prices=.price[]" --field "img=img@src"
156
+ chromectl links example --external --json # list links (filter internal/external)
157
+
158
+ # --- reliable flows ---
159
+ chromectl wait example --selector "#results" --timeout 8000 # wait until it's visible
160
+ chromectl wait example --network-idle # or: --text "Done" / --url "/checkout" / --gone
161
+ chromectl fill-form login --set "#user=ada" --set "#pass=secret" --submit "#go"
162
+
163
+ # Most read-only commands accept --json for scripting/agents:
164
+ chromectl list --json ; chromectl cookies example --json ; chromectl seo example --json
165
+
166
+ # --- performance (Tier 3) ---
167
+ chromectl perf https://example.com # Core Web Vitals (LCP/CLS/INP/FCP/TTFB)
168
+ chromectl perf https://example.com --out trace.json # + raw trace (DevTools ▸ Performance ▸ Load)
169
+ chromectl perf --attach example --reload # measure an existing tab
170
+ chromectl lighthouse https://example.com --preset desktop # full Lighthouse audit (needs the CLI)
171
+ chromectl lighthouse https://example.com --categories performance,seo --out report.json
172
+
173
+ # --- robust interaction via Playwright-over-CDP (Tier 2) ---
174
+ chromectl snapshot example # list interactive elements + save refs
175
+ chromectl click example --role button --name "Sign in" # click by ARIA role + name
176
+ chromectl click example --ref 3 # click element #3 from last snapshot
177
+ chromectl click example --text "Add to cart" # click by visible text
178
+ chromectl fill example "ada@x.com" --selector "#email" --enter # fill + submit (auto-waits)
179
+ chromectl hover example --selector ".menu" # hover (reveals submenus)
180
+
181
+ # --- interaction / emulation (Tier 1) ---
182
+ chromectl resize example 390 844 --mobile --shot m.png # viewport + full-page screenshot
183
+ chromectl emulate example --color dark --shot dark.png # dark mode
184
+ chromectl emulate example --geo 48.85,2.35 --throttle slow-3g --hold # geo + network (held)
185
+ chromectl type example "hello" --selector "#search" --enter # type into a field
186
+ chromectl press example Enter # press key(s): Enter/Tab/ArrowDown/a…
187
+ chromectl upload example ./photo.png --selector "#file" # set a file <input>
188
+ chromectl dialog example --accept --text "Ada" # auto-answer alert/confirm/prompt
189
+ chromectl heap example --out heap.heapsnapshot # V8 heap snapshot (DevTools ▸ Memory)
190
+
191
+ chromectl raw browser Browser.getVersion # raw CDP command (browser target)
192
+ chromectl raw example Runtime.evaluate '{"expression":"1+1","returnByValue":true}'
193
+ chromectl proto Network # protocol lookup: a domain…
194
+ chromectl proto Network.getResponseBody # …a command's params/returns
195
+ chromectl repl example # interactive CDP prompt
196
+ ```
197
+
198
+ ### Target selection
199
+ Anywhere a command takes a target you can pass:
200
+ - an **id-prefix** (`B1B0`), a **url/title substring** (`example`, `github`),
201
+ - `browser` for the browser-level target (for `raw`/`repl`),
202
+ - or **nothing** to use the first open page.
203
+
204
+ ### Emulation caveat
205
+ CDP overrides (`emulate`/`resize` viewport, geo, throttle, color-scheme, UA) live on
206
+ the **CDP connection** and revert when it closes. Since each `chromectl` command connects,
207
+ acts, and disconnects, use `--shot` to capture in the same session, or `--hold` to keep
208
+ the connection open (Ctrl-C to release) so the override persists while you do other work.
209
+
210
+ ### Interaction (Tier 2) — how it works
211
+ `snapshot`/`click`/`fill`/`hover` use **Playwright attached to your Chrome over CDP**
212
+ (`connect_over_cdp`) — no separate browser is launched. You get Playwright's
213
+ auto-waiting and actionability checks (waits for the element to exist, be visible, and
214
+ be stable before acting) instead of hand-rolled timing. `snapshot` writes `.cdp-snap.json`
215
+ so `--ref N` works in a later, separate command (the stateless equivalent of the MCP's
216
+ element uids). Locate an element by any of: `--ref`, `--selector`, `--text`, or
217
+ `--role`+`--name`.
218
+
219
+ ### Handy options
220
+ - `--host` / `--port` (or env `CDP_HOST` / `CDP_PORT`) — default `localhost:9222`.
221
+ - `capture`: `--print N`, `--out FILE`, `--har FILE`, `--type TYPE`,
222
+ `--no-bodies`, `--bodycap N`, `--max SECONDS`, `--quiet SECONDS`,
223
+ `--attach TARGET`, `--reload`.
224
+
225
+ ## How it works (the workflow)
226
+
227
+ `HTTP /json/version` → open ONE WebSocket to the browser (or a per-tab socket) →
228
+ send CDP commands (`{id, method, params}`) and receive replies + unsolicited
229
+ events → for capture: `Network.enable` **before** navigating, correlate events by
230
+ `requestId`, fetch each body on `loadingFinished` (before Chrome evicts it), merge
231
+ the `*ExtraInfo` events for the real cookies/headers, and reconstruct raw HTTP.
232
+
233
+ A background thread reads frames into a queue so `call()` (request/response) and
234
+ the capture/console/watch loops (event streams) share one connection cleanly.
235
+
236
+ **Gotcha baked in:** `websocket-client` sends an `Origin` header by default, which
237
+ modern Chrome rejects on the debug port. `chromectl` sets `suppress_origin=True` so
238
+ connections are accepted without relaunching Chrome.
239
+
240
+ ## Layout
241
+ - `chromectl/cli.py` — the CLI.
242
+ - `chromectl/protocol.json` — bundled CDP schema used by `chromectl proto`/`cheat` (falls back to live).
243
+ - `pyproject.toml` — packaging; `chromectl` console entry point.
244
+ - `AGENTS.md` — the agent-facing interface reference (auto-read by coding agents).
245
+
246
+ ## For agents
247
+ Read `AGENTS.md` (or run `chromectl cheat --json` once) for the full command surface —
248
+ no need to call `--help` per command.
@@ -0,0 +1,210 @@
1
+ # chromectl — a friendly CLI for the Chrome DevTools Protocol
2
+
3
+ Drive a Chrome/Chromium instance from the shell over its remote debugging port.
4
+ Everything is the Chrome DevTools Protocol (CDP) under the hood; this wraps it in
5
+ ergonomic subcommands with nice output. Not just network — JS execution, console
6
+ logs/errors, screenshots, PDFs, cookies, SEO audits, page-reading, form flows,
7
+ Core Web Vitals / Lighthouse, and a raw escape hatch.
8
+
9
+ ## Install
10
+
11
+ ```bash
12
+ pipx install chromectl # from PyPI
13
+ pipx upgrade chromectl # pull later releases
14
+ npm i -g lighthouse # optional — only for `lighthouse`
15
+ ```
16
+
17
+ Bleeding edge, straight from the repo:
18
+
19
+ ```bash
20
+ pipx install git+https://github.com/0xenesbayram/chromectl.git
21
+ # or, from a local clone: pipx install .
22
+ ```
23
+
24
+ pipx puts `chromectl` on your PATH in an isolated env and pulls all Python deps
25
+ (`websocket-client`, `rich`, `playwright`, `readability-lxml`, `markdownify`).
26
+ **No `playwright install` needed** — the interaction commands *attach* to your Chrome
27
+ over CDP rather than launching their own browser. Playwright and the read/markdown
28
+ libs are imported lazily, so the core commands stay fast.
29
+
30
+ ## 1. Launch Chrome
31
+
32
+ ```bash
33
+ chromectl start # headless, port 9222, PERSISTENT profile
34
+ chromectl start --headful --port 9223 # visible window, custom port
35
+ chromectl start --profile ~/.cache/chromectl # custom profile dir
36
+ chromectl start --ephemeral # throwaway profile in /tmp (no persistence)
37
+ chromectl start --copy-profile # copy your REAL Chrome profile (logins!) then launch
38
+ chromectl start --from-profile /path/to/profile # copy from a specific profile dir
39
+ ```
40
+
41
+ `--copy-profile` auto-detects your default Chrome user-data-dir (per-OS), copies it into
42
+ `--profile` (skipping caches), and launches from the copy — so you debug **with your real
43
+ logins** without touching/using the original profile. Close Chrome using that profile first
44
+ so its files aren't mid-write. Security: the copy holds your live cookies/sessions — anyone
45
+ who reaches the debug port can act as you, so keep it local and delete it when done.
46
+
47
+ ### Multiple instances
48
+ Run and manage several browsers at once, each on its own port, addressed by name:
49
+
50
+ ```bash
51
+ chromectl start --name work # instance on 9222
52
+ chromectl start --name scratch --auto-port # a second, on the next free port
53
+ chromectl instances # list them + up/down status (--json, --prune)
54
+
55
+ chromectl -i scratch open https://example.com # target by name (or --port 9223)
56
+ chromectl -i work read --json
57
+
58
+ chromectl stop scratch # stop one by name/port
59
+ chromectl stop --all # stop every managed instance
60
+ ```
61
+
62
+ `-i NAME` (or `--port N`) selects which browser every command talks to. The registry lives
63
+ at `~/.chromectl/instances.json`.
64
+
65
+ Notes:
66
+ - **Profiles persist by default.** Each instance gets a stable dir at
67
+ `~/.chromectl/profiles/<name>` that's **reused every time you start that name**, so
68
+ cookies/logins survive restarts. Use `--profile PATH` for a custom location,
69
+ `--ephemeral` for a throwaway `/tmp` profile, or `stop <name> --purge` to delete it.
70
+ - A **non-default profile is mandatory** since Chrome 136 — the real default profile
71
+ refuses the debug port (anti-cookie-theft). `start`'s profile is non-default; to reuse
72
+ your logins, copy your real one first: `cp -r ~/.config/google-chrome /tmp/prof` then
73
+ `chromectl start --profile /tmp/prof`.
74
+ - `start` sets `--remote-allow-origins=*` so clients (incl. Playwright) can connect.
75
+ - Anyone who can reach the port has **full, unauthenticated control** of that browser
76
+ (read cookies/sessions, run JS, read traffic). Keep it on localhost; never forward it.
77
+
78
+ ## 2. Use it
79
+
80
+ ```bash
81
+ chromectl list # open tabs/targets
82
+ chromectl version # browser + protocol info
83
+ chromectl open https://example.com # open a tab
84
+ chromectl close example # close a tab (by url/title substring or id-prefix)
85
+
86
+ chromectl goto example https://news.ycombinator.com # navigate
87
+ chromectl eval example "document.title" # run JS, get the value back
88
+ chromectl eval example "({t: document.title, links: document.links.length})"
89
+ chromectl html example --out page.html # dump HTML
90
+ chromectl text example # visible text
91
+ chromectl cookies example # cookie table (--json for raw)
92
+ chromectl screenshot example --full --out shot.png # full-page screenshot
93
+ chromectl pdf example --out page.pdf # print to PDF
94
+
95
+ chromectl console example # tail console.* + JS errors (Ctrl-C)
96
+ chromectl watch example # live one-line-per-request network tail
97
+
98
+ chromectl capture https://github.com --print 3 # Burp-style full req/resp capture
99
+ chromectl capture https://api.github.com/ --type xhr --har out.har # filter + HAR export
100
+ chromectl capture --attach example --reload # capture an existing tab from reload
101
+
102
+ chromectl seo https://example.com # on-page SEO audit (open+audit+close)
103
+ chromectl seo example # audit an already-loaded tab
104
+
105
+ # --- run a whole flow in ONE process (script/batch) ---
106
+ chromectl run steps.txt # one command per line (# comments ok)
107
+ chromectl run --step "open https://site/login" \
108
+ --step "wait --selector #user" \
109
+ --step "fill-form --set #user=ada --set #pass=pw --submit #go" \
110
+ --step "wait --url /dashboard" \
111
+ --step "read --json"
112
+ # opened tab auto-becomes the target for later steps; one connection; state persists; --keep-going to continue on error
113
+
114
+ # --- read & extract (turn pages into data) ---
115
+ chromectl read example # main content as clean Markdown
116
+ chromectl read example --json # {url,title,markdown,chars}
117
+ chromectl extract example --field "title=h1" --field "prices=.price[]" --field "img=img@src"
118
+ chromectl links example --external --json # list links (filter internal/external)
119
+
120
+ # --- reliable flows ---
121
+ chromectl wait example --selector "#results" --timeout 8000 # wait until it's visible
122
+ chromectl wait example --network-idle # or: --text "Done" / --url "/checkout" / --gone
123
+ chromectl fill-form login --set "#user=ada" --set "#pass=secret" --submit "#go"
124
+
125
+ # Most read-only commands accept --json for scripting/agents:
126
+ chromectl list --json ; chromectl cookies example --json ; chromectl seo example --json
127
+
128
+ # --- performance (Tier 3) ---
129
+ chromectl perf https://example.com # Core Web Vitals (LCP/CLS/INP/FCP/TTFB)
130
+ chromectl perf https://example.com --out trace.json # + raw trace (DevTools ▸ Performance ▸ Load)
131
+ chromectl perf --attach example --reload # measure an existing tab
132
+ chromectl lighthouse https://example.com --preset desktop # full Lighthouse audit (needs the CLI)
133
+ chromectl lighthouse https://example.com --categories performance,seo --out report.json
134
+
135
+ # --- robust interaction via Playwright-over-CDP (Tier 2) ---
136
+ chromectl snapshot example # list interactive elements + save refs
137
+ chromectl click example --role button --name "Sign in" # click by ARIA role + name
138
+ chromectl click example --ref 3 # click element #3 from last snapshot
139
+ chromectl click example --text "Add to cart" # click by visible text
140
+ chromectl fill example "ada@x.com" --selector "#email" --enter # fill + submit (auto-waits)
141
+ chromectl hover example --selector ".menu" # hover (reveals submenus)
142
+
143
+ # --- interaction / emulation (Tier 1) ---
144
+ chromectl resize example 390 844 --mobile --shot m.png # viewport + full-page screenshot
145
+ chromectl emulate example --color dark --shot dark.png # dark mode
146
+ chromectl emulate example --geo 48.85,2.35 --throttle slow-3g --hold # geo + network (held)
147
+ chromectl type example "hello" --selector "#search" --enter # type into a field
148
+ chromectl press example Enter # press key(s): Enter/Tab/ArrowDown/a…
149
+ chromectl upload example ./photo.png --selector "#file" # set a file <input>
150
+ chromectl dialog example --accept --text "Ada" # auto-answer alert/confirm/prompt
151
+ chromectl heap example --out heap.heapsnapshot # V8 heap snapshot (DevTools ▸ Memory)
152
+
153
+ chromectl raw browser Browser.getVersion # raw CDP command (browser target)
154
+ chromectl raw example Runtime.evaluate '{"expression":"1+1","returnByValue":true}'
155
+ chromectl proto Network # protocol lookup: a domain…
156
+ chromectl proto Network.getResponseBody # …a command's params/returns
157
+ chromectl repl example # interactive CDP prompt
158
+ ```
159
+
160
+ ### Target selection
161
+ Anywhere a command takes a target you can pass:
162
+ - an **id-prefix** (`B1B0`), a **url/title substring** (`example`, `github`),
163
+ - `browser` for the browser-level target (for `raw`/`repl`),
164
+ - or **nothing** to use the first open page.
165
+
166
+ ### Emulation caveat
167
+ CDP overrides (`emulate`/`resize` viewport, geo, throttle, color-scheme, UA) live on
168
+ the **CDP connection** and revert when it closes. Since each `chromectl` command connects,
169
+ acts, and disconnects, use `--shot` to capture in the same session, or `--hold` to keep
170
+ the connection open (Ctrl-C to release) so the override persists while you do other work.
171
+
172
+ ### Interaction (Tier 2) — how it works
173
+ `snapshot`/`click`/`fill`/`hover` use **Playwright attached to your Chrome over CDP**
174
+ (`connect_over_cdp`) — no separate browser is launched. You get Playwright's
175
+ auto-waiting and actionability checks (waits for the element to exist, be visible, and
176
+ be stable before acting) instead of hand-rolled timing. `snapshot` writes `.cdp-snap.json`
177
+ so `--ref N` works in a later, separate command (the stateless equivalent of the MCP's
178
+ element uids). Locate an element by any of: `--ref`, `--selector`, `--text`, or
179
+ `--role`+`--name`.
180
+
181
+ ### Handy options
182
+ - `--host` / `--port` (or env `CDP_HOST` / `CDP_PORT`) — default `localhost:9222`.
183
+ - `capture`: `--print N`, `--out FILE`, `--har FILE`, `--type TYPE`,
184
+ `--no-bodies`, `--bodycap N`, `--max SECONDS`, `--quiet SECONDS`,
185
+ `--attach TARGET`, `--reload`.
186
+
187
+ ## How it works (the workflow)
188
+
189
+ `HTTP /json/version` → open ONE WebSocket to the browser (or a per-tab socket) →
190
+ send CDP commands (`{id, method, params}`) and receive replies + unsolicited
191
+ events → for capture: `Network.enable` **before** navigating, correlate events by
192
+ `requestId`, fetch each body on `loadingFinished` (before Chrome evicts it), merge
193
+ the `*ExtraInfo` events for the real cookies/headers, and reconstruct raw HTTP.
194
+
195
+ A background thread reads frames into a queue so `call()` (request/response) and
196
+ the capture/console/watch loops (event streams) share one connection cleanly.
197
+
198
+ **Gotcha baked in:** `websocket-client` sends an `Origin` header by default, which
199
+ modern Chrome rejects on the debug port. `chromectl` sets `suppress_origin=True` so
200
+ connections are accepted without relaunching Chrome.
201
+
202
+ ## Layout
203
+ - `chromectl/cli.py` — the CLI.
204
+ - `chromectl/protocol.json` — bundled CDP schema used by `chromectl proto`/`cheat` (falls back to live).
205
+ - `pyproject.toml` — packaging; `chromectl` console entry point.
206
+ - `AGENTS.md` — the agent-facing interface reference (auto-read by coding agents).
207
+
208
+ ## For agents
209
+ Read `AGENTS.md` (or run `chromectl cheat --json` once) for the full command surface —
210
+ no need to call `--help` per command.
@@ -0,0 +1,2 @@
1
+ from .cli import main
2
+ __all__ = ["main"]