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
use clap::{Args, Parser, Subcommand};
use std::path::PathBuf;
#[derive(Parser, Debug)]
#[command(
name = "cargo-depflame",
about = "Visualize and optimize your Cargo dependency tree",
version
)]
pub struct Cli {
/// When invoked as `cargo depflame`, cargo passes
/// "depflame" as the first positional arg. We consume it here.
#[arg(hide = true, required = false)]
_subcommand_name: Option<String>,
#[command(subcommand)]
pub command: Option<Command>,
}
#[derive(Subcommand, Debug)]
pub enum Command {
/// Analyze the workspace dependency graph and generate a report.
Analyze(AnalyzeArgs),
/// Re-render a previously saved JSON analysis.
Report(ReportArgs),
/// Analyze and open an interactive HTML report in the default browser.
Flame(FlameArgs),
}
/// Arguments shared between Analyze and Flame commands.
#[derive(Args, Debug, Clone)]
pub struct CommonArgs {
/// Path to the workspace Cargo.toml.
#[arg(long, default_value = "Cargo.toml")]
pub manifest_path: PathBuf,
/// Analyze a crate from crates.io instead of a local workspace.
/// Accepts: crate name (e.g. "serde"), name@version (e.g. "serde@1.0.228"),
/// or a crates.io URL (e.g. "https://crates.io/crates/serde").
#[arg(long = "crate", value_name = "SPEC")]
pub crate_spec: Option<String>,
/// Minimum hURRS score to include in the report.
#[arg(long, default_value_t = 3.0)]
pub threshold: f64,
/// Show only the top N results.
#[arg(long, default_value_t = 10)]
pub top: usize,
/// Minimum transitive weight for a node to be considered "heavy".
#[arg(long, default_value_t = 10)]
pub heavy_threshold: usize,
/// Show detailed analysis (file matches, dep chains, metrics).
#[arg(long, short)]
pub verbose: bool,
/// Include noise-level results (phantom deps, sibling-required, FFI wrappers).
#[arg(long)]
pub include_noise: bool,
}
impl Default for CommonArgs {
fn default() -> Self {
Self {
manifest_path: PathBuf::from("Cargo.toml"),
crate_spec: None,
threshold: 3.0,
top: 10,
heavy_threshold: 10,
verbose: false,
include_noise: false,
}
}
}
#[derive(Parser, Debug)]
pub struct AnalyzeArgs {
#[command(flatten)]
pub common: CommonArgs,
/// Output format.
#[arg(long, default_value = "text")]
pub format: OutputFormat,
/// Write report to a file instead of stdout.
#[arg(long)]
pub output: Option<PathBuf>,
}
#[derive(Parser, Debug)]
pub struct ReportArgs {
/// Path to a previously saved JSON analysis.
#[arg(long)]
pub input: PathBuf,
/// Output format.
#[arg(long, default_value = "text")]
pub format: OutputFormat,
/// Write report to a file instead of stdout.
#[arg(long)]
pub output: Option<PathBuf>,
/// Show detailed analysis (file matches, dep chains, metrics).
#[arg(long, short)]
pub verbose: bool,
}
#[derive(Args, Debug, Default)]
pub struct FlameArgs {
#[command(flatten)]
pub common: CommonArgs,
}
#[derive(Debug, Clone, clap::ValueEnum)]
pub enum OutputFormat {
Text,
Json,
/// Self-contained HTML report with flamegraph, targets table, and JSON.
Html,
}