lean_ctx/cli/
discover_cmd.rs1use super::common::load_shell_history;
2
3pub fn cmd_discover(_args: &[String]) {
4 let history = load_shell_history();
5 if history.is_empty() {
6 println!("No shell history found.");
7 return;
8 }
9
10 let result = crate::tools::ctx_discover::analyze_history(&history, 20);
11 println!("{}", crate::tools::ctx_discover::format_cli_output(&result));
12}
13
14pub fn cmd_ghost(args: &[String]) {
15 let json = args.iter().any(|a| a == "--json");
16
17 let history = load_shell_history();
18 let discover = crate::tools::ctx_discover::analyze_history(&history, 20);
19
20 let session = crate::core::session::SessionState::load_latest();
21 let store = crate::core::stats::load();
22
23 let unoptimized_tokens = discover.potential_tokens;
24 let _unoptimized_usd = discover.potential_usd;
25
26 let redundant_reads = store.cep.total_cache_hits as usize;
27 let redundant_tokens = redundant_reads * 200;
28
29 let wasted_original = store
30 .cep
31 .total_tokens_original
32 .saturating_sub(store.cep.total_tokens_compressed) as usize;
33 let truncated_tokens = wasted_original / 3;
34
35 let total_ghost = unoptimized_tokens + redundant_tokens + truncated_tokens;
36 let total_usd =
37 total_ghost as f64 * crate::core::stats::DEFAULT_INPUT_PRICE_PER_M / 1_000_000.0;
38 let monthly_usd = total_usd * 30.0;
39
40 if json {
41 let obj = serde_json::json!({
42 "ghost_tokens": total_ghost,
43 "breakdown": {
44 "unoptimized_shells": unoptimized_tokens,
45 "redundant_reads": redundant_tokens,
46 "truncated_contexts": truncated_tokens,
47 },
48 "estimated_usd": total_usd,
49 "monthly_usd": monthly_usd,
50 "session_active": session.is_some(),
51 "history_commands": discover.total_commands,
52 "already_optimized": discover.already_optimized,
53 });
54 println!("{}", serde_json::to_string_pretty(&obj).unwrap_or_default());
55 return;
56 }
57
58 let bold = "\x1b[1m";
59 let green = "\x1b[32m";
60 let yellow = "\x1b[33m";
61 let red = "\x1b[31m";
62 let dim = "\x1b[2m";
63 let rst = "\x1b[0m";
64 let white = "\x1b[97m";
65
66 println!();
67 println!(" {bold}{white}lean-ctx ghost report{rst}");
68 println!(" {dim}{}{rst}", "=".repeat(40));
69 println!();
70
71 if total_ghost == 0 {
72 println!(" {green}No ghost tokens detected!{rst}");
73 println!(
74 " {dim}All {} commands optimized.{rst}",
75 discover.total_commands
76 );
77 println!();
78 return;
79 }
80
81 let severity = if total_ghost > 10000 {
82 red
83 } else if total_ghost > 3000 {
84 yellow
85 } else {
86 green
87 };
88
89 println!(
90 " {bold}Ghost Tokens found:{rst} {severity}{total_ghost:>8}{rst} tokens {dim}(~${total_usd:.2}){rst}"
91 );
92 println!();
93
94 if unoptimized_tokens > 0 {
95 let missed_count: u32 = discover.missed_commands.iter().map(|m| m.count).sum();
96 println!(
97 " {dim} Unoptimized shells:{rst} {white}{unoptimized_tokens:>8}{rst} {dim}({missed_count} cmds without lean-ctx){rst}"
98 );
99 }
100 if redundant_tokens > 0 {
101 println!(
102 " {dim} Redundant reads:{rst} {white}{redundant_tokens:>8}{rst} {dim}({redundant_reads} cache hits = wasted re-reads){rst}"
103 );
104 }
105 if truncated_tokens > 0 {
106 println!(
107 " {dim} Oversized contexts:{rst} {white}{truncated_tokens:>8}{rst} {dim}(uncompressed portion of tool results){rst}"
108 );
109 }
110
111 println!();
112 println!(" {bold}Monthly savings potential:{rst} {green}${monthly_usd:.2}{rst}");
113
114 if !discover.missed_commands.is_empty() {
115 println!();
116 println!(" {bold}Top unoptimized commands:{rst}");
117 for m in discover.missed_commands.iter().take(5) {
118 println!(
119 " {dim}{:>4}x{rst} {white}{:<12}{rst} {dim}{}{rst}",
120 m.count, m.prefix, m.description
121 );
122 }
123 }
124
125 println!();
126 if discover.already_optimized == 0 {
127 println!(
128 " {yellow}Run '{bold}lean-ctx setup{rst}{yellow}' to eliminate ghost tokens.{rst}"
129 );
130 } else {
131 println!(
132 " {dim}Already optimized: {}/{} commands{rst}",
133 discover.already_optimized, discover.total_commands
134 );
135 }
136 println!();
137}