use std::path::PathBuf;
use clap::{Parser, Subcommand, ValueEnum};
use clap_complete::Shell;
#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
pub enum ColorChoice {
Auto,
Always,
Never,
}
#[derive(Parser, Debug)]
#[command(
name = "devpulse",
version,
about = "Take the pulse of your dev environment"
)]
#[command(propagate_version = true, arg_required_else_help = false)]
#[command(long_about = "devpulse — Developer diagnostics CLI\n\n\
A single binary with 6 subcommands:\n \
http HTTP request timing visualizer\n \
sweep Build artifact scanner & cleaner\n \
doctor Dev environment health checker\n \
ports Listening port inspector\n \
env Environment variable analyzer\n \
convert Config format converter\n\n\
All commands support --json for CI/scripting.\n\
Respects NO_COLOR environment variable.")]
pub struct Cli {
#[command(subcommand)]
pub command: Option<Commands>,
#[arg(
long,
global = true,
help = "Output as JSON for scripting and CI pipelines"
)]
pub json: bool,
#[arg(
long,
global = true,
default_value = "auto",
help = "Color output: auto, always, never"
)]
pub color: ColorChoice,
}
#[derive(Subcommand, Debug)]
pub enum Commands {
#[command(
long_about = "HTTP request timing visualizer with colored phase breakdown.\n\n\
Shows DNS lookup, TCP connection, TLS handshake, server processing,\n\
and content transfer times with colored bars and cumulative labels.\n\n\
Examples:\n \
devpulse http https://httpbin.org/get\n \
devpulse http -X POST -d '{\"key\":\"val\"}' https://api.example.com\n \
devpulse http -H 'Authorization: Bearer tok' https://api.example.com"
)]
Http {
#[arg(help = "URL to request (http:// or https://)")]
url: String,
#[arg(
short = 'X',
long,
default_value = "GET",
help = "HTTP method (GET, POST, PUT, DELETE, etc.)"
)]
method: String,
#[arg(
short = 'H',
long = "header",
help = "Header in 'Key: Value' format (repeatable)"
)]
headers: Vec<String>,
#[arg(short = 'd', long = "data", help = "Request body data")]
data: Option<String>,
},
#[command(
long_about = "Scan and clean build artifacts across all languages.\n\n\
Finds node_modules/, target/, __pycache__/, .venv/, .next/, .gradle/,\n\
and more. Shows sizes with color coding, supports selective deletion.\n\n\
Examples:\n \
devpulse sweep\n \
devpulse sweep ~/projects\n \
devpulse sweep -y --min-size 100M ~/projects"
)]
Sweep {
#[arg(help = "Root directory to scan (defaults to current directory)")]
path: Option<PathBuf>,
#[arg(short = 'y', long, help = "Delete all without confirmation")]
yes: bool,
#[arg(long, default_value = "1M", help = "Minimum size filter: 1M, 500K, 2G")]
min_size: String,
},
#[command(long_about = "Check developer environment health.\n\n\
Runs checks for Git, Node.js, Rust, Python, Docker, disk space,\n\
and SSH keys. Shows pass/warn/fail status for each.\n\n\
Examples:\n \
devpulse doctor\n \
devpulse doctor --json")]
Doctor,
#[command(long_about = "Show listening ports and their processes.\n\n\
Lists all TCP ports currently in LISTEN state with the process\n\
name and PID. Optionally filter to a specific port number.\n\n\
Examples:\n \
devpulse ports\n \
devpulse ports 3000\n \
devpulse ports --json")]
Ports {
#[arg(help = "Filter to specific port number")]
port: Option<u16>,
#[arg(
long = "scan-range",
help = "Scan custom port range: START-END (e.g., 1-1024)"
)]
scan_range: Option<String>,
},
#[command(long_about = "Inspect developer environment variables and PATH.\n\n\
Analyzes PATH entries (missing dirs, duplicates, tool locations),\n\
shows dev tool variables, proxy settings, and CI detection.\n\n\
Examples:\n \
devpulse env\n \
devpulse env path\n \
devpulse env proxy\n \
devpulse env --json")]
Env {
#[arg(help = "Filter: 'path', 'proxy', 'ci', or regex pattern")]
filter: Option<String>,
},
#[command(
long_about = "Convert config files between JSON, YAML, TOML, and .env formats.\n\n\
Reads a config file, detects the input format (by extension or --from flag),\n\
and converts it to the target format. Dot-flattening is used for .env output.\n\n\
Examples:\n \
devpulse convert config.json --to yaml\n \
devpulse convert settings.yaml --to toml\n \
devpulse convert .env --to json\n \
devpulse convert data.toml --to env -o .env.local"
)]
Convert {
#[arg(help = "Input config file (json, yaml, toml, or .env)")]
input: String,
#[arg(long, help = "Target format: json, yaml, toml, env")]
to: String,
#[arg(long, help = "Source format (auto-detected from extension if omitted)")]
from: Option<String>,
#[arg(short = 'o', long = "output", help = "Write output to file instead of stdout")]
output: Option<String>,
},
#[command(hide = true)]
Completions {
#[arg(help = "Shell: bash, zsh, fish, powershell, elvish")]
shell: Shell,
},
}
#[cfg(test)]
mod tests {
use clap::CommandFactory;
#[test]
fn verify_cli() {
super::Cli::command().debug_assert();
}
}