use clap::{Args, Parser, Subcommand};
#[derive(Parser, Debug)]
#[command(name = "cargo", bin_name = "cargo", version)]
pub struct Cargo {
#[command(subcommand)]
pub command: CargoCommand,
}
#[derive(Subcommand, Debug)]
pub enum CargoCommand {
Brief(BriefDirect),
}
#[derive(Parser, Debug)]
#[command(
version,
about = "Visibility-aware Rust API extractor for AI agents",
after_help = "Run `cargo brief <subcommand> --help` for subcommand-specific options."
)]
pub struct BriefDirect {
#[command(subcommand)]
pub command: BriefCommand,
}
#[derive(Subcommand, Debug, Clone)]
pub enum BriefCommand {
#[command(after_help = "\
EXAMPLES:
# Browse the current crate's API (run inside a Cargo project)
cargo brief api
# Browse a specific module in the current crate
cargo brief api self::net::tcp
# Inspect a crates.io dependency (cached after first run)
cargo brief api --crates serde@1 --compact
cargo brief api --crates tokio@1 --features rt,net,io-util
# Browse a specific module of a remote crate
cargo brief api --crates tokio@1 --features net tokio::net
# Reduce output verbosity for large crates
cargo brief api --crates tokio@1 --features full --compact
cargo brief api --crates tokio@1 --features full --doc-lines 1
RESOLUTION RULES:
The <TARGET> argument is resolved as follows:
1. \"self\" → current package (cwd-based detection)
2. \"self::mod\" → current package, specific module
3. \"crate::mod\" → named crate + module in one argument
4. \"src/foo.rs\" → file path auto-converted to module path
5. \"crate_name\" → workspace package (hyphen/underscore normalized)
6. \"unknown_name\" → treated as package name (use \"self::mod\" for modules)
The [MODULE_PATH] argument also accepts file paths (e.g., src/foo.rs).")]
Api(ApiArgs),
#[command(after_help = "\
EXAMPLES:
# Search for items by name (smart-case: lowercase=insensitive, uppercase=sensitive)
cargo brief search --crates axum@0.8 \"Router route\"
# List all methods/fields of a type
cargo brief search --crates bytes@1 --methods-of Bytes
# OR-match with comma: find items matching either term
cargo brief search self \"EventReader,EventWriter\"
SEARCH MATCHING:
Smart-case: all-lowercase pattern → case-insensitive, any uppercase → case-sensitive.
Space-separated words are AND-matched: \"World spawn\" finds items whose path contains both.
Comma-separated terms are OR-matched: \"Foo,Bar\" finds items matching either.
Comma splits into OR groups; within each group, spaces are AND.
Example: \"World spawn,despawn\" matches paths containing (World AND spawn) OR (despawn).
OUTPUT:
One line per match with full path prefix:
fn module::Type::method(&self, arg: T) -> Ret;
struct module::StructName;
field module::Struct::field_name: Type;
variant module::Enum::Variant(T1, T2);")]
Search(SearchArgs),
Examples(ExamplesArgs),
}
#[derive(Args, Debug, Clone)]
pub struct TargetArgs {
#[arg(value_name = "TARGET", default_value = "self")]
pub crate_name: String,
pub module_path: Option<String>,
#[arg(long, help_heading = "Local Workspace")]
pub at_package: Option<String>,
#[arg(long, help_heading = "Local Workspace")]
pub at_mod: Option<String>,
#[arg(long, help_heading = "Local Workspace")]
pub manifest_path: Option<String>,
}
#[derive(Args, Debug, Clone)]
pub struct RemoteArgs {
#[arg(long, value_name = "SPEC", help_heading = "Remote Crate (crates.io)")]
pub crates: Option<String>,
#[arg(
long,
value_name = "FEATURES",
help_heading = "Remote Crate (crates.io)"
)]
pub features: Option<String>,
#[arg(long, help_heading = "Remote Crate (crates.io)")]
pub no_cache: bool,
#[arg(
long,
value_name = "SPEC",
num_args = 0..=1,
default_missing_value = "",
help_heading = "Remote Crate (crates.io)"
)]
pub clean: Option<String>,
}
#[derive(Args, Debug, Clone)]
pub struct FilterArgs {
#[arg(long, help_heading = "Filtering")]
pub no_structs: bool,
#[arg(long, help_heading = "Filtering")]
pub no_enums: bool,
#[arg(long, help_heading = "Filtering")]
pub no_traits: bool,
#[arg(long, help_heading = "Filtering")]
pub no_functions: bool,
#[arg(long, help_heading = "Filtering")]
pub no_aliases: bool,
#[arg(long, help_heading = "Filtering")]
pub no_constants: bool,
#[arg(long, help_heading = "Filtering")]
pub no_unions: bool,
#[arg(long, help_heading = "Filtering")]
pub no_macros: bool,
#[arg(long, help_heading = "Filtering")]
pub no_docs: bool,
#[arg(long, help_heading = "Filtering")]
pub no_crate_docs: bool,
#[arg(long, value_name = "N", help_heading = "Filtering")]
pub doc_lines: Option<usize>,
#[arg(long, help_heading = "Filtering")]
pub compact: bool,
#[arg(long, help_heading = "Filtering")]
pub verbose_metadata: bool,
#[arg(long)]
pub all: bool,
}
#[derive(Args, Debug, Clone)]
pub struct GlobalArgs {
#[arg(long, default_value = "nightly", help_heading = "Advanced")]
pub toolchain: String,
#[arg(short, long)]
pub verbose: bool,
}
#[derive(Args, Debug, Clone)]
pub struct ApiArgs {
#[command(flatten)]
pub target: TargetArgs,
#[command(flatten)]
pub remote: RemoteArgs,
#[command(flatten)]
pub filter: FilterArgs,
#[command(flatten)]
pub global: GlobalArgs,
#[arg(long, default_value = "1")]
pub depth: u32,
#[arg(long)]
pub recursive: bool,
#[arg(long)]
pub expand_glob: bool,
}
#[derive(Args, Debug, Clone)]
pub struct SearchArgs {
#[arg(value_name = "TARGET", default_value = "self")]
pub crate_name: String,
#[arg(default_value = "")]
pub pattern: String,
#[command(flatten)]
pub remote: RemoteArgs,
#[command(flatten)]
pub filter: FilterArgs,
#[command(flatten)]
pub global: GlobalArgs,
#[arg(long, help_heading = "Local Workspace")]
pub at_package: Option<String>,
#[arg(long, help_heading = "Local Workspace")]
pub at_mod: Option<String>,
#[arg(long, help_heading = "Local Workspace")]
pub manifest_path: Option<String>,
#[arg(long, value_name = "[OFFSET:]N")]
pub limit: Option<String>,
#[arg(long, value_name = "TYPE")]
pub methods_of: Option<String>,
}
#[derive(Args, Debug, Clone)]
pub struct ExamplesArgs {
#[arg(value_name = "TARGET", default_value = "self")]
pub crate_name: String,
pub pattern: Option<String>,
#[command(flatten)]
pub remote: RemoteArgs,
#[command(flatten)]
pub global: GlobalArgs,
#[arg(long, help_heading = "Local Workspace")]
pub manifest_path: Option<String>,
#[arg(long, default_value = "2")]
pub context: String,
#[arg(long)]
pub include_tests: bool,
}