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
use clap::{Parser, Subcommand, ValueEnum};
use std::path::PathBuf;
#[derive(Parser, Debug)]
#[command(
name = "mycop",
version,
about = "AI Code Security Scanner — detect vulnerabilities in AI-generated code",
long_about = "mycop scans your codebase for security vulnerabilities using pattern matching,\n\
AST analysis, and optional AI-powered explanations and fix suggestions.\n\n\
Designed to catch the security issues that AI coding assistants commonly introduce."
)]
pub struct Cli {
#[command(subcommand)]
pub command: Commands,
}
#[derive(Subcommand, Debug)]
pub enum Commands {
/// Scan files or directories for security vulnerabilities
Scan {
/// Files or directories to scan (defaults to current directory)
#[arg(default_value = ".")]
paths: Vec<PathBuf>,
/// Get AI-powered explanations for each finding
#[arg(long)]
explain: bool,
/// Auto-fix all security vulnerabilities using AI (same as `mycop fix`)
#[arg(long)]
fix: bool,
/// Output format
#[arg(long, value_enum, default_value = "terminal")]
format: OutputFormat,
/// Minimum severity level to report
#[arg(long, value_enum)]
severity: Option<SeverityFilter>,
/// Minimum severity to fail with exit code 1 (default: high)
#[arg(long, value_enum)]
fail_on: Option<SeverityFilter>,
/// Only scan files changed in git diff
#[arg(long)]
diff: bool,
/// Override AI provider selection
#[arg(long, value_enum)]
ai_provider: Option<AiProviderChoice>,
/// Path to config file
#[arg(long)]
config: Option<PathBuf>,
},
/// Auto-fix security vulnerabilities using AI (rewrites files)
Fix {
/// Files or directories to fix (defaults to current directory)
#[arg(default_value = ".")]
paths: Vec<PathBuf>,
/// Minimum severity level to fix
#[arg(long, value_enum)]
severity: Option<SeverityFilter>,
/// Show what would change without writing files
#[arg(long)]
dry_run: bool,
/// Override AI provider selection
#[arg(long, value_enum)]
ai_provider: Option<AiProviderChoice>,
/// Only fix files changed in git diff
#[arg(long)]
diff: bool,
},
/// Deep AI security review of a file
Review {
/// File to review
file: PathBuf,
/// Override AI provider selection
#[arg(long, value_enum)]
ai_provider: Option<AiProviderChoice>,
},
/// Initialize a .scanrc.yml config file
Init,
/// Manage security rules
Rules {
#[command(subcommand)]
action: RulesAction,
},
/// Check dependencies for issues
Deps {
#[command(subcommand)]
action: DepsAction,
},
/// Start MCP server for agentic tool integration (Claude Code, Cursor, Windsurf, etc.)
Mcp,
}
#[derive(Subcommand, Debug)]
pub enum RulesAction {
/// List all available security rules
List {
/// Filter by language
#[arg(long)]
language: Option<String>,
/// Filter by severity
#[arg(long, value_enum)]
severity: Option<SeverityFilter>,
},
}
#[derive(Subcommand, Debug)]
pub enum DepsAction {
/// Check for hallucinated or non-existent packages
Check {
/// Path to requirements.txt, package.json, etc.
#[arg(default_value = ".")]
path: PathBuf,
},
}
#[derive(ValueEnum, Clone, Debug, PartialEq)]
pub enum OutputFormat {
Terminal,
Json,
Sarif,
}
#[derive(ValueEnum, Clone, Debug, PartialEq, PartialOrd)]
pub enum SeverityFilter {
Low,
Medium,
High,
Critical,
}
#[derive(ValueEnum, Clone, Debug)]
pub enum AiProviderChoice {
ClaudeCli,
Anthropic,
Openai,
Ollama,
None,
}