1pub mod auth;
4pub mod config;
5pub mod go_ralph;
6pub mod oracle;
7pub mod run;
8
9use clap::{Parser, Subcommand};
10use std::path::PathBuf;
11
12#[derive(Parser, Debug)]
17#[command(name = "codetether")]
18#[command(version, about, long_about = None)]
19pub struct Cli {
20 #[arg(global = true, last = true)]
22 pub project: Option<PathBuf>,
23
24 #[arg(long, global = true)]
26 pub print_logs: bool,
27
28 #[arg(long, global = true, value_parser = ["DEBUG", "INFO", "WARN", "ERROR"])]
30 pub log_level: Option<String>,
31
32 #[arg(short, long, env = "CODETETHER_SERVER")]
35 pub server: Option<String>,
36
37 #[arg(short, long, env = "CODETETHER_TOKEN")]
39 pub token: Option<String>,
40
41 #[arg(short, long, env = "CODETETHER_WORKER_NAME")]
43 pub name: Option<String>,
44
45 #[command(subcommand)]
46 pub command: Option<Command>,
47}
48
49#[derive(Subcommand, Debug)]
50pub enum Command {
51 Tui(TuiArgs),
53
54 Serve(ServeArgs),
56
57 Run(RunArgs),
59
60 Pr(PrArgs),
62
63 Auth(AuthArgs),
65
66 Config(ConfigArgs),
68
69 Worker(A2aArgs),
71
72 #[command(hide = true)]
74 GitCredentialHelper(GitCredentialHelperArgs),
75
76 Spawn(SpawnArgs),
78
79 Swarm(SwarmArgs),
81
82 #[command(hide = true)]
84 SwarmSubagent(SwarmSubagentArgs),
85
86 Rlm(RlmArgs),
88
89 Oracle(OracleArgs),
91
92 Ralph(RalphArgs),
94
95 Mcp(McpArgs),
97
98 Stats(StatsArgs),
100
101 Cleanup(CleanupArgs),
103
104 Models(ModelsArgs),
106
107 Index(IndexArgs),
109
110 Benchmark(BenchmarkArgs),
112
113 Moltbook(MoltbookArgs),
115
116 Okr(OkrArgs),
118
119 Forage(ForageArgs),
121}
122
123#[derive(Parser, Debug)]
124pub struct AuthArgs {
125 #[command(subcommand)]
126 pub command: AuthCommand,
127}
128
129#[derive(Subcommand, Debug)]
130pub enum AuthCommand {
131 Copilot(CopilotAuthArgs),
133
134 Codex(CodexAuthArgs),
136
137 Cookies(CookieAuthArgs),
139
140 Register(RegisterAuthArgs),
142
143 Login(LoginAuthArgs),
145}
146
147#[derive(Parser, Debug)]
148pub struct RegisterAuthArgs {
149 #[arg(short, long, env = "CODETETHER_SERVER")]
151 pub server: String,
152
153 #[arg(short, long)]
155 pub email: Option<String>,
156
157 #[arg(long)]
159 pub first_name: Option<String>,
160
161 #[arg(long)]
163 pub last_name: Option<String>,
164
165 #[arg(long)]
167 pub referral_source: Option<String>,
168}
169
170#[derive(Parser, Debug)]
171pub struct LoginAuthArgs {
172 #[arg(short, long, env = "CODETETHER_SERVER")]
174 pub server: String,
175
176 #[arg(short, long)]
178 pub email: Option<String>,
179}
180
181#[derive(Parser, Debug)]
182pub struct CopilotAuthArgs {
183 #[arg(long)]
185 pub enterprise_url: Option<String>,
186
187 #[arg(long, env = "CODETETHER_COPILOT_OAUTH_CLIENT_ID")]
189 pub client_id: Option<String>,
190}
191
192#[derive(Parser, Debug)]
193pub struct CodexAuthArgs {
194 #[arg(long, default_value_t = false)]
196 pub device_code: bool,
197}
198
199#[derive(Parser, Debug)]
200pub struct CookieAuthArgs {
201 #[arg(long, default_value = "nextdoor-web")]
203 pub provider: String,
204
205 #[arg(long)]
207 pub file: PathBuf,
208
209 #[arg(long, default_value_t = false)]
211 pub keep_all: bool,
212}
213
214#[derive(Parser, Debug)]
215pub struct TuiArgs {
216 pub project: Option<PathBuf>,
218
219 #[arg(long)]
221 pub allow_network: bool,
222}
223
224#[derive(Parser, Debug)]
225pub struct ServeArgs {
226 #[arg(short, long, default_value = "4096")]
228 pub port: u16,
229
230 #[arg(long, default_value = "127.0.0.1")]
232 pub hostname: String,
233
234 #[arg(long)]
236 pub mdns: bool,
237}
238
239#[derive(Parser, Debug)]
240pub struct RunArgs {
241 pub message: String,
243
244 #[arg(short, long)]
246 pub continue_session: bool,
247
248 #[arg(short, long)]
250 pub session: Option<String>,
251
252 #[arg(short, long)]
254 pub model: Option<String>,
255
256 #[arg(long)]
258 pub agent: Option<String>,
259
260 #[arg(long, default_value = "default", value_parser = ["default", "json"])]
262 pub format: String,
263
264 #[arg(short, long)]
266 pub file: Vec<PathBuf>,
267
268 #[arg(long)]
270 pub codex_session: Option<String>,
271
272 #[arg(long)]
274 pub max_steps: Option<usize>,
275}
276
277#[derive(Parser, Debug)]
278pub struct PrArgs {
279 #[command(subcommand)]
280 pub command: PrCommand,
281}
282
283#[derive(Subcommand, Debug)]
284pub enum PrCommand {
285 Create(CreatePrArgs),
287}
288
289#[derive(Parser, Debug, Clone)]
290pub struct CreatePrArgs {
291 #[arg(long)]
293 pub title: String,
294
295 #[arg(long)]
297 pub body: Option<String>,
298
299 #[arg(long)]
301 pub body_file: Option<PathBuf>,
302
303 #[arg(long, default_value = "main")]
305 pub base: String,
306
307 #[arg(long)]
309 pub head: Option<String>,
310
311 #[arg(long, default_value_t = false)]
313 pub draft: bool,
314
315 #[arg(long, default_value_t = false)]
317 pub json: bool,
318
319 #[arg(long)]
321 pub project: Option<PathBuf>,
322}
323
324#[derive(Parser, Debug, Clone)]
326pub struct WorkerServerArgs {
327 #[arg(long, default_value = "0.0.0.0")]
329 pub hostname: String,
330
331 #[arg(short, long, default_value = "8080")]
333 pub port: u16,
334}
335
336#[derive(Parser, Debug, Clone)]
337pub struct A2aArgs {
338 #[arg(short, long, env = "CODETETHER_SERVER", default_value = crate::a2a::worker::DEFAULT_A2A_SERVER_URL)]
340 pub server: String,
341
342 #[arg(short, long, env = "CODETETHER_TOKEN")]
344 pub token: Option<String>,
345
346 #[arg(short, long, env = "CODETETHER_WORKER_NAME")]
348 pub name: Option<String>,
349
350 #[arg(short, long, visible_alias = "codebases")]
352 pub workspaces: Option<String>,
353
354 #[arg(
356 long,
357 env = "CODETETHER_WORKER_MAX_CONCURRENT_TASKS",
358 default_value_t = 4
359 )]
360 pub max_concurrent_tasks: usize,
361
362 #[arg(long, default_value = "safe", value_parser = ["all", "safe", "none"])]
364 pub auto_approve: String,
365
366 #[arg(short, long)]
368 pub email: Option<String>,
369
370 #[arg(long)]
372 pub push_url: Option<String>,
373
374 #[arg(long, default_value = "0.0.0.0", env = "CODETETHER_WORKER_HOST")]
376 pub hostname: String,
377
378 #[arg(long, default_value = "8080", env = "CODETETHER_WORKER_PORT")]
380 pub port: u16,
381
382 #[arg(long, env = "CODETETHER_WORKER_PUBLIC_URL")]
384 pub public_url: Option<String>,
385
386 #[arg(long, env = "CODETETHER_WORKER_HTTP_DISABLED")]
388 pub no_http_server: bool,
389}
390
391#[derive(Parser, Debug, Clone)]
392pub struct GitCredentialHelperArgs {
393 #[arg(long = "workspace-id", alias = "codebase-id")]
395 pub workspace_id: String,
396
397 #[arg(long, env = "CODETETHER_SERVER")]
399 pub server: Option<String>,
400
401 #[arg(long, env = "CODETETHER_TOKEN")]
403 pub token: Option<String>,
404
405 #[arg(long, env = "CODETETHER_WORKER_ID")]
407 pub worker_id: Option<String>,
408
409 pub operation: Option<String>,
411}
412
413#[derive(Parser, Debug, Clone)]
414pub struct SpawnArgs {
415 #[arg(short, long)]
417 pub name: Option<String>,
418
419 #[arg(long, default_value = "127.0.0.1")]
421 pub hostname: String,
422
423 #[arg(short, long, default_value = "4097")]
425 pub port: u16,
426
427 #[arg(long)]
429 pub public_url: Option<String>,
430
431 #[arg(short, long)]
433 pub description: Option<String>,
434
435 #[arg(long, value_delimiter = ',', env = "CODETETHER_A2A_PEERS")]
437 pub peer: Vec<String>,
438
439 #[arg(long, default_value = "15")]
441 pub discovery_interval_secs: u64,
442
443 #[arg(long = "no-auto-introduce", action = clap::ArgAction::SetFalse, default_value_t = true)]
445 pub auto_introduce: bool,
446}
447
448#[derive(Parser, Debug)]
449pub struct ConfigArgs {
450 #[arg(long)]
452 pub show: bool,
453
454 #[arg(long)]
456 pub init: bool,
457
458 #[arg(long)]
460 pub set: Option<String>,
461}
462
463#[derive(Parser, Debug)]
464pub struct SwarmArgs {
465 pub task: String,
467
468 #[arg(short, long)]
470 pub model: Option<String>,
471
472 #[arg(short = 's', long, default_value = "auto")]
474 pub strategy: String,
475
476 #[arg(long, default_value = "100")]
478 pub max_subagents: usize,
479
480 #[arg(long, default_value = "100")]
482 pub max_steps: usize,
483
484 #[arg(long, default_value = "300")]
486 pub timeout: u64,
487
488 #[arg(long)]
490 pub json: bool,
491
492 #[arg(long, default_value = "local", value_parser = ["local", "k8s", "kubernetes", "kubernetes-pod", "pod"])]
494 pub execution_mode: String,
495
496 #[arg(long, default_value = "8")]
498 pub k8s_pod_budget: usize,
499
500 #[arg(long)]
502 pub k8s_image: Option<String>,
503}
504
505#[derive(Parser, Debug)]
506pub struct SwarmSubagentArgs {
507 #[arg(long)]
509 pub payload_base64: Option<String>,
510
511 #[arg(long, default_value = "CODETETHER_SWARM_SUBTASK_PAYLOAD")]
513 pub payload_env: String,
514}
515
516#[derive(Parser, Debug)]
517pub struct RlmArgs {
518 pub query: String,
520
521 #[arg(short, long)]
523 pub model: Option<String>,
524
525 #[arg(short, long)]
527 pub file: Vec<PathBuf>,
528
529 #[arg(long)]
531 pub content: Option<String>,
532
533 #[arg(long, default_value = "auto")]
535 pub content_type: String,
536
537 #[arg(long, default_value = "4000")]
539 pub max_tokens: usize,
540
541 #[arg(long)]
543 pub json: bool,
544
545 #[arg(short, long)]
547 pub verbose: bool,
548
549 #[arg(long)]
551 pub oracle_verify: bool,
552
553 #[arg(long)]
555 pub no_oracle_verify: bool,
556
557 #[arg(long, default_value = "1")]
559 pub consensus_runs: usize,
560
561 #[arg(long, default_value = "1.0")]
563 pub consensus_threshold: f32,
564
565 #[arg(long)]
567 pub analysis_temperature: Option<f32>,
568
569 #[arg(long)]
571 pub oracle_out_dir: Option<PathBuf>,
572
573 #[arg(long, default_value = "rlm_oracle")]
575 pub oracle_prefix: String,
576}
577
578#[derive(Parser, Debug)]
579pub struct OracleArgs {
580 #[command(subcommand)]
581 pub command: OracleCommand,
582}
583
584#[derive(Subcommand, Debug)]
585pub enum OracleCommand {
586 Validate(OracleValidateArgs),
588 Sync(OracleSyncArgs),
590}
591
592#[derive(Parser, Debug)]
593pub struct OracleValidateArgs {
594 #[arg(long)]
596 pub query: String,
597
598 #[arg(short, long)]
600 pub file: Option<PathBuf>,
601
602 #[arg(long)]
604 pub content: Option<String>,
605
606 #[arg(long)]
608 pub payload: Option<String>,
609
610 #[arg(long)]
612 pub payload_file: Option<PathBuf>,
613
614 #[arg(long)]
616 pub json: bool,
617
618 #[arg(long)]
620 pub persist: bool,
621}
622
623#[derive(Parser, Debug)]
624pub struct OracleSyncArgs {
625 #[arg(long)]
627 pub json: bool,
628}
629
630#[derive(Parser, Debug)]
631pub struct RalphArgs {
632 #[arg(value_parser = ["run", "status", "create-prd"])]
634 pub action: String,
635
636 #[arg(short, long, default_value = "prd.json")]
638 pub prd: PathBuf,
639
640 #[arg(short, long)]
642 pub feature: Option<String>,
643
644 #[arg(long = "project-name")]
646 pub project_name: Option<String>,
647
648 #[arg(long, default_value = "10")]
650 pub max_iterations: usize,
651
652 #[arg(short, long)]
654 pub model: Option<String>,
655
656 #[arg(long)]
658 pub json: bool,
659}
660
661#[derive(Parser, Debug)]
662pub struct McpArgs {
663 #[arg(value_parser = ["serve", "connect", "list-tools", "call"])]
665 pub action: String,
666
667 #[arg(short, long)]
669 pub command: Option<String>,
670
671 #[arg(long)]
673 pub server_name: Option<String>,
674
675 #[arg(long)]
677 pub tool: Option<String>,
678
679 #[arg(long)]
681 pub arguments: Option<String>,
682
683 #[arg(long)]
685 pub json: bool,
686
687 #[arg(long)]
689 pub worker_id: Option<String>,
690
691 #[arg(long)]
693 pub workspace_id: Option<String>,
694
695 #[arg(long)]
700 pub bus_url: Option<String>,
701
702 #[arg(allow_hyphen_values = true)]
705 pub command_args: Vec<String>,
706}
707
708#[derive(Parser, Debug)]
709pub struct StatsArgs {
710 #[arg(short, long)]
712 pub tools: bool,
713
714 #[arg(short, long)]
716 pub files: bool,
717
718 #[arg(long)]
720 pub tokens: bool,
721
722 #[arg(long)]
724 pub tool: Option<String>,
725
726 #[arg(long)]
728 pub file: Option<String>,
729
730 #[arg(short, long, default_value = "20")]
732 pub limit: usize,
733
734 #[arg(long)]
736 pub json: bool,
737
738 #[arg(long)]
740 pub all: bool,
741}
742
743#[derive(Parser, Debug)]
744pub struct CleanupArgs {
745 #[arg(short, long)]
747 pub dry_run: bool,
748
749 #[arg(long)]
751 pub worktrees_only: bool,
752
753 #[arg(long)]
755 pub json: bool,
756}
757
758#[derive(Parser, Debug)]
759pub struct ModelsArgs {
760 #[arg(short, long)]
762 pub provider: Option<String>,
763
764 #[arg(long)]
766 pub json: bool,
767}
768
769#[derive(Parser, Debug)]
770pub struct IndexArgs {
771 #[arg(short, long)]
773 pub path: Option<PathBuf>,
774
775 #[arg(short, long)]
777 pub output: Option<PathBuf>,
778
779 #[arg(long, default_value = "1024")]
781 pub max_file_size_kib: u64,
782
783 #[arg(long, default_value = "hash-v1")]
785 pub embedding_model: String,
786
787 #[arg(long, default_value = "local")]
789 pub embedding_provider: String,
790
791 #[arg(long, default_value = "384")]
793 pub embedding_dimensions: usize,
794
795 #[arg(long, default_value = "32")]
797 pub embedding_batch_size: usize,
798
799 #[arg(long, default_value = "3")]
801 pub embedding_max_retries: u32,
802
803 #[arg(long, default_value = "250")]
805 pub embedding_retry_initial_ms: u64,
806
807 #[arg(long, default_value = "2000")]
809 pub embedding_retry_max_ms: u64,
810
811 #[arg(long, default_value = "8000")]
813 pub embedding_input_chars: usize,
814
815 #[arg(long, default_value_t = false)]
817 pub include_hidden: bool,
818
819 #[arg(long)]
821 pub json: bool,
822}
823
824#[derive(Parser, Debug)]
825pub struct MoltbookArgs {
826 #[command(subcommand)]
827 pub command: MoltbookCommand,
828}
829
830#[derive(Subcommand, Debug)]
831pub enum MoltbookCommand {
832 Register(MoltbookRegisterArgs),
834
835 Status,
837
838 Profile,
840
841 UpdateProfile(MoltbookUpdateProfileArgs),
843
844 Post(MoltbookPostArgs),
846
847 Intro,
849
850 Heartbeat,
852
853 Comment(MoltbookCommentArgs),
855
856 Search(MoltbookSearchArgs),
858}
859
860#[derive(Parser, Debug)]
861pub struct MoltbookRegisterArgs {
862 pub name: String,
864
865 #[arg(short, long)]
867 pub description: Option<String>,
868}
869
870#[derive(Parser, Debug)]
871pub struct MoltbookUpdateProfileArgs {
872 #[arg(short, long)]
874 pub description: Option<String>,
875}
876
877#[derive(Parser, Debug)]
878pub struct MoltbookPostArgs {
879 pub title: String,
881
882 #[arg(short, long)]
884 pub content: String,
885
886 #[arg(short, long, default_value = "general")]
888 pub submolt: String,
889}
890
891#[derive(Parser, Debug)]
892pub struct MoltbookCommentArgs {
893 pub post_id: String,
895
896 pub content: String,
898}
899
900#[derive(Parser, Debug)]
901pub struct MoltbookSearchArgs {
902 pub query: String,
904
905 #[arg(short, long, default_value = "10")]
907 pub limit: usize,
908}
909
910#[derive(Parser, Debug)]
911pub struct BenchmarkArgs {
912 #[arg(long, default_value = "benchmarks")]
914 pub prd_dir: String,
915
916 #[arg(short, long, value_delimiter = ',')]
918 pub models: Vec<String>,
919
920 #[arg(long)]
922 pub tier: Option<u8>,
923
924 #[arg(long)]
926 pub parallel: bool,
927
928 #[arg(long, default_value = "10")]
930 pub max_iterations: usize,
931
932 #[arg(long, default_value = "300")]
934 pub story_timeout: u64,
935
936 #[arg(short, long, default_value = "benchmark_results.json")]
938 pub output: String,
939
940 #[arg(long, default_value = "50.0")]
942 pub cost_ceiling: f64,
943
944 #[arg(long)]
946 pub submit_url: Option<String>,
947
948 #[arg(long, env = "BENCHMARK_API_KEY")]
950 pub submit_key: Option<String>,
951
952 #[arg(long)]
954 pub json: bool,
955}
956
957#[derive(Parser, Debug)]
958pub struct OkrArgs {
959 #[arg(value_parser = ["list", "status", "create", "runs", "export", "stats", "report"])]
961 pub action: String,
962
963 #[arg(short, long)]
965 pub id: Option<String>,
966
967 #[arg(short, long)]
969 pub title: Option<String>,
970
971 #[arg(short, long)]
973 pub description: Option<String>,
974
975 #[arg(long)]
977 pub target: Option<f64>,
978
979 #[arg(long, default_value = "%")]
981 pub unit: String,
982
983 #[arg(long)]
985 pub status: Option<String>,
986
987 #[arg(long)]
989 pub owner: Option<String>,
990
991 #[arg(long)]
993 pub json: bool,
994
995 #[arg(long)]
997 pub evidence: bool,
998}
999
1000#[derive(Parser, Debug)]
1001#[command(
1002 about = "OKR-governed autonomous opportunity scanner/executor",
1003 long_about = "Scan OKRs/KRs for high-priority opportunities and optionally execute the top selections with the build agent.",
1004 after_long_help = "Examples:\n codetether forage --top 5\n codetether forage --loop --interval-secs 600\n codetether forage --loop --execute --top 1 --interval-secs 600 --max-cycles 48 --run-timeout-secs 900 --model minimax/MiniMax-M2.5\n codetether forage --loop --execute --execution-engine swarm --swarm-max-subagents 8 --swarm-strategy auto --model zai/glm-5"
1005)]
1006pub struct ForageArgs {
1007 #[arg(long, default_value = "3")]
1009 pub top: usize,
1010
1011 #[arg(long = "loop")]
1013 pub loop_mode: bool,
1014
1015 #[arg(long, default_value = "120")]
1017 pub interval_secs: u64,
1018
1019 #[arg(long, default_value = "0")]
1021 pub max_cycles: usize,
1022
1023 #[arg(long)]
1025 pub execute: bool,
1026
1027 #[arg(long)]
1029 pub no_s3: bool,
1030
1031 #[arg(long = "moonshot")]
1035 pub moonshots: Vec<String>,
1036
1037 #[arg(long)]
1039 pub moonshot_file: Option<PathBuf>,
1040
1041 #[arg(long)]
1043 pub moonshot_required: bool,
1044
1045 #[arg(long, default_value = "0.10")]
1047 pub moonshot_min_alignment: f64,
1048
1049 #[arg(long, default_value = "run", value_parser = ["run", "swarm", "go"])]
1051 pub execution_engine: String,
1052
1053 #[arg(long, default_value = "900")]
1055 pub run_timeout_secs: u64,
1056
1057 #[arg(long)]
1059 pub fail_fast: bool,
1060
1061 #[arg(long, default_value = "auto", value_parser = ["auto", "domain", "data", "stage", "none"])]
1063 pub swarm_strategy: String,
1064
1065 #[arg(long, default_value = "8")]
1067 pub swarm_max_subagents: usize,
1068
1069 #[arg(long, default_value = "100")]
1071 pub swarm_max_steps: usize,
1072
1073 #[arg(long, default_value = "300")]
1075 pub swarm_subagent_timeout_secs: u64,
1076
1077 #[arg(short, long)]
1079 pub model: Option<String>,
1080
1081 #[arg(long)]
1083 pub json: bool,
1084}