1#![allow(missing_docs)]
5
6use clap::{Parser, Subcommand, ValueEnum};
7
8#[derive(Debug, Parser)]
10#[command(
11 name = "browser-automation-cli",
12 version,
13 about = "One-shot browser automation CLI (Chrome CDP). BORN, EXECUTE, FINALIZE, DIE.",
14 long_about = None,
15 propagate_version = true
16)]
17pub struct Cli {
18 #[command(flatten)]
19 pub globals: GlobalOpts,
20
21 #[command(subcommand)]
22 pub command: Commands,
23}
24
25#[derive(Debug, Clone, Parser)]
26pub struct GlobalOpts {
27 #[arg(long, global = true)]
28 pub json: bool,
29
30 #[arg(
32 short = 'q',
33 long = "quiet",
34 global = true,
35 )]
36 pub quiet: bool,
37
38 #[arg(
40 long = "verbose",
41 global = true,
42 )]
43 pub verbose: bool,
44
45 #[arg(long = "debug", global = true)]
47 pub debug: bool,
48
49 #[arg(
50 long,
51 global = true,
52 default_value_t = 0
53 )]
54 pub timeout: u64,
55
56 #[arg(
58 long,
59 global = true,
60 default_value_t = 0
61 )]
62 pub step_timeout: u64,
63
64 #[arg(long, global = true)]
66 pub headed: bool,
67
68 #[arg(long, global = true)]
69 pub artifacts_dir: Option<std::path::PathBuf>,
70
71 #[arg(long, global = true)]
72 pub lang: Option<String>,
73
74 #[arg(long, global = true)]
75 pub capture_console: bool,
76
77 #[arg(long, global = true)]
78 pub capture_network: bool,
79
80 #[arg(long, global = true)]
81 pub ignore_robots: bool,
82
83 #[arg(
84 long,
85 global = true,
86 )]
87 pub i_accept_robots_risk: bool,
88
89 #[arg(long, global = true)]
91 pub category_memory: bool,
92
93 #[arg(
95 long,
96 global = true,
97 )]
98 pub category_extensions: bool,
99
100 #[arg(
102 long,
103 global = true,
104 )]
105 pub category_third_party: bool,
106
107 #[arg(long, global = true)]
109 pub category_webmcp: bool,
110
111 #[arg(
113 long,
114 global = true,
115 )]
116 pub experimental_screencast: bool,
117
118 #[arg(
120 long,
121 global = true,
122 )]
123 pub experimental_vision: bool,
124}
125
126#[derive(Debug, Subcommand)]
127pub enum Commands {
128 Doctor {
130 #[arg(long)]
131 offline: bool,
132 #[arg(long)]
133 quick: bool,
134 #[arg(long)]
135 fix: bool,
136 #[arg(long)]
137 json: bool,
138 },
139 Commands {
141 #[arg(long)]
142 json: bool,
143 },
144 Schema {
146 #[arg(long = "cmd", value_name = "CMD")]
147 cmd: String,
148 },
149 Version,
151 Goto {
153 url: String,
154 #[arg(long)]
156 init_script: Option<String>,
157 #[arg(long)]
159 handle_before_unload: bool,
160 #[arg(long)]
162 navigation_timeout_ms: Option<u64>,
163 },
164 View {
166 #[arg(long)]
167 verbose: bool,
168 #[arg(long)]
169 path: Option<std::path::PathBuf>,
170 },
171 Press {
173 target: String,
174 #[arg(long)]
175 dblclick: bool,
176 #[arg(long)]
178 include_snapshot: bool,
179 },
180 ClickAt {
182 #[arg(long)]
183 x: f64,
184 #[arg(long)]
185 y: f64,
186 #[arg(long)]
187 dblclick: bool,
188 #[arg(long)]
190 include_snapshot: bool,
191 },
192 Write {
194 target: String,
195 value: String,
196 #[arg(long)]
198 include_snapshot: bool,
199 },
200 Keys {
202 key: String,
203 #[arg(long)]
205 include_snapshot: bool,
206 },
207 Type {
209 text: String,
211 #[arg(long)]
213 target: Option<String>,
214 #[arg(long)]
215 clear: bool,
216 #[arg(long)]
218 submit: Option<String>,
219 #[arg(long)]
221 focus_only: bool,
222 },
223 Wait {
225 #[arg(long, default_value_t = 0)]
226 ms: u64,
227 #[arg(long = "text", action = clap::ArgAction::Append)]
229 text: Vec<String>,
230 #[arg(long)]
231 selector: Option<String>,
232 #[arg(long)]
234 state: Option<String>,
235 #[arg(long)]
237 wait_timeout_ms: Option<u64>,
238 #[arg(long)]
240 include_snapshot: bool,
241 },
242 Hover {
244 target: String,
245 #[arg(long)]
247 include_snapshot: bool,
248 },
249 Drag {
251 #[arg(long)]
252 from: String,
253 #[arg(long)]
254 to: String,
255 #[arg(long)]
257 include_snapshot: bool,
258 },
259 FillForm {
261 #[arg(long)]
262 json: String,
263 #[arg(long)]
265 include_snapshot: bool,
266 },
267 Upload {
269 target: String,
270 path: std::path::PathBuf,
271 #[arg(long)]
273 include_snapshot: bool,
274 },
275 Back,
277 Forward,
279 Reload {
281 #[arg(long)]
282 ignore_cache: bool,
283 #[arg(long)]
285 init_script: Option<String>,
286 #[arg(long)]
288 handle_before_unload: bool,
289 },
290 Eval {
292 expression: String,
294 #[arg(long)]
296 args: Option<String>,
297 #[arg(long)]
299 dialog_action: Option<String>,
300 #[arg(long)]
302 file_path: Option<std::path::PathBuf>,
303 },
304 Grab {
306 #[arg(long)]
307 path: Option<std::path::PathBuf>,
308 #[arg(long, value_enum, default_value_t = GrabFormat::Png)]
309 format: GrabFormat,
310 #[arg(long)]
311 full_page: bool,
312 #[arg(long)]
313 quality: Option<i32>,
314 #[arg(long)]
316 element: Option<String>,
317 },
318 Run {
320 #[arg(long)]
321 script: std::path::PathBuf,
322 },
323 Exec {
325 #[arg(trailing_var_arg = true)]
328 args: Vec<String>,
329 },
330 Extract {
332 target: String,
333 #[arg(long)]
334 attr: Option<String>,
335 },
336 Text { target: String },
338 Scroll {
340 #[arg(long)]
342 target: Option<String>,
343 #[arg(long, default_value_t = 0.0)]
344 delta_x: f64,
345 #[arg(long, default_value_t = 0.0)]
346 delta_y: f64,
347 },
348 Cookie {
350 #[command(subcommand)]
351 action: CookieAction,
352 },
353 Attr { target: String, name: String },
355 Assert {
357 #[command(subcommand)]
358 kind: AssertKind,
359 },
360 Console {
362 #[command(subcommand)]
363 action: ConsoleAction,
364 },
365 Net {
367 #[command(subcommand)]
368 action: NetAction,
369 },
370 Page {
372 #[command(subcommand)]
373 action: Option<PageAction>,
374 },
375 Dialog {
377 #[command(subcommand)]
378 action: DialogAction,
379 },
380 Scrape {
382 url: String,
383 #[arg(long, default_value = "text")]
385 format: String,
386 #[arg(long, default_value = "browser")]
388 engine: String,
389 #[arg(long)]
391 only_main_content: bool,
392 },
393 BatchScrape {
395 #[arg(long)]
396 urls_file: std::path::PathBuf,
397 #[arg(long, default_value = "text")]
398 format: String,
399 #[arg(long, default_value_t = 2)]
400 concurrency: usize,
401 },
402 Crawl {
404 url: String,
405 #[arg(long, default_value_t = 20)]
406 limit: usize,
407 #[arg(long, default_value_t = 2)]
408 max_depth: usize,
409 #[arg(long, default_value = "text")]
410 format: String,
411 #[arg(long, default_value_t = true)]
413 same_host: bool,
414 },
415 Map {
417 url: String,
418 #[arg(long, default_value_t = 50)]
419 limit: usize,
420 #[arg(long, default_value_t = 2)]
421 max_depth: usize,
422 },
423 Search {
425 query: String,
426 #[arg(long, default_value_t = 10)]
427 limit: usize,
428 },
429 Parse {
431 path: std::path::PathBuf,
432 },
433 Mitm {
435 #[command(subcommand)]
436 action: MitmAction,
437 },
438 Workflow {
440 #[command(subcommand)]
441 action: WorkflowAction,
442 },
443 Config {
445 #[command(subcommand)]
446 action: ConfigAction,
447 },
448 Emulate {
450 #[arg(long)]
451 user_agent: Option<String>,
452 #[arg(long)]
453 locale: Option<String>,
454 #[arg(long)]
455 timezone: Option<String>,
456 #[arg(long)]
457 offline: bool,
458 #[arg(long)]
459 latitude: Option<f64>,
460 #[arg(long)]
461 longitude: Option<f64>,
462 #[arg(long)]
463 media: Option<String>,
464 #[arg(long)]
466 network_conditions: Option<String>,
467 #[arg(long)]
469 cpu_throttling_rate: Option<f64>,
470 #[arg(long)]
472 color_scheme: Option<String>,
473 #[arg(long)]
475 extra_headers: Option<String>,
476 #[arg(long)]
478 viewport: Option<String>,
479 },
480 Resize {
482 #[arg(long)]
483 width: i32,
484 #[arg(long)]
485 height: i32,
486 #[arg(long, default_value_t = 1.0)]
487 scale: f64,
488 #[arg(long)]
489 mobile: bool,
490 },
491 Perf {
493 #[command(subcommand)]
494 action: PerfAction,
495 },
496 Lighthouse {
498 url: String,
499 #[arg(long)]
500 out_dir: Option<std::path::PathBuf>,
501 #[arg(long, default_value = "desktop")]
502 device: String,
503 #[arg(long, default_value = "navigation")]
505 mode: String,
506 #[arg(long)]
507 lighthouse_path: Option<std::path::PathBuf>,
508 },
509 Screencast {
511 #[command(subcommand)]
512 action: ScreencastAction,
513 },
514 Heap {
516 #[command(subcommand)]
517 action: HeapAction,
518 },
519 Extension {
521 #[command(subcommand)]
522 action: ExtensionAction,
523 },
524 Devtools3p {
526 #[command(subcommand)]
527 action: Devtools3pAction,
528 },
529 Webmcp {
531 #[command(subcommand)]
532 action: WebmcpAction,
533 },
534 Completions {
536 #[arg(value_enum)]
537 shell: CompletionShell,
538 },
539}
540
541#[derive(Debug, Clone, Subcommand)]
542pub enum PerfAction {
543 Start {
544 #[arg(long)]
545 path: Option<std::path::PathBuf>,
546 #[arg(long)]
547 reload: bool,
548 #[arg(long)]
550 auto_stop: bool,
551 },
552 Stop {
553 #[arg(long)]
554 path: Option<std::path::PathBuf>,
555 },
556 Insight {
557 #[arg(long)]
559 name: Option<String>,
560 #[arg(long)]
562 insight_set_id: Option<String>,
563 #[arg(long)]
565 insight_name: Option<String>,
566 },
567}
568
569#[derive(Debug, Clone, Subcommand)]
570pub enum ScreencastAction {
571 Start {
572 #[arg(long)]
573 path: Option<std::path::PathBuf>,
574 },
575 Stop {
576 #[arg(long)]
578 path: Option<std::path::PathBuf>,
579 },
580}
581
582#[derive(Debug, Clone, Subcommand)]
583pub enum HeapAction {
584 Take {
585 #[arg(long)]
586 path: std::path::PathBuf,
587 },
588 Close {
589 #[arg(long)]
590 path: std::path::PathBuf,
591 },
592 Compare {
593 #[arg(long)]
594 base: std::path::PathBuf,
595 #[arg(long)]
596 current: std::path::PathBuf,
597 #[arg(long)]
599 class_index: Option<u64>,
600 },
601 Summary {
602 #[arg(long)]
603 path: std::path::PathBuf,
604 },
605 Details {
606 #[arg(long)]
607 path: std::path::PathBuf,
608 #[arg(long)]
609 filter_name: Option<String>,
610 #[arg(long)]
611 page_idx: Option<usize>,
612 #[arg(long)]
613 page_size: Option<usize>,
614 },
615 ClassNodes {
616 #[arg(long)]
617 path: std::path::PathBuf,
618 #[arg(long)]
619 id: u64,
620 #[arg(long)]
621 filter_name: Option<String>,
622 #[arg(long)]
623 page_idx: Option<usize>,
624 #[arg(long)]
625 page_size: Option<usize>,
626 },
627 Dominators {
628 #[arg(long)]
629 path: std::path::PathBuf,
630 #[arg(long)]
631 node: u64,
632 },
633 DupStrings {
634 #[arg(long)]
635 path: std::path::PathBuf,
636 #[arg(long)]
637 page_idx: Option<usize>,
638 #[arg(long)]
639 page_size: Option<usize>,
640 },
641 Edges {
642 #[arg(long)]
643 path: std::path::PathBuf,
644 #[arg(long)]
645 node: u64,
646 #[arg(long)]
647 page_idx: Option<usize>,
648 #[arg(long)]
649 page_size: Option<usize>,
650 },
651 Retainers {
652 #[arg(long)]
653 path: std::path::PathBuf,
654 #[arg(long)]
655 node: u64,
656 #[arg(long)]
657 page_idx: Option<usize>,
658 #[arg(long)]
659 page_size: Option<usize>,
660 },
661 Paths {
662 #[arg(long)]
663 path: std::path::PathBuf,
664 #[arg(long)]
665 node: u64,
666 #[arg(long, default_value_t = 8)]
667 max_depth: u64,
668 #[arg(long)]
669 max_nodes: Option<u64>,
670 #[arg(long)]
671 max_siblings: Option<u64>,
672 },
673 ObjectDetails {
675 #[arg(long)]
676 path: std::path::PathBuf,
677 #[arg(long)]
678 node: u64,
679 },
680}
681
682#[derive(Debug, Clone, Subcommand)]
683pub enum ExtensionAction {
684 List,
685 Install {
686 path: std::path::PathBuf,
687 },
688 Reload {
689 id: String,
690 #[arg(long)]
692 path: Option<std::path::PathBuf>,
693 },
694 Trigger {
695 id: String,
696 #[arg(long)]
698 path: Option<std::path::PathBuf>,
699 },
700 Uninstall {
701 id: String,
702 },
703}
704
705#[derive(Debug, Clone, Subcommand)]
706pub enum Devtools3pAction {
707 List {
708 #[arg(long)]
710 url: Option<String>,
711 },
712 Exec {
713 name: String,
714 #[arg(long)]
715 params: Option<String>,
716 #[arg(long)]
717 url: Option<String>,
718 },
719}
720
721#[derive(Debug, Clone, Subcommand)]
722pub enum WebmcpAction {
723 List {
724 #[arg(long)]
725 url: Option<String>,
726 },
727 Exec {
728 name: String,
729 #[arg(long)]
730 input: Option<String>,
731 #[arg(long)]
732 url: Option<String>,
733 },
734}
735
736#[derive(Debug, Clone, Copy, ValueEnum)]
737pub enum CompletionShell {
738 Bash,
739 Zsh,
740 Fish,
741 Elvish,
742 Powershell,
743}
744
745#[derive(Debug, Clone, Subcommand)]
746pub enum PageAction {
747 Info,
749 List,
751 New {
753 #[arg(long)]
754 url: Option<String>,
755 #[arg(long)]
757 background: bool,
758 #[arg(long)]
760 isolated_context: bool,
761 },
762 Select {
764 #[arg(value_name = "INDEX")]
765 index: Option<usize>,
766 #[arg(long = "page-id")]
768 page_id: Option<usize>,
769 #[arg(long, default_value_t = true)]
771 bring_to_front: bool,
772 },
773 Close {
775 #[arg(long)]
776 index: Option<usize>,
777 #[arg(long = "page-id")]
779 page_id: Option<usize>,
780 },
781}
782
783#[derive(Debug, Clone, Subcommand)]
784pub enum CookieAction {
785 List {
787 #[arg(long)]
788 url: Option<String>,
789 },
790 Set {
792 #[arg(long)]
794 json: String,
795 },
796 Clear,
798}
799
800#[derive(Debug, Clone, Copy, ValueEnum, Default)]
801pub enum GrabFormat {
802 #[default]
803 Png,
804 Jpeg,
805 Webp,
806}
807
808#[derive(Debug, Clone, Subcommand)]
809pub enum AssertKind {
810 Url {
811 value: String,
812 #[arg(long)]
813 contains: bool,
814 },
815 Text {
816 value: String,
817 #[arg(long)]
818 target: Option<String>,
819 },
820 Console {
821 #[arg(long, default_value = "error")]
822 level: String,
823 #[arg(long, default_value_t = 0)]
824 max: u64,
825 },
826}
827
828#[derive(Debug, Clone, Subcommand)]
829pub enum ConsoleAction {
830 List {
831 #[arg(long)]
833 page_idx: Option<usize>,
834 #[arg(long)]
836 page_size: Option<usize>,
837 #[arg(long)]
839 types: Option<String>,
840 #[arg(long)]
842 include_preserved: bool,
843 #[arg(long)]
845 service_worker_id: Option<String>,
846 },
847 Get {
848 id: usize,
849 },
850 Clear,
851 Dump {
852 #[arg(long)]
853 path: std::path::PathBuf,
854 },
855}
856
857#[derive(Debug, Clone, Subcommand)]
858pub enum NetAction {
859 List {
860 #[arg(long)]
862 page_idx: Option<usize>,
863 #[arg(long)]
865 page_size: Option<usize>,
866 #[arg(long)]
868 resource_types: Option<String>,
869 #[arg(long)]
871 include_preserved: bool,
872 },
873 Get {
874 id: String,
876 #[arg(long)]
877 request_path: Option<std::path::PathBuf>,
878 #[arg(long)]
879 response_path: Option<std::path::PathBuf>,
880 },
881}
882
883#[derive(Debug, Clone, Subcommand)]
884pub enum DialogAction {
885 Accept {
886 #[arg(long)]
887 text: Option<String>,
888 },
889 Dismiss,
890}
891
892#[derive(Debug, Clone, Subcommand)]
893pub enum MitmAction {
894 Status,
896 List {
898 #[arg(long)]
899 host: Option<String>,
900 #[arg(long, default_value_t = 100)]
901 limit: usize,
902 },
903 Get { id: u64 },
905 Har {
907 #[arg(long)]
908 out: std::path::PathBuf,
909 },
910 Export {
912 #[arg(long, default_value = "json")]
913 format: String,
914 #[arg(long)]
915 out: std::path::PathBuf,
916 },
917 Domains,
919 Apis {
921 #[arg(long)]
922 kind: Option<String>,
923 },
924 InitCa,
926 Start {
928 #[arg(long, default_value_t = 30)]
930 seconds: u64,
931 },
932}
933
934#[derive(Debug, Clone, Subcommand)]
935pub enum WorkflowAction {
936 Run {
938 #[arg(long)]
939 manifest: std::path::PathBuf,
940 #[arg(long)]
941 journal: Option<std::path::PathBuf>,
942 },
943 Resume {
945 #[arg(long)]
946 manifest: std::path::PathBuf,
947 #[arg(long)]
948 journal: Option<std::path::PathBuf>,
949 },
950 Status {
952 #[arg(long)]
953 journal: Option<std::path::PathBuf>,
954 #[arg(long)]
955 name: Option<String>,
956 },
957}
958
959#[derive(Debug, Clone, Subcommand)]
960pub enum ConfigAction {
961 Path,
963 Init,
965 Show,
967 Set {
969 key: String,
970 value: String,
971 },
972 Get {
974 key: Option<String>,
975 },
976}