syncable_cli/cli.rs
1use clap::{Parser, Subcommand, ValueEnum};
2use std::path::PathBuf;
3
4#[derive(Parser)]
5#[command(name = "sync-ctl")]
6#[command(version = env!("CARGO_PKG_VERSION"))]
7#[command(about = "Generate Infrastructure as Code from your codebase")]
8#[command(
9 long_about = "A powerful CLI tool that analyzes your codebase and automatically generates optimized Infrastructure as Code configurations including Dockerfiles, Docker Compose files, and Terraform configurations"
10)]
11pub struct Cli {
12 #[command(subcommand)]
13 pub command: Commands,
14
15 /// Path to configuration file
16 #[arg(short, long, global = true, value_name = "FILE")]
17 pub config: Option<PathBuf>,
18
19 /// Enable verbose logging (-v for info, -vv for debug, -vvv for trace)
20 #[arg(short, long, global = true, action = clap::ArgAction::Count)]
21 pub verbose: u8,
22
23 /// Suppress all output except errors
24 #[arg(short, long, global = true)]
25 pub quiet: bool,
26
27 /// Output in JSON format where applicable
28 #[arg(long, global = true)]
29 pub json: bool,
30
31 /// Clear the update check cache and force a new check
32 #[arg(long, global = true)]
33 pub clear_update_cache: bool,
34
35 /// Disable telemetry data collection
36 #[arg(long, global = true)]
37 pub disable_telemetry: bool,
38}
39
40#[derive(Subcommand)]
41pub enum Commands {
42 /// Analyze a project and display detected components
43 Analyze {
44 /// Path to the project directory to analyze
45 #[arg(value_name = "PROJECT_PATH")]
46 path: PathBuf,
47
48 /// Output analysis results in JSON format
49 #[arg(short, long)]
50 json: bool,
51
52 /// Show detailed analysis information (legacy format)
53 #[arg(short, long, conflicts_with = "display")]
54 detailed: bool,
55
56 /// Display format for analysis results
57 #[arg(long, value_enum, default_value = "matrix")]
58 display: Option<DisplayFormat>,
59
60 /// Only analyze specific aspects (languages, frameworks, dependencies)
61 #[arg(long, value_delimiter = ',')]
62 only: Option<Vec<String>>,
63
64 /// Color scheme for terminal output (auto-detect, dark, light)
65 #[arg(long, value_enum, default_value = "auto")]
66 color_scheme: Option<ColorScheme>,
67 },
68
69 /// Generate IaC files for a project
70 Generate {
71 /// Path to the project directory to analyze
72 #[arg(value_name = "PROJECT_PATH")]
73 path: PathBuf,
74
75 /// Output directory for generated files
76 #[arg(short, long, value_name = "OUTPUT_DIR")]
77 output: Option<PathBuf>,
78
79 /// Generate Dockerfile
80 #[arg(long)]
81 dockerfile: bool,
82
83 /// Generate Docker Compose file
84 #[arg(long)]
85 compose: bool,
86
87 /// Generate Terraform configuration
88 #[arg(long)]
89 terraform: bool,
90
91 /// Generate all supported IaC files
92 #[arg(long, conflicts_with_all = ["dockerfile", "compose", "terraform"])]
93 all: bool,
94
95 /// Perform a dry run without creating files
96 #[arg(long)]
97 dry_run: bool,
98
99 /// Overwrite existing files
100 #[arg(long)]
101 force: bool,
102 },
103
104 /// Validate existing IaC files against best practices
105 Validate {
106 /// Path to the directory containing IaC files
107 #[arg(value_name = "PATH")]
108 path: PathBuf,
109
110 /// Types of files to validate
111 #[arg(long, value_delimiter = ',')]
112 types: Option<Vec<String>>,
113
114 /// Fix issues automatically where possible
115 #[arg(long)]
116 fix: bool,
117 },
118
119 /// Show supported languages and frameworks
120 Support {
121 /// Show only languages
122 #[arg(long)]
123 languages: bool,
124
125 /// Show only frameworks
126 #[arg(long)]
127 frameworks: bool,
128
129 /// Show detailed information
130 #[arg(short, long)]
131 detailed: bool,
132 },
133
134 /// Analyze project dependencies in detail
135 Dependencies {
136 /// Path to the project directory to analyze
137 #[arg(value_name = "PROJECT_PATH")]
138 path: PathBuf,
139
140 /// Show license information for dependencies
141 #[arg(long)]
142 licenses: bool,
143
144 /// Check for known vulnerabilities
145 #[arg(long)]
146 vulnerabilities: bool,
147
148 /// Show only production dependencies
149 #[arg(long, conflicts_with = "dev_only")]
150 prod_only: bool,
151
152 /// Show only development dependencies
153 #[arg(long, conflicts_with = "prod_only")]
154 dev_only: bool,
155
156 /// Output format
157 #[arg(long, value_enum, default_value = "table")]
158 format: OutputFormat,
159 },
160
161 /// Check dependencies for known vulnerabilities
162 Vulnerabilities {
163 /// Check vulnerabilities in a specific path
164 #[arg(default_value = ".")]
165 path: PathBuf,
166
167 /// Show only vulnerabilities with severity >= threshold
168 #[arg(long, value_enum)]
169 severity: Option<SeverityThreshold>,
170
171 /// Output format
172 #[arg(long, value_enum, default_value = "table")]
173 format: OutputFormat,
174
175 /// Export report to file
176 #[arg(long)]
177 output: Option<PathBuf>,
178 },
179
180 /// Perform comprehensive security analysis
181 Security {
182 /// Path to the project directory to analyze
183 #[arg(value_name = "PROJECT_PATH", default_value = ".")]
184 path: PathBuf,
185
186 /// Security scan mode (lightning, fast, balanced, thorough, paranoid)
187 #[arg(long, value_enum, default_value = "thorough")]
188 mode: SecurityScanMode,
189
190 /// Include low severity findings
191 #[arg(long)]
192 include_low: bool,
193
194 /// Skip secrets detection
195 #[arg(long)]
196 no_secrets: bool,
197
198 /// Skip code pattern analysis
199 #[arg(long)]
200 no_code_patterns: bool,
201
202 /// Skip infrastructure analysis (not implemented yet)
203 #[arg(long, hide = true)]
204 no_infrastructure: bool,
205
206 /// Skip compliance checks (not implemented yet)
207 #[arg(long, hide = true)]
208 no_compliance: bool,
209
210 /// Compliance frameworks to check (not implemented yet)
211 #[arg(long, value_delimiter = ',', hide = true)]
212 frameworks: Vec<String>,
213
214 /// Output format
215 #[arg(long, value_enum, default_value = "table")]
216 format: OutputFormat,
217
218 /// Export report to file
219 #[arg(long)]
220 output: Option<PathBuf>,
221
222 /// Exit with error code on security findings
223 #[arg(long)]
224 fail_on_findings: bool,
225 },
226
227 /// Manage vulnerability scanning tools
228 Tools {
229 #[command(subcommand)]
230 command: ToolsCommand,
231 },
232
233 /// Analyze Kubernetes manifests for resource optimization opportunities
234 Optimize {
235 /// Path to Kubernetes manifests (file or directory)
236 #[arg(value_name = "PATH", default_value = ".")]
237 path: PathBuf,
238
239 /// Connect to a live Kubernetes cluster for metrics-based recommendations
240 /// Uses current kubeconfig context, or specify a context name
241 #[arg(long, short = 'k', value_name = "CONTEXT", default_missing_value = "current", num_args = 0..=1)]
242 cluster: Option<String>,
243
244 /// Prometheus URL for historical metrics (e.g., http://localhost:9090)
245 #[arg(long, value_name = "URL")]
246 prometheus: Option<String>,
247
248 /// Target namespace(s) for cluster analysis (comma-separated, or * for all)
249 #[arg(long, short = 'n', value_name = "NAMESPACE")]
250 namespace: Option<String>,
251
252 /// Analysis period for historical metrics (e.g., 7d, 30d)
253 #[arg(long, short = 'p', default_value = "7d")]
254 period: String,
255
256 /// Minimum severity to report (critical, warning, info)
257 #[arg(long, short = 's')]
258 severity: Option<String>,
259
260 /// Minimum waste percentage threshold (0-100)
261 #[arg(long, short = 't')]
262 threshold: Option<u8>,
263
264 /// Safety margin percentage for recommendations (default: 20)
265 #[arg(long)]
266 safety_margin: Option<u8>,
267
268 /// Include info-level suggestions
269 #[arg(long)]
270 include_info: bool,
271
272 /// Include system namespaces (kube-system, etc.)
273 #[arg(long)]
274 include_system: bool,
275
276 /// Output format (table, json, yaml)
277 #[arg(long, value_enum, default_value = "table")]
278 format: OutputFormat,
279
280 /// Write report to file
281 #[arg(long, short = 'o')]
282 output: Option<PathBuf>,
283
284 /// Generate fix suggestions
285 #[arg(long)]
286 fix: bool,
287
288 /// Apply fixes to manifest files (requires --fix or --full with live cluster)
289 #[arg(long, requires = "fix")]
290 apply: bool,
291
292 /// Preview changes without applying (dry-run mode)
293 #[arg(long)]
294 dry_run: bool,
295
296 /// Backup directory for original files before applying fixes
297 #[arg(long, value_name = "DIR")]
298 backup_dir: Option<PathBuf>,
299
300 /// Minimum confidence threshold for auto-apply (0-100, default: 70)
301 #[arg(long, default_value = "70")]
302 min_confidence: u8,
303
304 /// Cloud provider for cost estimation (aws, gcp, azure, onprem)
305 #[arg(long, value_name = "PROVIDER")]
306 cloud_provider: Option<String>,
307
308 /// Region for cloud pricing (e.g., us-east-1, us-central1)
309 #[arg(long, value_name = "REGION", default_value = "us-east-1")]
310 region: String,
311
312 /// Run comprehensive analysis (includes kubelint security checks and helmlint validation)
313 #[arg(long, short = 'f')]
314 full: bool,
315 },
316
317 /// Start an interactive AI chat session to analyze and understand your project
318 Chat {
319 /// Path to the project directory (default: current directory)
320 #[arg(value_name = "PROJECT_PATH", default_value = ".")]
321 path: PathBuf,
322
323 /// LLM provider to use (uses saved preference by default)
324 #[arg(long, value_enum, default_value = "auto")]
325 provider: ChatProvider,
326
327 /// Model to use (e.g., gpt-4o, claude-3-5-sonnet-latest, llama3.2)
328 #[arg(long)]
329 model: Option<String>,
330
331 /// Run a single query instead of interactive mode
332 #[arg(long)]
333 query: Option<String>,
334
335 /// Resume a previous session (accepts: "latest", session number, or UUID)
336 #[arg(long, short = 'r')]
337 resume: Option<String>,
338
339 /// List available sessions for this project and exit
340 #[arg(long)]
341 list_sessions: bool,
342
343 /// Start AG-UI server for frontend connectivity (SSE/WebSocket)
344 #[arg(long)]
345 ag_ui: bool,
346
347 /// AG-UI server port (default: 9090)
348 #[arg(long, default_value = "9090", requires = "ag_ui")]
349 ag_ui_port: u16,
350 },
351
352 /// Authenticate with the Syncable platform
353 Auth {
354 #[command(subcommand)]
355 command: AuthCommand,
356 },
357
358 /// Manage Syncable projects
359 Project {
360 #[command(subcommand)]
361 command: ProjectCommand,
362 },
363
364 /// Manage Syncable organizations
365 Org {
366 #[command(subcommand)]
367 command: OrgCommand,
368 },
369
370 /// Manage environments within a project
371 Env {
372 #[command(subcommand)]
373 command: EnvCommand,
374 },
375
376 /// Deploy services to the Syncable platform (launches wizard by default)
377 Deploy {
378 /// Path to the project directory (default: current directory)
379 #[arg(value_name = "PROJECT_PATH", default_value = ".")]
380 path: PathBuf,
381
382 #[command(subcommand)]
383 command: Option<DeployCommand>,
384 },
385
386 /// Run as dedicated AG-UI agent server (headless mode for containers)
387 Agent {
388 /// Path to the project directory
389 #[arg(value_name = "PROJECT_PATH", default_value = ".")]
390 path: PathBuf,
391
392 /// Port for AG-UI server
393 #[arg(long, short, default_value = "9090")]
394 port: u16,
395
396 /// Host address to bind to
397 #[arg(long, default_value = "127.0.0.1")]
398 host: String,
399
400 /// LLM provider to use
401 #[arg(long, value_enum, default_value = "auto")]
402 provider: ChatProvider,
403
404 /// Model to use
405 #[arg(long)]
406 model: Option<String>,
407 },
408}
409
410#[derive(Subcommand)]
411pub enum ToolsCommand {
412 /// Check which vulnerability scanning tools are installed
413 Status {
414 /// Output format
415 #[arg(long, value_enum, default_value = "table")]
416 format: OutputFormat,
417
418 /// Check tools for specific languages only
419 #[arg(long, value_delimiter = ',')]
420 languages: Option<Vec<String>>,
421 },
422
423 /// Install missing vulnerability scanning tools
424 Install {
425 /// Install tools for specific languages only
426 #[arg(long, value_delimiter = ',')]
427 languages: Option<Vec<String>>,
428
429 /// Also install OWASP Dependency Check (large download)
430 #[arg(long)]
431 include_owasp: bool,
432
433 /// Perform a dry run to show what would be installed
434 #[arg(long)]
435 dry_run: bool,
436
437 /// Skip confirmation prompts
438 #[arg(short, long)]
439 yes: bool,
440 },
441
442 /// Verify that installed tools are working correctly
443 Verify {
444 /// Test tools for specific languages only
445 #[arg(long, value_delimiter = ',')]
446 languages: Option<Vec<String>>,
447
448 /// Show detailed verification output
449 #[arg(short, long)]
450 detailed: bool,
451 },
452
453 /// Show tool installation guides for manual setup
454 Guide {
455 /// Show guide for specific languages only
456 #[arg(long, value_delimiter = ',')]
457 languages: Option<Vec<String>>,
458
459 /// Show platform-specific instructions
460 #[arg(long)]
461 platform: Option<String>,
462 },
463}
464
465/// Authentication subcommands for the Syncable platform
466#[derive(Subcommand)]
467pub enum AuthCommand {
468 /// Log in to Syncable (opens browser for authentication)
469 Login {
470 /// Don't open browser automatically
471 #[arg(long)]
472 no_browser: bool,
473 },
474
475 /// Log out and clear stored credentials
476 Logout,
477
478 /// Show current authentication status
479 Status,
480
481 /// Print current access token (for scripting)
482 Token {
483 /// Print raw token without formatting
484 #[arg(long)]
485 raw: bool,
486 },
487}
488
489/// Project management subcommands
490#[derive(Subcommand)]
491pub enum ProjectCommand {
492 /// List projects in the current organization
493 List {
494 /// Organization ID to list projects from (uses current org if not specified)
495 #[arg(long)]
496 org_id: Option<String>,
497
498 /// Output format
499 #[arg(long, value_enum, default_value = "table")]
500 format: OutputFormat,
501 },
502
503 /// Select a project to work with
504 Select {
505 /// Project ID to select
506 id: String,
507 },
508
509 /// Show current organization and project context
510 Current,
511
512 /// Show details of a project
513 Info {
514 /// Project ID (uses current project if not specified)
515 id: Option<String>,
516 },
517}
518
519/// Organization management subcommands
520#[derive(Subcommand)]
521pub enum OrgCommand {
522 /// List organizations you belong to
523 List {
524 /// Output format
525 #[arg(long, value_enum, default_value = "table")]
526 format: OutputFormat,
527 },
528
529 /// Select an organization to work with
530 Select {
531 /// Organization ID to select
532 id: String,
533 },
534}
535
536/// Environment management subcommands
537#[derive(Subcommand)]
538pub enum EnvCommand {
539 /// List environments in the current project
540 List {
541 /// Output format
542 #[arg(long, value_enum, default_value = "table")]
543 format: OutputFormat,
544 },
545
546 /// Select an environment to work with
547 Select {
548 /// Environment ID to select
549 id: String,
550 },
551}
552
553/// Deployment subcommands
554#[derive(Subcommand)]
555pub enum DeployCommand {
556 /// Launch interactive deployment wizard
557 Wizard {
558 /// Path to the project directory (default: current directory)
559 #[arg(value_name = "PROJECT_PATH", default_value = ".")]
560 path: PathBuf,
561 },
562
563 /// Create a new environment for the current project
564 NewEnv,
565
566 /// Check deployment status
567 Status {
568 /// The deployment task ID (from deploy command output)
569 task_id: String,
570
571 /// Watch for status updates (poll until complete)
572 #[arg(short, long)]
573 watch: bool,
574 },
575}
576
577#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
578pub enum OutputFormat {
579 Table,
580 Json,
581}
582
583#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
584pub enum DisplayFormat {
585 /// Compact matrix/dashboard view (modern, easy to scan)
586 Matrix,
587 /// Detailed vertical view (legacy format with all details)
588 Detailed,
589 /// Brief summary only
590 Summary,
591}
592
593#[derive(Clone, Copy, Debug, ValueEnum)]
594pub enum ColorScheme {
595 /// Auto-detect terminal background (default)
596 Auto,
597 /// Dark background terminal colors
598 Dark,
599 /// Light background terminal colors
600 Light,
601}
602
603#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
604pub enum SeverityThreshold {
605 Low,
606 Medium,
607 High,
608 Critical,
609}
610
611#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
612pub enum SecurityScanMode {
613 /// Lightning fast scan - critical files only (.env, configs)
614 Lightning,
615 /// Fast scan - smart sampling with priority patterns
616 Fast,
617 /// Balanced scan - good coverage with performance optimizations (recommended)
618 Balanced,
619 /// Thorough scan - comprehensive analysis of all files
620 Thorough,
621 /// Paranoid scan - most comprehensive including low-severity findings
622 Paranoid,
623}
624
625#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum, Default)]
626pub enum ChatProvider {
627 /// OpenAI (GPT-4o, GPT-4, etc.)
628 Openai,
629 /// Anthropic (Claude 3)
630 Anthropic,
631 /// AWS Bedrock (Claude via AWS)
632 Bedrock,
633 /// Ollama (local LLM, no API key needed)
634 Ollama,
635 /// Use saved default from config file
636 #[default]
637 Auto,
638}
639
640impl Cli {
641 /// Initialize logging based on verbosity level
642 pub fn init_logging(&self) {
643 if self.quiet {
644 return;
645 }
646
647 let level = match self.verbose {
648 0 => log::LevelFilter::Warn,
649 1 => log::LevelFilter::Info,
650 2 => log::LevelFilter::Debug,
651 _ => log::LevelFilter::Trace,
652 };
653
654 env_logger::Builder::from_default_env()
655 .filter_level(level)
656 .init();
657 }
658}