use clap::{Parser, Subcommand, ValueEnum};
#[derive(Parser)]
#[command(
name = "diskard",
about = "Developer-aware disk cleanup CLI",
version,
long_about = "Scans your machine for reclaimable disk space from developer tools, \
build caches, AI models, and more."
)]
pub struct Cli {
#[command(subcommand)]
pub command: Option<Command>,
#[cfg(feature = "tui")]
#[arg(short = 'i', long = "interactive", global = true)]
pub interactive: bool,
#[arg(long, global = true, default_value = "table")]
pub format: OutputFormat,
#[arg(short, long, global = true)]
pub verbose: bool,
}
#[derive(Subcommand)]
pub enum Command {
Scan {
#[arg(long, short, default_value = "moderate")]
risk: RiskFilter,
#[arg(long)]
min_size: Option<String>,
#[arg(long, short)]
category: Option<CategoryFilter>,
#[arg(long, short, default_value = "size")]
sort: SortField,
#[arg(long)]
older_than: Option<String>,
},
Clean {
#[arg(long)]
dry_run: bool,
#[arg(long, conflicts_with = "permanent")]
trash: bool,
#[arg(long, conflicts_with = "trash")]
permanent: bool,
#[arg(long, short, default_value = "safe")]
risk: RiskFilter,
#[arg(long, short)]
category: Option<CategoryFilter>,
#[arg(long)]
older_than: Option<String>,
#[arg(short = 'y', long)]
yes: bool,
},
List {
#[command(subcommand)]
what: ListCommand,
},
Config {
#[command(subcommand)]
action: ConfigAction,
},
#[cfg(feature = "tui")]
Interactive {
#[arg(long, short, default_value = "moderate")]
risk: RiskFilter,
#[arg(long, short)]
category: Option<CategoryFilter>,
},
Completions {
shell: clap_complete::Shell,
},
}
#[derive(Subcommand)]
pub enum ListCommand {
Targets,
}
#[derive(Subcommand)]
pub enum ConfigAction {
Show,
Init,
Path,
}
#[derive(Clone, Copy, ValueEnum)]
pub enum RiskFilter {
Safe,
Moderate,
Risky,
}
impl RiskFilter {
pub fn to_risk_level(self) -> diskard_core::finding::RiskLevel {
match self {
Self::Safe => diskard_core::finding::RiskLevel::Safe,
Self::Moderate => diskard_core::finding::RiskLevel::Moderate,
Self::Risky => diskard_core::finding::RiskLevel::Risky,
}
}
}
#[derive(Clone, Copy, ValueEnum)]
pub enum OutputFormat {
Table,
Json,
}
#[derive(Clone, Copy, ValueEnum)]
pub enum CategoryFilter {
Xcode,
Node,
Homebrew,
Python,
Rust,
Docker,
Ollama,
Huggingface,
Claude,
Vscode,
Gradle,
Cocoapods,
Generic,
}
impl CategoryFilter {
pub fn to_category(self) -> diskard_core::finding::Category {
use diskard_core::finding::Category;
match self {
Self::Xcode => Category::Xcode,
Self::Node => Category::Node,
Self::Homebrew => Category::Homebrew,
Self::Python => Category::Python,
Self::Rust => Category::Rust,
Self::Docker => Category::Docker,
Self::Ollama => Category::Ollama,
Self::Huggingface => Category::HuggingFace,
Self::Claude => Category::Claude,
Self::Vscode => Category::VSCode,
Self::Gradle => Category::Gradle,
Self::Cocoapods => Category::CocoaPods,
Self::Generic => Category::Generic,
}
}
}
#[derive(Clone, Copy, ValueEnum)]
pub enum SortField {
Size,
Risk,
Category,
}
impl SortField {
pub fn to_sort_order(self) -> diskard_core::scanner::SortOrder {
use diskard_core::scanner::SortOrder;
match self {
Self::Size => SortOrder::Size,
Self::Risk => SortOrder::Risk,
Self::Category => SortOrder::Category,
}
}
}