1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
use clap::Subcommand;
#[derive(Subcommand, Debug)]
pub enum BrowserCommand {
/// Open a URL in the browser.
Open {
/// URL to navigate to.
url: String,
},
/// Take a snapshot of the current page (accessibility tree with element refs).
Snapshot {
/// Only show interactive/actionable elements.
#[arg(long, short)]
interactive: bool,
/// Remove empty structural elements (no text content).
#[arg(long, short)]
compact: bool,
/// Limit tree depth.
#[arg(long, short)]
depth: Option<u32>,
/// Scope snapshot to a CSS selector.
#[arg(long, short = 'S')]
selector: Option<String>,
},
/// Click an element by @ref.
Click {
/// Element reference (e.g., @e3).
#[arg(name = "ref")]
eref: String,
},
/// Click using real mouse events at coordinates or @ref.
ClickAt {
/// Element reference or coordinates.
#[arg(name = "ref")]
eref: Option<String>,
/// X coordinate.
#[arg(long)]
x: Option<f64>,
/// Y coordinate.
#[arg(long)]
y: Option<f64>,
},
/// Fill text into an input element.
Fill {
/// Element reference (e.g., @e5).
#[arg(name = "ref")]
eref: String,
/// Text to fill.
text: String,
},
/// Press a key (Enter, Tab, Escape, etc.).
Press {
/// Key name.
key: String,
},
/// Scroll the page.
Scroll {
/// Direction: up, down, left, right.
#[arg(default_value = "down")]
direction: String,
/// Distance in pixels.
#[arg(long, default_value = "500")]
amount: i32,
},
/// Take a screenshot.
Screenshot {
/// Output path (default: screenshot.png).
#[arg(default_value = "screenshot.png")]
path: String,
},
/// Take an annotated screenshot with numbered element labels.
Annotate {
/// Output path (default: annotated.png).
#[arg(default_value = "annotated.png")]
path: String,
},
/// Open Chrome DevTools inspector for the active page.
Inspect,
/// Get page text content.
Text,
/// Get current URL.
Url,
/// Get page title.
Title,
/// Get full page HTML.
Content,
/// Get browser console messages.
Console {
/// Max entries to show.
#[arg(long, default_value = "50")]
limit: u64,
},
/// Wait for a condition (selector, text, url, networkidle).
Wait {
/// Wait target.
target: String,
/// Timeout in seconds.
#[arg(long, default_value = "30")]
timeout: u64,
},
/// Wait for URL to match a pattern.
WaitForUrl {
/// URL pattern to match.
pattern: String,
/// Timeout in seconds.
#[arg(long, default_value = "30")]
timeout: u64,
},
/// Execute JavaScript.
Evaluate {
/// JavaScript code.
js: String,
},
/// Find elements by text.
GetByText {
/// Text to search for.
text: String,
/// Exact match.
#[arg(long)]
exact: bool,
},
/// Capture video URLs from a page (inject interceptor, wait, collect).
CaptureVideo {
/// Video page URL.
url: String,
/// Wait time in milliseconds for video to load (default: 8000).
#[arg(long, default_value = "8000")]
wait: u64,
},
/// Download video from a page (capture URL + download with cookies).
DownloadVideo {
/// Video page URL.
url: String,
/// Output file path.
#[arg(short, long, default_value = "video.mp4")]
output: String,
/// Wait time in milliseconds for video to load (default: 8000).
#[arg(long, default_value = "8000")]
wait: u64,
},
/// Find elements by ARIA role.
GetByRole {
/// Role name (e.g., button, link, textbox).
role: String,
},
/// Find elements by label.
GetByLabel {
/// Label text.
label: String,
},
/// Find element by text content or label.
Find {
/// Text or label to search for.
text: String,
},
/// Navigate back.
Back,
/// Navigate forward.
Forward,
/// Reload page.
Reload,
/// Close the browser.
Close,
/// Tab management subcommands.
#[command(subcommand)]
Tab(TabCommand),
/// Get element property (text, html, value, attribute, count, bounding box).
#[command(subcommand)]
Get(GetCommand),
/// Get page errors.
Errors,
/// Execute multiple browser commands in a single session.
Batch {
/// Commands to execute, each as a quoted string (e.g., "open https://example.com" "snapshot -i").
commands: Vec<String>,
},
/// Keyboard input subcommands.
#[command(subcommand)]
Keyboard(KeyboardCommand),
/// Download a file by clicking an element.
Download {
/// Element selector or @ref to click.
selector: String,
/// Output file path.
path: String,
},
/// Auth vault management for saved credentials.
#[command(subcommand)]
Auth(AuthCommand),
/// List available Chrome profiles.
Profiles,
/// Connect to a browser via CDP (port number or ws:// URL).
Connect {
/// CDP port number or WebSocket URL (e.g., 9222 or ws://127.0.0.1:9222/...).
target: String,
},
/// Save browser state (cookies + localStorage) to a JSON file.
StateSave {
/// Output file path.
path: String,
},
/// Load browser state (cookies + localStorage) from a JSON file.
StateLoad {
/// Input file path.
path: String,
},
/// List network requests from the page.
Requests {
/// Clear request history after listing.
#[arg(long)]
clear: bool,
/// Filter requests by URL pattern.
#[arg(long)]
filter: Option<String>,
},
/// Show or list browser sessions/targets.
Session {
/// Action: show (current session info) or list (all debugging targets).
#[arg(default_value = "show")]
action: String,
},
/// Run any browser action with JSON args (advanced).
Raw {
/// Action name.
action: String,
/// JSON arguments.
#[arg(default_value = "{}")]
args: String,
},
}
/// Tab management subcommands.
#[derive(Subcommand, Debug)]
pub enum TabCommand {
/// Open a new tab.
New {
/// Optional URL to open in the new tab.
url: Option<String>,
},
/// List all open tabs.
List,
/// Close a tab by index.
Close {
/// Tab index (0-based).
index: u32,
},
/// Switch to a tab by index.
Switch {
/// Tab index (0-based).
index: u32,
},
}
/// Get element property subcommands.
#[derive(Subcommand, Debug)]
pub enum GetCommand {
/// Get element text content.
Text {
/// CSS selector or @ref.
selector: Option<String>,
},
/// Get element inner HTML.
Html {
/// CSS selector or @ref.
selector: Option<String>,
},
/// Get input element value.
Value {
/// CSS selector or @ref.
selector: Option<String>,
},
/// Get element attribute value.
Attr {
/// Attribute name.
name: String,
/// CSS selector or @ref.
selector: Option<String>,
},
/// Count elements matching a selector.
Count {
/// CSS selector.
selector: String,
},
/// Get element bounding box.
Box {
/// CSS selector or @ref.
selector: Option<String>,
},
}
/// Keyboard input subcommands.
#[derive(Subcommand, Debug)]
pub enum KeyboardCommand {
/// Type text with key events (keyDown/keyUp per character).
Type {
/// Text to type.
text: String,
},
/// Insert text directly (bypasses key events).
Inserttext {
/// Text to insert.
text: String,
},
}
/// Auth vault subcommands.
#[derive(Subcommand, Debug)]
pub enum AuthCommand {
/// Save credentials to the vault.
Save {
/// Site domain or identifier.
site: String,
/// Username.
#[arg(long)]
username: String,
/// Password.
#[arg(long)]
password: String,
},
/// Auto-login using saved credentials.
Login {
/// Site domain or identifier.
site: String,
},
/// List saved credential entries.
List,
/// Show details for a saved credential.
Show {
/// Site domain or identifier.
site: String,
},
/// Delete a saved credential.
Delete {
/// Site domain or identifier.
site: String,
},
}