1pub mod auth;
4pub mod config;
5pub mod context;
6pub mod go_ralph;
7pub mod oracle;
8pub mod run;
9pub mod search;
10pub mod search_render;
11
12use clap::{Parser, Subcommand};
13use std::path::PathBuf;
14
15#[derive(Parser, Debug)]
20#[command(name = "codetether")]
21#[command(version, about, long_about = None)]
22pub struct Cli {
23 #[arg(global = true, last = true)]
25 pub project: Option<PathBuf>,
26
27 #[arg(long, global = true)]
29 pub print_logs: bool,
30
31 #[arg(long, global = true, value_parser = ["DEBUG", "INFO", "WARN", "ERROR"])]
33 pub log_level: Option<String>,
34
35 #[arg(short, long, env = "CODETETHER_SERVER")]
38 pub server: Option<String>,
39
40 #[arg(short, long, env = "CODETETHER_TOKEN")]
42 pub token: Option<String>,
43
44 #[arg(short, long, env = "CODETETHER_WORKER_NAME")]
46 pub name: Option<String>,
47
48 #[command(subcommand)]
49 pub command: Option<Command>,
50}
51
52#[derive(Subcommand, Debug)]
53pub enum Command {
54 Tui(TuiArgs),
56
57 Serve(ServeArgs),
59
60 Run(RunArgs),
62
63 Pr(PrArgs),
65
66 Auth(AuthArgs),
68
69 Config(ConfigArgs),
71
72 Context(ContextArgs),
74
75 Worker(A2aArgs),
77
78 #[command(hide = true)]
80 GitCredentialHelper(GitCredentialHelperArgs),
81
82 Spawn(SpawnArgs),
84
85 Swarm(SwarmArgs),
87
88 #[command(hide = true)]
90 SwarmSubagent(SwarmSubagentArgs),
91
92 Rlm(RlmArgs),
94
95 Oracle(OracleArgs),
97
98 Ralph(RalphArgs),
100
101 Mcp(McpArgs),
103
104 Stats(StatsArgs),
106
107 Cleanup(CleanupArgs),
109
110 Models(ModelsArgs),
112
113 Index(IndexArgs),
115
116 Benchmark(BenchmarkArgs),
118
119 Moltbook(MoltbookArgs),
121
122 Okr(OkrArgs),
124
125 Forage(ForageArgs),
127
128 Search(SearchArgs),
130}
131
132#[derive(Parser, Debug)]
133pub struct AuthArgs {
134 #[command(subcommand)]
135 pub command: AuthCommand,
136}
137
138#[derive(Subcommand, Debug)]
139pub enum AuthCommand {
140 Copilot(CopilotAuthArgs),
142
143 Codex(CodexAuthArgs),
145
146 Cookies(CookieAuthArgs),
148
149 Register(RegisterAuthArgs),
151
152 Login(LoginAuthArgs),
154}
155
156#[derive(Parser, Debug)]
157pub struct RegisterAuthArgs {
158 #[arg(short, long, env = "CODETETHER_SERVER")]
160 pub server: String,
161
162 #[arg(short, long)]
164 pub email: Option<String>,
165
166 #[arg(long)]
168 pub first_name: Option<String>,
169
170 #[arg(long)]
172 pub last_name: Option<String>,
173
174 #[arg(long)]
176 pub referral_source: Option<String>,
177}
178
179#[derive(Parser, Debug)]
180pub struct LoginAuthArgs {
181 #[arg(short, long, env = "CODETETHER_SERVER")]
183 pub server: String,
184
185 #[arg(short, long)]
187 pub email: Option<String>,
188}
189
190#[derive(Parser, Debug)]
191pub struct CopilotAuthArgs {
192 #[arg(long)]
194 pub enterprise_url: Option<String>,
195
196 #[arg(long, env = "CODETETHER_COPILOT_OAUTH_CLIENT_ID")]
198 pub client_id: Option<String>,
199}
200
201#[derive(Parser, Debug)]
202pub struct CodexAuthArgs {
203 #[arg(long, default_value_t = false)]
205 pub device_code: bool,
206}
207
208#[derive(Parser, Debug)]
209pub struct CookieAuthArgs {
210 #[arg(long, default_value = "nextdoor-web")]
212 pub provider: String,
213
214 #[arg(long)]
216 pub file: PathBuf,
217
218 #[arg(long, default_value_t = false)]
220 pub keep_all: bool,
221}
222
223#[derive(Parser, Debug)]
224pub struct TuiArgs {
225 pub project: Option<PathBuf>,
227
228 #[arg(long)]
230 pub allow_network: bool,
231}
232
233#[derive(Parser, Debug)]
234pub struct ServeArgs {
235 #[arg(short, long, default_value = "4096")]
237 pub port: u16,
238
239 #[arg(long, default_value = "127.0.0.1")]
241 pub hostname: String,
242
243 #[arg(long)]
245 pub mdns: bool,
246}
247
248#[derive(Parser, Debug)]
249pub struct RunArgs {
250 pub message: String,
252
253 #[arg(short, long)]
255 pub continue_session: bool,
256
257 #[arg(short, long)]
259 pub session: Option<String>,
260
261 #[arg(short, long)]
263 pub model: Option<String>,
264
265 #[arg(long)]
267 pub agent: Option<String>,
268
269 #[arg(long, default_value = "default", value_parser = ["default", "json"])]
271 pub format: String,
272
273 #[arg(short, long)]
275 pub file: Vec<PathBuf>,
276
277 #[arg(long)]
279 pub codex_session: Option<String>,
280
281 #[arg(long)]
283 pub max_steps: Option<usize>,
284}
285
286#[derive(Parser, Debug)]
287pub struct PrArgs {
288 #[command(subcommand)]
289 pub command: PrCommand,
290}
291
292#[derive(Subcommand, Debug)]
293pub enum PrCommand {
294 Create(CreatePrArgs),
296}
297
298#[derive(Parser, Debug, Clone)]
299pub struct CreatePrArgs {
300 #[arg(long)]
302 pub title: String,
303
304 #[arg(long)]
306 pub body: Option<String>,
307
308 #[arg(long)]
310 pub body_file: Option<PathBuf>,
311
312 #[arg(long, default_value = "main")]
314 pub base: String,
315
316 #[arg(long)]
318 pub head: Option<String>,
319
320 #[arg(long, default_value_t = false)]
322 pub draft: bool,
323
324 #[arg(long, default_value_t = false)]
326 pub json: bool,
327
328 #[arg(long)]
330 pub project: Option<PathBuf>,
331}
332
333#[derive(Parser, Debug, Clone)]
335pub struct WorkerServerArgs {
336 #[arg(long, default_value = "0.0.0.0")]
338 pub hostname: String,
339
340 #[arg(short, long, default_value = "8080")]
342 pub port: u16,
343}
344
345#[derive(Parser, Debug, Clone)]
346pub struct A2aArgs {
347 #[arg(short, long, env = "CODETETHER_SERVER", default_value = crate::a2a::worker::DEFAULT_A2A_SERVER_URL)]
349 pub server: String,
350
351 #[arg(short, long, env = "CODETETHER_TOKEN")]
353 pub token: Option<String>,
354
355 #[arg(short, long, env = "CODETETHER_WORKER_NAME")]
357 pub name: Option<String>,
358
359 #[arg(short, long, visible_alias = "codebases")]
361 pub workspaces: Option<String>,
362
363 #[arg(
365 long,
366 env = "CODETETHER_WORKER_MAX_CONCURRENT_TASKS",
367 default_value_t = 4
368 )]
369 pub max_concurrent_tasks: usize,
370
371 #[arg(long, default_value = "safe", value_parser = ["all", "safe", "none"])]
373 pub auto_approve: String,
374
375 #[arg(short, long)]
377 pub email: Option<String>,
378
379 #[arg(long)]
381 pub push_url: Option<String>,
382
383 #[arg(long, default_value = "0.0.0.0", env = "CODETETHER_WORKER_HOST")]
385 pub hostname: String,
386
387 #[arg(long, default_value = "8080", env = "CODETETHER_WORKER_PORT")]
389 pub port: u16,
390
391 #[arg(long, env = "CODETETHER_WORKER_PUBLIC_URL")]
393 pub public_url: Option<String>,
394
395 #[arg(long, env = "CODETETHER_WORKER_HTTP_DISABLED")]
397 pub no_http_server: bool,
398}
399
400#[derive(Parser, Debug, Clone)]
401pub struct GitCredentialHelperArgs {
402 #[arg(long = "workspace-id", alias = "codebase-id")]
404 pub workspace_id: String,
405
406 #[arg(long, env = "CODETETHER_SERVER")]
408 pub server: Option<String>,
409
410 #[arg(long, env = "CODETETHER_TOKEN")]
412 pub token: Option<String>,
413
414 #[arg(long, env = "CODETETHER_WORKER_ID")]
416 pub worker_id: Option<String>,
417
418 pub operation: Option<String>,
420}
421
422#[derive(Parser, Debug, Clone)]
423pub struct SpawnArgs {
424 #[arg(short, long)]
426 pub name: Option<String>,
427
428 #[arg(long, default_value = "127.0.0.1")]
430 pub hostname: String,
431
432 #[arg(short, long, default_value = "4097")]
434 pub port: u16,
435
436 #[arg(long)]
438 pub public_url: Option<String>,
439
440 #[arg(short, long)]
442 pub description: Option<String>,
443
444 #[arg(long, value_delimiter = ',', env = "CODETETHER_A2A_PEERS")]
446 pub peer: Vec<String>,
447
448 #[arg(long, default_value = "15")]
450 pub discovery_interval_secs: u64,
451
452 #[arg(long = "no-auto-introduce", action = clap::ArgAction::SetFalse, default_value_t = true)]
454 pub auto_introduce: bool,
455}
456
457#[derive(Parser, Debug)]
458pub struct ConfigArgs {
459 #[arg(long)]
461 pub show: bool,
462
463 #[arg(long)]
465 pub init: bool,
466
467 #[arg(long)]
469 pub set: Option<String>,
470}
471
472#[derive(Parser, Debug)]
473pub struct ContextArgs {
474 #[command(subcommand)]
475 pub command: ContextCommand,
476}
477
478#[derive(Subcommand, Debug)]
479pub enum ContextCommand {
480 Reset(ContextResetArgs),
482 Browse(ContextBrowseArgs),
484}
485
486#[derive(Parser, Debug)]
487pub struct ContextResetArgs {
488 #[arg(long)]
490 pub summary: Option<String>,
491}
492
493#[derive(Parser, Debug)]
494pub struct ContextBrowseArgs {
495 #[command(subcommand)]
496 pub command: Option<ContextBrowseCommand>,
497}
498
499#[derive(Subcommand, Debug)]
500pub enum ContextBrowseCommand {
501 List,
503 ShowTurn(ContextShowTurnArgs),
505}
506
507#[derive(Parser, Debug)]
508pub struct ContextShowTurnArgs {
509 pub turn: usize,
511}
512
513#[derive(Parser, Debug)]
514pub struct SwarmArgs {
515 pub task: String,
517
518 #[arg(short, long)]
520 pub model: Option<String>,
521
522 #[arg(short = 's', long, default_value = "auto")]
524 pub strategy: String,
525
526 #[arg(long, default_value = "100")]
528 pub max_subagents: usize,
529
530 #[arg(long, default_value = "100")]
532 pub max_steps: usize,
533
534 #[arg(long, default_value = "300")]
536 pub timeout: u64,
537
538 #[arg(long)]
540 pub json: bool,
541
542 #[arg(long, default_value = "local", value_parser = ["local", "k8s", "kubernetes", "kubernetes-pod", "pod"])]
544 pub execution_mode: String,
545
546 #[arg(long, default_value = "8")]
548 pub k8s_pod_budget: usize,
549
550 #[arg(long)]
552 pub k8s_image: Option<String>,
553}
554
555#[derive(Parser, Debug)]
556pub struct SwarmSubagentArgs {
557 #[arg(long)]
559 pub payload_base64: Option<String>,
560
561 #[arg(long, default_value = "CODETETHER_SWARM_SUBTASK_PAYLOAD")]
563 pub payload_env: String,
564}
565
566#[derive(Parser, Debug)]
567pub struct RlmArgs {
568 pub query: String,
570
571 #[arg(short, long)]
573 pub model: Option<String>,
574
575 #[arg(short, long)]
577 pub file: Vec<PathBuf>,
578
579 #[arg(long)]
581 pub content: Option<String>,
582
583 #[arg(long, default_value = "auto")]
585 pub content_type: String,
586
587 #[arg(long, default_value = "4000")]
589 pub max_tokens: usize,
590
591 #[arg(long)]
593 pub json: bool,
594
595 #[arg(short, long)]
597 pub verbose: bool,
598
599 #[arg(long)]
601 pub oracle_verify: bool,
602
603 #[arg(long)]
605 pub no_oracle_verify: bool,
606
607 #[arg(long, default_value = "1")]
609 pub consensus_runs: usize,
610
611 #[arg(long, default_value = "1.0")]
613 pub consensus_threshold: f32,
614
615 #[arg(long)]
617 pub analysis_temperature: Option<f32>,
618
619 #[arg(long)]
621 pub oracle_out_dir: Option<PathBuf>,
622
623 #[arg(long, default_value = "rlm_oracle")]
625 pub oracle_prefix: String,
626}
627
628#[derive(Parser, Debug)]
629pub struct OracleArgs {
630 #[command(subcommand)]
631 pub command: OracleCommand,
632}
633
634#[derive(Subcommand, Debug)]
635pub enum OracleCommand {
636 Validate(OracleValidateArgs),
638 Sync(OracleSyncArgs),
640}
641
642#[derive(Parser, Debug)]
643pub struct OracleValidateArgs {
644 #[arg(long)]
646 pub query: String,
647
648 #[arg(short, long)]
650 pub file: Option<PathBuf>,
651
652 #[arg(long)]
654 pub content: Option<String>,
655
656 #[arg(long)]
658 pub payload: Option<String>,
659
660 #[arg(long)]
662 pub payload_file: Option<PathBuf>,
663
664 #[arg(long)]
666 pub json: bool,
667
668 #[arg(long)]
670 pub persist: bool,
671}
672
673#[derive(Parser, Debug)]
674pub struct OracleSyncArgs {
675 #[arg(long)]
677 pub json: bool,
678}
679
680#[derive(Parser, Debug)]
681pub struct RalphArgs {
682 #[arg(value_parser = ["run", "status", "create-prd"])]
684 pub action: String,
685
686 #[arg(short, long, default_value = "prd.json")]
688 pub prd: PathBuf,
689
690 #[arg(short, long)]
692 pub feature: Option<String>,
693
694 #[arg(long = "project-name")]
696 pub project_name: Option<String>,
697
698 #[arg(long, default_value = "10")]
700 pub max_iterations: usize,
701
702 #[arg(short, long)]
704 pub model: Option<String>,
705
706 #[arg(long)]
708 pub json: bool,
709}
710
711#[derive(Parser, Debug)]
712pub struct McpArgs {
713 #[arg(value_parser = ["serve", "connect", "list-tools", "call"])]
715 pub action: String,
716
717 #[arg(short, long)]
719 pub command: Option<String>,
720
721 #[arg(long)]
723 pub server_name: Option<String>,
724
725 #[arg(long)]
727 pub tool: Option<String>,
728
729 #[arg(long)]
731 pub arguments: Option<String>,
732
733 #[arg(long)]
735 pub json: bool,
736
737 #[arg(long)]
739 pub worker_id: Option<String>,
740
741 #[arg(long)]
743 pub workspace_id: Option<String>,
744
745 #[arg(long)]
750 pub bus_url: Option<String>,
751
752 #[arg(allow_hyphen_values = true)]
755 pub command_args: Vec<String>,
756}
757
758#[derive(Parser, Debug)]
759pub struct StatsArgs {
760 #[arg(short, long)]
762 pub tools: bool,
763
764 #[arg(short, long)]
766 pub files: bool,
767
768 #[arg(long)]
770 pub tokens: bool,
771
772 #[arg(long)]
774 pub tool: Option<String>,
775
776 #[arg(long)]
778 pub file: Option<String>,
779
780 #[arg(short, long, default_value = "20")]
782 pub limit: usize,
783
784 #[arg(long)]
786 pub json: bool,
787
788 #[arg(long)]
790 pub all: bool,
791}
792
793#[derive(Parser, Debug)]
794pub struct CleanupArgs {
795 #[arg(short, long)]
797 pub dry_run: bool,
798
799 #[arg(long)]
801 pub worktrees_only: bool,
802
803 #[arg(long)]
805 pub json: bool,
806}
807
808#[derive(Parser, Debug)]
809pub struct ModelsArgs {
810 #[arg(short, long)]
812 pub provider: Option<String>,
813
814 #[arg(long)]
816 pub json: bool,
817}
818
819#[derive(Parser, Debug)]
820pub struct IndexArgs {
821 #[arg(short, long)]
823 pub path: Option<PathBuf>,
824
825 #[arg(short, long)]
827 pub output: Option<PathBuf>,
828
829 #[arg(long, default_value = "1024")]
831 pub max_file_size_kib: u64,
832
833 #[arg(long, default_value = "hash-v1")]
835 pub embedding_model: String,
836
837 #[arg(long, default_value = "local")]
839 pub embedding_provider: String,
840
841 #[arg(long, default_value = "384")]
843 pub embedding_dimensions: usize,
844
845 #[arg(long, default_value = "32")]
847 pub embedding_batch_size: usize,
848
849 #[arg(long, default_value = "3")]
851 pub embedding_max_retries: u32,
852
853 #[arg(long, default_value = "250")]
855 pub embedding_retry_initial_ms: u64,
856
857 #[arg(long, default_value = "2000")]
859 pub embedding_retry_max_ms: u64,
860
861 #[arg(long, default_value = "8000")]
863 pub embedding_input_chars: usize,
864
865 #[arg(long, default_value_t = false)]
867 pub include_hidden: bool,
868
869 #[arg(long)]
871 pub json: bool,
872}
873
874#[derive(Parser, Debug)]
875pub struct MoltbookArgs {
876 #[command(subcommand)]
877 pub command: MoltbookCommand,
878}
879
880#[derive(Subcommand, Debug)]
881pub enum MoltbookCommand {
882 Register(MoltbookRegisterArgs),
884
885 Status,
887
888 Profile,
890
891 UpdateProfile(MoltbookUpdateProfileArgs),
893
894 Post(MoltbookPostArgs),
896
897 Intro,
899
900 Heartbeat,
902
903 Comment(MoltbookCommentArgs),
905
906 Search(MoltbookSearchArgs),
908}
909
910#[derive(Parser, Debug)]
911pub struct MoltbookRegisterArgs {
912 pub name: String,
914
915 #[arg(short, long)]
917 pub description: Option<String>,
918}
919
920#[derive(Parser, Debug)]
921pub struct MoltbookUpdateProfileArgs {
922 #[arg(short, long)]
924 pub description: Option<String>,
925}
926
927#[derive(Parser, Debug)]
928pub struct MoltbookPostArgs {
929 pub title: String,
931
932 #[arg(short, long)]
934 pub content: String,
935
936 #[arg(short, long, default_value = "general")]
938 pub submolt: String,
939}
940
941#[derive(Parser, Debug)]
942pub struct MoltbookCommentArgs {
943 pub post_id: String,
945
946 pub content: String,
948}
949
950#[derive(Parser, Debug)]
951pub struct MoltbookSearchArgs {
952 pub query: String,
954
955 #[arg(short, long, default_value = "10")]
957 pub limit: usize,
958}
959
960#[derive(Parser, Debug)]
961pub struct BenchmarkArgs {
962 #[arg(long, default_value = "benchmarks")]
964 pub prd_dir: String,
965
966 #[arg(short, long, value_delimiter = ',')]
968 pub models: Vec<String>,
969
970 #[arg(long)]
972 pub tier: Option<u8>,
973
974 #[arg(long)]
976 pub parallel: bool,
977
978 #[arg(long, default_value = "10")]
980 pub max_iterations: usize,
981
982 #[arg(long, default_value = "300")]
984 pub story_timeout: u64,
985
986 #[arg(short, long, default_value = "benchmark_results.json")]
988 pub output: String,
989
990 #[arg(long, default_value = "50.0")]
992 pub cost_ceiling: f64,
993
994 #[arg(long)]
996 pub submit_url: Option<String>,
997
998 #[arg(long, env = "BENCHMARK_API_KEY")]
1000 pub submit_key: Option<String>,
1001
1002 #[arg(long)]
1004 pub json: bool,
1005}
1006
1007#[derive(Parser, Debug)]
1008pub struct OkrArgs {
1009 #[arg(value_parser = ["list", "status", "create", "runs", "export", "stats", "report"])]
1011 pub action: String,
1012
1013 #[arg(short, long)]
1015 pub id: Option<String>,
1016
1017 #[arg(short, long)]
1019 pub title: Option<String>,
1020
1021 #[arg(short, long)]
1023 pub description: Option<String>,
1024
1025 #[arg(long)]
1027 pub target: Option<f64>,
1028
1029 #[arg(long, default_value = "%")]
1031 pub unit: String,
1032
1033 #[arg(long)]
1035 pub status: Option<String>,
1036
1037 #[arg(long)]
1039 pub owner: Option<String>,
1040
1041 #[arg(long)]
1043 pub json: bool,
1044
1045 #[arg(long)]
1047 pub evidence: bool,
1048}
1049
1050#[derive(Parser, Debug)]
1051#[command(
1052 about = "LLM-routed search across grep/glob/web/memory/RLM backends",
1053 long_about = "Uses the configured LLM router (default zai/glm-5.1) to pick the best search backend for your query, runs it, and returns normalized results.",
1054 after_long_help = "Examples:\n codetether search \"where is fn main\"\n codetether search --json \"how to center a div\"\n codetether search --top-n 3 --router-model zai/glm-5.1 \"latest rust async trait docs\""
1055)]
1056pub struct SearchArgs {
1057 pub query: String,
1059
1060 #[arg(long, default_value = "1")]
1062 pub top_n: usize,
1063
1064 #[arg(long)]
1066 pub router_model: Option<String>,
1067
1068 #[arg(long)]
1070 pub json: bool,
1071}
1072
1073#[derive(Parser, Debug)]
1074#[command(
1075 about = "OKR-governed autonomous opportunity scanner/executor",
1076 long_about = "Scan OKRs/KRs for high-priority opportunities and optionally execute the top selections with the build agent.",
1077 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"
1078)]
1079pub struct ForageArgs {
1080 #[arg(long, default_value = "3")]
1082 pub top: usize,
1083
1084 #[arg(long = "loop")]
1086 pub loop_mode: bool,
1087
1088 #[arg(long, default_value = "120")]
1090 pub interval_secs: u64,
1091
1092 #[arg(long, default_value = "0")]
1094 pub max_cycles: usize,
1095
1096 #[arg(long)]
1098 pub execute: bool,
1099
1100 #[arg(long)]
1102 pub no_s3: bool,
1103
1104 #[arg(long = "moonshot")]
1108 pub moonshots: Vec<String>,
1109
1110 #[arg(long)]
1112 pub moonshot_file: Option<PathBuf>,
1113
1114 #[arg(long)]
1116 pub moonshot_required: bool,
1117
1118 #[arg(long, default_value = "0.10")]
1120 pub moonshot_min_alignment: f64,
1121
1122 #[arg(long, default_value = "run", value_parser = ["run", "swarm", "go"])]
1124 pub execution_engine: String,
1125
1126 #[arg(long, default_value = "900")]
1128 pub run_timeout_secs: u64,
1129
1130 #[arg(long)]
1132 pub fail_fast: bool,
1133
1134 #[arg(long, default_value = "auto", value_parser = ["auto", "domain", "data", "stage", "none"])]
1136 pub swarm_strategy: String,
1137
1138 #[arg(long, default_value = "8")]
1140 pub swarm_max_subagents: usize,
1141
1142 #[arg(long, default_value = "100")]
1144 pub swarm_max_steps: usize,
1145
1146 #[arg(long, default_value = "300")]
1148 pub swarm_subagent_timeout_secs: u64,
1149
1150 #[arg(short, long)]
1152 pub model: Option<String>,
1153
1154 #[arg(long)]
1156 pub json: bool,
1157}