1use anyhow::Result;
2
3use crate::{
4 core, dashboard, doctor, heatmap, hook_handlers, mcp_stdio, report, setup, shell, status,
5 tools, tui, uninstall,
6};
7
8pub fn run(args: Vec<String>) {
9 if args.len() > 1 {
10 let rest = args[2..].to_vec();
11
12 match args[1].as_str() {
13 "-c" | "exec" => {
14 let raw = rest.first().map(|a| a == "--raw").unwrap_or(false);
15 let cmd_args = if raw { &args[3..] } else { &args[2..] };
16 let command = if cmd_args.len() == 1 {
17 cmd_args[0].clone()
18 } else {
19 shell::join_command(cmd_args)
20 };
21 if std::env::var("LEAN_CTX_ACTIVE").is_ok()
22 || std::env::var("LEAN_CTX_DISABLED").is_ok()
23 {
24 passthrough(&command);
25 }
26 if raw {
27 std::env::set_var("LEAN_CTX_RAW", "1");
28 } else {
29 std::env::set_var("LEAN_CTX_COMPRESS", "1");
30 }
31 let code = shell::exec(&command);
32 core::stats::flush();
33 std::process::exit(code);
34 }
35 "shell" | "--shell" => {
36 shell::interactive();
37 return;
38 }
39 "gain" => {
40 if rest.iter().any(|a| a == "--reset") {
41 core::stats::reset_all();
42 println!("Stats reset. All token savings data cleared.");
43 return;
44 }
45 if rest.iter().any(|a| a == "--live" || a == "--watch") {
46 core::stats::gain_live();
47 return;
48 }
49 let model = rest.iter().enumerate().find_map(|(i, a)| {
50 if let Some(v) = a.strip_prefix("--model=") {
51 return Some(v.to_string());
52 }
53 if a == "--model" {
54 return rest.get(i + 1).cloned();
55 }
56 None
57 });
58 let period = rest
59 .iter()
60 .enumerate()
61 .find_map(|(i, a)| {
62 if let Some(v) = a.strip_prefix("--period=") {
63 return Some(v.to_string());
64 }
65 if a == "--period" {
66 return rest.get(i + 1).cloned();
67 }
68 None
69 })
70 .unwrap_or_else(|| "all".to_string());
71 let limit = rest
72 .iter()
73 .enumerate()
74 .find_map(|(i, a)| {
75 if let Some(v) = a.strip_prefix("--limit=") {
76 return v.parse::<usize>().ok();
77 }
78 if a == "--limit" {
79 return rest.get(i + 1).and_then(|v| v.parse::<usize>().ok());
80 }
81 None
82 })
83 .unwrap_or(10);
84
85 if rest.iter().any(|a| a == "--graph") {
86 println!("{}", core::stats::format_gain_graph());
87 } else if rest.iter().any(|a| a == "--daily") {
88 println!("{}", core::stats::format_gain_daily());
89 } else if rest.iter().any(|a| a == "--json") {
90 println!(
91 "{}",
92 tools::ctx_gain::handle(
93 "json",
94 Some(&period),
95 model.as_deref(),
96 Some(limit)
97 )
98 );
99 } else if rest.iter().any(|a| a == "--score") {
100 println!(
101 "{}",
102 tools::ctx_gain::handle("score", None, model.as_deref(), Some(limit))
103 );
104 } else if rest.iter().any(|a| a == "--cost") {
105 println!(
106 "{}",
107 tools::ctx_gain::handle("cost", None, model.as_deref(), Some(limit))
108 );
109 } else if rest.iter().any(|a| a == "--tasks") {
110 println!(
111 "{}",
112 tools::ctx_gain::handle("tasks", None, None, Some(limit))
113 );
114 } else if rest.iter().any(|a| a == "--agents") {
115 println!(
116 "{}",
117 tools::ctx_gain::handle("agents", None, None, Some(limit))
118 );
119 } else if rest.iter().any(|a| a == "--heatmap") {
120 println!(
121 "{}",
122 tools::ctx_gain::handle("heatmap", None, None, Some(limit))
123 );
124 } else if rest.iter().any(|a| a == "--wrapped") {
125 println!(
126 "{}",
127 tools::ctx_gain::handle(
128 "wrapped",
129 Some(&period),
130 model.as_deref(),
131 Some(limit)
132 )
133 );
134 } else if rest.iter().any(|a| a == "--deep") {
135 println!(
136 "{}\n{}\n{}\n{}\n{}",
137 tools::ctx_gain::handle("report", None, model.as_deref(), Some(limit)),
138 tools::ctx_gain::handle("tasks", None, None, Some(limit)),
139 tools::ctx_gain::handle("cost", None, model.as_deref(), Some(limit)),
140 tools::ctx_gain::handle("agents", None, None, Some(limit)),
141 tools::ctx_gain::handle("heatmap", None, None, Some(limit))
142 );
143 } else {
144 println!(
145 "{}",
146 tools::ctx_gain::handle("report", None, model.as_deref(), Some(limit))
147 );
148 }
149 return;
150 }
151 "token-report" | "report-tokens" => {
152 let code = crate::token_report::run_cli(&rest);
153 if code != 0 {
154 std::process::exit(code);
155 }
156 return;
157 }
158 "cep" => {
159 println!("{}", tools::ctx_gain::handle("score", None, None, Some(10)));
160 return;
161 }
162 "dashboard" => {
163 let port = rest
164 .iter()
165 .find_map(|p| p.strip_prefix("--port=").or_else(|| p.strip_prefix("-p=")))
166 .and_then(|p| p.parse().ok());
167 let host = rest
168 .iter()
169 .find_map(|p| p.strip_prefix("--host=").or_else(|| p.strip_prefix("-H=")))
170 .map(String::from);
171 run_async(dashboard::start(port, host));
172 return;
173 }
174 "serve" => {
175 #[cfg(feature = "http-server")]
176 {
177 let mut cfg = crate::http_server::HttpServerConfig::default();
178 let mut i = 0;
179 while i < rest.len() {
180 match rest[i].as_str() {
181 "--host" | "-H" => {
182 i += 1;
183 if i < rest.len() {
184 cfg.host = rest[i].clone();
185 }
186 }
187 arg if arg.starts_with("--host=") => {
188 cfg.host = arg["--host=".len()..].to_string();
189 }
190 "--port" | "-p" => {
191 i += 1;
192 if i < rest.len() {
193 if let Ok(p) = rest[i].parse::<u16>() {
194 cfg.port = p;
195 }
196 }
197 }
198 arg if arg.starts_with("--port=") => {
199 if let Ok(p) = arg["--port=".len()..].parse::<u16>() {
200 cfg.port = p;
201 }
202 }
203 "--project-root" => {
204 i += 1;
205 if i < rest.len() {
206 cfg.project_root = std::path::PathBuf::from(&rest[i]);
207 }
208 }
209 arg if arg.starts_with("--project-root=") => {
210 cfg.project_root =
211 std::path::PathBuf::from(&arg["--project-root=".len()..]);
212 }
213 "--auth-token" => {
214 i += 1;
215 if i < rest.len() {
216 cfg.auth_token = Some(rest[i].clone());
217 }
218 }
219 arg if arg.starts_with("--auth-token=") => {
220 cfg.auth_token = Some(arg["--auth-token=".len()..].to_string());
221 }
222 "--stateful" => cfg.stateful_mode = true,
223 "--stateless" => cfg.stateful_mode = false,
224 "--json" => cfg.json_response = true,
225 "--sse" => cfg.json_response = false,
226 "--disable-host-check" => cfg.disable_host_check = true,
227 "--allowed-host" => {
228 i += 1;
229 if i < rest.len() {
230 cfg.allowed_hosts.push(rest[i].clone());
231 }
232 }
233 arg if arg.starts_with("--allowed-host=") => {
234 cfg.allowed_hosts
235 .push(arg["--allowed-host=".len()..].to_string());
236 }
237 "--max-body-bytes" => {
238 i += 1;
239 if i < rest.len() {
240 if let Ok(n) = rest[i].parse::<usize>() {
241 cfg.max_body_bytes = n;
242 }
243 }
244 }
245 arg if arg.starts_with("--max-body-bytes=") => {
246 if let Ok(n) = arg["--max-body-bytes=".len()..].parse::<usize>() {
247 cfg.max_body_bytes = n;
248 }
249 }
250 "--max-concurrency" => {
251 i += 1;
252 if i < rest.len() {
253 if let Ok(n) = rest[i].parse::<usize>() {
254 cfg.max_concurrency = n;
255 }
256 }
257 }
258 arg if arg.starts_with("--max-concurrency=") => {
259 if let Ok(n) = arg["--max-concurrency=".len()..].parse::<usize>() {
260 cfg.max_concurrency = n;
261 }
262 }
263 "--max-rps" => {
264 i += 1;
265 if i < rest.len() {
266 if let Ok(n) = rest[i].parse::<u32>() {
267 cfg.max_rps = n;
268 }
269 }
270 }
271 arg if arg.starts_with("--max-rps=") => {
272 if let Ok(n) = arg["--max-rps=".len()..].parse::<u32>() {
273 cfg.max_rps = n;
274 }
275 }
276 "--rate-burst" => {
277 i += 1;
278 if i < rest.len() {
279 if let Ok(n) = rest[i].parse::<u32>() {
280 cfg.rate_burst = n;
281 }
282 }
283 }
284 arg if arg.starts_with("--rate-burst=") => {
285 if let Ok(n) = arg["--rate-burst=".len()..].parse::<u32>() {
286 cfg.rate_burst = n;
287 }
288 }
289 "--request-timeout-ms" => {
290 i += 1;
291 if i < rest.len() {
292 if let Ok(n) = rest[i].parse::<u64>() {
293 cfg.request_timeout_ms = n;
294 }
295 }
296 }
297 arg if arg.starts_with("--request-timeout-ms=") => {
298 if let Ok(n) = arg["--request-timeout-ms=".len()..].parse::<u64>() {
299 cfg.request_timeout_ms = n;
300 }
301 }
302 "--help" | "-h" => {
303 eprintln!(
304 "Usage: lean-ctx serve [--host H] [--port N] [--project-root DIR]\\n\\
305 \\n\\
306 Options:\\n\\
307 --host, -H Bind host (default: 127.0.0.1)\\n\\
308 --port, -p Bind port (default: 8080)\\n\\
309 --project-root Resolve relative paths against this root (default: cwd)\\n\\
310 --auth-token Require Authorization: Bearer <token> (required for non-loopback binds)\\n\\
311 --stateful/--stateless Streamable HTTP session mode (default: stateless)\\n\\
312 --json/--sse Response framing in stateless mode (default: json)\\n\\
313 --max-body-bytes Max request body size in bytes (default: 2097152)\\n\\
314 --max-concurrency Max concurrent requests (default: 32)\\n\\
315 --max-rps Max requests/sec (global, default: 50)\\n\\
316 --rate-burst Rate limiter burst (global, default: 100)\\n\\
317 --request-timeout-ms REST tool-call timeout (default: 30000)\\n\\
318 --allowed-host Add allowed Host header (repeatable)\\n\\
319 --disable-host-check Disable Host header validation (unsafe)"
320 );
321 return;
322 }
323 _ => {}
324 }
325 i += 1;
326 }
327
328 if cfg.auth_token.is_none() {
329 if let Ok(v) = std::env::var("LEAN_CTX_HTTP_TOKEN") {
330 if !v.trim().is_empty() {
331 cfg.auth_token = Some(v);
332 }
333 }
334 }
335
336 if let Err(e) = run_async(crate::http_server::serve(cfg)) {
337 eprintln!("HTTP server error: {e}");
338 std::process::exit(1);
339 }
340 return;
341 }
342 #[cfg(not(feature = "http-server"))]
343 {
344 eprintln!("lean-ctx serve is not available in this build");
345 std::process::exit(1);
346 }
347 }
348 "watch" => {
349 if let Err(e) = tui::run() {
350 eprintln!("TUI error: {e}");
351 std::process::exit(1);
352 }
353 return;
354 }
355 "init" => {
356 super::cmd_init(&rest);
357 return;
358 }
359 "setup" => {
360 let non_interactive = rest.iter().any(|a| a == "--non-interactive");
361 let yes = rest.iter().any(|a| a == "--yes" || a == "-y");
362 let fix = rest.iter().any(|a| a == "--fix");
363 let json = rest.iter().any(|a| a == "--json");
364
365 if non_interactive || fix || json || yes {
366 let opts = setup::SetupOptions {
367 non_interactive,
368 yes,
369 fix,
370 json,
371 };
372 match setup::run_setup_with_options(opts) {
373 Ok(report) => {
374 if json {
375 println!(
376 "{}",
377 serde_json::to_string_pretty(&report)
378 .unwrap_or_else(|_| "{}".to_string())
379 );
380 }
381 if !report.success {
382 std::process::exit(1);
383 }
384 }
385 Err(e) => {
386 eprintln!("{e}");
387 std::process::exit(1);
388 }
389 }
390 } else {
391 setup::run_setup();
392 }
393 return;
394 }
395 "bootstrap" => {
396 let json = rest.iter().any(|a| a == "--json");
397 let opts = setup::SetupOptions {
398 non_interactive: true,
399 yes: true,
400 fix: true,
401 json,
402 };
403 match setup::run_setup_with_options(opts) {
404 Ok(report) => {
405 if json {
406 println!(
407 "{}",
408 serde_json::to_string_pretty(&report)
409 .unwrap_or_else(|_| "{}".to_string())
410 );
411 }
412 if !report.success {
413 std::process::exit(1);
414 }
415 }
416 Err(e) => {
417 eprintln!("{e}");
418 std::process::exit(1);
419 }
420 }
421 return;
422 }
423 "status" => {
424 let code = status::run_cli(&rest);
425 if code != 0 {
426 std::process::exit(code);
427 }
428 return;
429 }
430 "read" => {
431 super::cmd_read(&rest);
432 return;
433 }
434 "diff" => {
435 super::cmd_diff(&rest);
436 return;
437 }
438 "grep" => {
439 super::cmd_grep(&rest);
440 return;
441 }
442 "find" => {
443 super::cmd_find(&rest);
444 return;
445 }
446 "ls" => {
447 super::cmd_ls(&rest);
448 return;
449 }
450 "deps" => {
451 super::cmd_deps(&rest);
452 return;
453 }
454 "discover" => {
455 super::cmd_discover(&rest);
456 return;
457 }
458 "filter" => {
459 super::cmd_filter(&rest);
460 return;
461 }
462 "heatmap" => {
463 heatmap::cmd_heatmap(&rest);
464 return;
465 }
466 "graph" => {
467 let mut action = "build";
468 let mut path_arg: Option<&str> = None;
469 for arg in &rest {
470 if arg == "build" {
471 action = "build";
472 } else {
473 path_arg = Some(arg.as_str());
474 }
475 }
476 let root = path_arg
477 .map(String::from)
478 .or_else(|| {
479 std::env::current_dir()
480 .ok()
481 .map(|p| p.to_string_lossy().to_string())
482 })
483 .unwrap_or_else(|| ".".to_string());
484 match action {
485 "build" => {
486 let index = core::graph_index::load_or_build(&root);
487 println!(
488 "Graph built: {} files, {} edges",
489 index.files.len(),
490 index.edges.len()
491 );
492 }
493 _ => {
494 eprintln!("Usage: lean-ctx graph [build] [path]");
495 }
496 }
497 return;
498 }
499 "session" => {
500 super::cmd_session();
501 return;
502 }
503 "wrapped" => {
504 super::cmd_wrapped(&rest);
505 return;
506 }
507 "sessions" => {
508 super::cmd_sessions(&rest);
509 return;
510 }
511 "benchmark" => {
512 super::cmd_benchmark(&rest);
513 return;
514 }
515 "config" => {
516 super::cmd_config(&rest);
517 return;
518 }
519 "stats" => {
520 super::cmd_stats(&rest);
521 return;
522 }
523 "cache" => {
524 super::cmd_cache(&rest);
525 return;
526 }
527 "theme" => {
528 super::cmd_theme(&rest);
529 return;
530 }
531 "tee" => {
532 super::cmd_tee(&rest);
533 return;
534 }
535 "slow-log" => {
536 super::cmd_slow_log(&rest);
537 return;
538 }
539 "update" | "--self-update" => {
540 core::updater::run(&rest);
541 return;
542 }
543 "doctor" => {
544 let code = doctor::run_cli(&rest);
545 if code != 0 {
546 std::process::exit(code);
547 }
548 return;
549 }
550 "gotchas" | "bugs" => {
551 super::cloud::cmd_gotchas(&rest);
552 return;
553 }
554 "buddy" | "pet" => {
555 super::cloud::cmd_buddy(&rest);
556 return;
557 }
558 "hook" => {
559 let action = rest.first().map(|s| s.as_str()).unwrap_or("help");
560 match action {
561 "rewrite" => hook_handlers::handle_rewrite(),
562 "redirect" => hook_handlers::handle_redirect(),
563 _ => {
564 eprintln!("Usage: lean-ctx hook <rewrite|redirect>");
565 eprintln!(" Internal commands used by agent hooks (Claude, Cursor, etc.)");
566 std::process::exit(1);
567 }
568 }
569 return;
570 }
571 "report-issue" | "report" => {
572 report::run(&rest);
573 return;
574 }
575 "uninstall" => {
576 uninstall::run();
577 return;
578 }
579 "cheat" | "cheatsheet" | "cheat-sheet" => {
580 super::cmd_cheatsheet();
581 return;
582 }
583 "login" => {
584 super::cloud::cmd_login(&rest);
585 return;
586 }
587 "sync" => {
588 super::cloud::cmd_sync();
589 return;
590 }
591 "contribute" => {
592 super::cloud::cmd_contribute();
593 return;
594 }
595 "cloud" => {
596 super::cloud::cmd_cloud(&rest);
597 return;
598 }
599 "upgrade" => {
600 super::cloud::cmd_upgrade();
601 return;
602 }
603 "--version" | "-V" => {
604 println!("{}", core::integrity::origin_line());
605 return;
606 }
607 "--help" | "-h" => {
608 print_help();
609 return;
610 }
611 "mcp" => {
612 }
614 _ => {
615 eprintln!("lean-ctx: unknown command '{}'\n", args[1]);
616 print_help();
617 std::process::exit(1);
618 }
619 }
620 }
621
622 if let Err(e) = run_mcp_server() {
623 eprintln!("lean-ctx: {e}");
624 std::process::exit(1);
625 }
626}
627
628fn passthrough(command: &str) -> ! {
629 let (shell, flag) = shell::shell_and_flag();
630 let status = std::process::Command::new(&shell)
631 .arg(&flag)
632 .arg(command)
633 .env("LEAN_CTX_ACTIVE", "1")
634 .status()
635 .map(|s| s.code().unwrap_or(1))
636 .unwrap_or(127);
637 std::process::exit(status);
638}
639
640fn run_async<F: std::future::Future>(future: F) -> F::Output {
641 tokio::runtime::Runtime::new()
642 .expect("failed to create async runtime")
643 .block_on(future)
644}
645
646fn run_mcp_server() -> Result<()> {
647 use rmcp::ServiceExt;
648 use tracing_subscriber::EnvFilter;
649
650 std::env::set_var("LEAN_CTX_MCP_SERVER", "1");
651
652 let rt = tokio::runtime::Runtime::new()?;
653 rt.block_on(async {
654 tracing_subscriber::fmt()
655 .with_env_filter(EnvFilter::from_default_env())
656 .with_writer(std::io::stderr)
657 .init();
658
659 tracing::info!(
660 "lean-ctx v{} MCP server starting",
661 env!("CARGO_PKG_VERSION")
662 );
663
664 let server = tools::create_server();
665 let transport =
666 mcp_stdio::HybridStdioTransport::new_server(tokio::io::stdin(), tokio::io::stdout());
667 let service = server.serve(transport).await?;
668 service.waiting().await?;
669
670 core::stats::flush();
671 core::mode_predictor::ModePredictor::flush();
672 core::feedback::FeedbackStore::flush();
673
674 Ok(())
675 })
676}
677
678fn print_help() {
679 println!(
680 "lean-ctx {version} — Context Runtime for AI Agents
681
68290+ compression patterns | 46 MCP tools | Context Continuity Protocol
683
684USAGE:
685 lean-ctx Start MCP server (stdio)
686 lean-ctx serve Start MCP server (Streamable HTTP)
687 lean-ctx -c \"command\" Execute with compressed output
688 lean-ctx -c --raw \"command\" Execute without compression (full output)
689 lean-ctx exec \"command\" Same as -c
690 lean-ctx shell Interactive shell with compression
691
692COMMANDS:
693 gain Visual dashboard (colors, bars, sparklines, USD)
694 gain --live Live mode: auto-refreshes every 1s in-place
695 gain --graph 30-day savings chart
696 gain --daily Bordered day-by-day table with USD
697 gain --json Raw JSON export of all stats
698 token-report [--json] Token + memory report (project + session + CEP)
699 cep CEP impact report (score trends, cache, modes)
700 dashboard [--port=N] [--host=H] Open web dashboard (default: http://localhost:3333)
701 serve [--host H] [--port N] MCP over HTTP (Streamable HTTP, local-first)
702 wrapped [--week|--month|--all] Savings report card (shareable)
703 sessions [list|show|cleanup] Manage CCP sessions (~/.lean-ctx/sessions/)
704 benchmark run [path] [--json] Run real benchmark on project files
705 benchmark report [path] Generate shareable Markdown report
706 cheatsheet Command cheat sheet & workflow quick reference
707 setup One-command setup: shell + editor + verify
708 bootstrap Non-interactive setup + fix (zero-config)
709 status [--json] Show setup + MCP + rules status
710 init [--global] Install shell aliases (zsh/bash/fish/PowerShell)
711 init --agent <name> Configure MCP for specific editor/agent
712 read <file> [-m mode] Read file with compression
713 diff <file1> <file2> Compressed file diff
714 grep <pattern> [path] Search with compressed output
715 find <pattern> [path] Find files with compressed output
716 ls [path] Directory listing with compression
717 deps [path] Show project dependencies
718 discover Find uncompressed commands in shell history
719 filter [list|validate|init] Manage custom compression filters (~/.lean-ctx/filters/)
720 session Show adoption statistics
721 config Show/edit configuration (~/.lean-ctx/config.toml)
722 theme [list|set|export|import] Customize terminal colors and themes
723 tee [list|clear|show <file>|last] Manage output tee files (~/.lean-ctx/tee/)
724 slow-log [list|clear] Show/clear slow command log (~/.lean-ctx/slow-commands.log)
725 update [--check] Self-update lean-ctx binary from GitHub Releases
726 gotchas [list|clear|export|stats] Bug Memory: view/manage auto-detected error patterns
727 buddy [show|stats|ascii|json] Token Guardian: your data-driven coding companion
728 doctor [--fix] [--json] Run diagnostics (and optionally repair)
729 uninstall Remove shell hook, MCP configs, and data directory
730
731SHELL HOOK PATTERNS (90+):
732 git status, log, diff, add, commit, push, pull, fetch, clone,
733 branch, checkout, switch, merge, stash, tag, reset, remote
734 docker build, ps, images, logs, compose, exec, network
735 npm/pnpm install, test, run, list, outdated, audit
736 cargo build, test, check, clippy
737 gh pr list/view/create, issue list/view, run list/view
738 kubectl get pods/services/deployments, logs, describe, apply
739 python pip install/list/outdated, ruff check/format, poetry, uv
740 linters eslint, biome, prettier, golangci-lint
741 builds tsc, next build, vite build
742 ruby rubocop, bundle install/update, rake test, rails test
743 tests jest, vitest, pytest, go test, playwright, rspec, minitest
744 iac terraform, make, maven, gradle, dotnet, flutter, dart
745 utils curl, grep/rg, find, ls, wget, env
746 data JSON schema extraction, log deduplication
747
748READ MODES:
749 auto Auto-select optimal mode (default)
750 full Full content (cached re-reads = 13 tokens)
751 map Dependency graph + API signatures
752 signatures tree-sitter AST extraction (18 languages)
753 task Task-relevant filtering (requires ctx_session task)
754 reference One-line reference stub (cheap cache key)
755 aggressive Syntax-stripped content
756 entropy Shannon entropy filtered
757 diff Changed lines only
758 lines:N-M Specific line ranges (e.g. lines:10-50,80)
759
760ENVIRONMENT:
761 LEAN_CTX_DISABLED=1 Bypass ALL compression + prevent shell hook from loading
762 LEAN_CTX_ENABLED=0 Prevent shell hook auto-start (lean-ctx-on still works)
763 LEAN_CTX_RAW=1 Same as --raw for current command
764 LEAN_CTX_AUTONOMY=false Disable autonomous features
765 LEAN_CTX_COMPRESS=1 Force compression (even for excluded commands)
766
767OPTIONS:
768 --version, -V Show version
769 --help, -h Show this help
770
771EXAMPLES:
772 lean-ctx -c \"git status\" Compressed git output
773 lean-ctx -c \"kubectl get pods\" Compressed k8s output
774 lean-ctx -c \"gh pr list\" Compressed GitHub CLI output
775 lean-ctx gain Visual terminal dashboard
776 lean-ctx gain --live Live auto-updating terminal dashboard
777 lean-ctx gain --graph 30-day savings chart
778 lean-ctx gain --daily Day-by-day breakdown with USD
779 lean-ctx token-report --json Machine-readable token + memory report
780 lean-ctx dashboard Open web dashboard at localhost:3333
781 lean-ctx dashboard --host=0.0.0.0 Bind to all interfaces (remote access)
782 lean-ctx wrapped Weekly savings report card
783 lean-ctx wrapped --month Monthly savings report card
784 lean-ctx sessions list List all CCP sessions
785 lean-ctx sessions show Show latest session state
786 lean-ctx discover Find missed savings in shell history
787 lean-ctx setup One-command setup (shell + editors + verify)
788 lean-ctx bootstrap Non-interactive setup + fix (zero-config)
789 lean-ctx bootstrap --json Machine-readable bootstrap report
790 lean-ctx init --global Install shell aliases (includes lean-ctx-on/off/status)
791 lean-ctx-on Enable all compression aliases (after init)
792 lean-ctx-off Disable all compression aliases (human-readable mode)
793 lean-ctx-status Show whether compression is active
794 lean-ctx init --agent pi Install Pi Coding Agent extension
795 lean-ctx doctor Check PATH, config, MCP, and dashboard port
796 lean-ctx doctor --fix --json Repair + machine-readable report
797 lean-ctx status --json Machine-readable current status
798 lean-ctx read src/main.rs -m map
799 lean-ctx grep \"pub fn\" src/
800 lean-ctx deps .
801
802CLOUD:
803 cloud status Show cloud connection status
804 login <email> Register/login to LeanCTX Cloud
805 sync Upload local stats to cloud dashboard
806 contribute Share anonymized compression data
807
808TROUBLESHOOTING:
809 Commands broken? lean-ctx-off (fixes current session)
810 Permanent fix? lean-ctx uninstall (removes all hooks)
811 Manual fix? Edit ~/.zshrc, remove the \"lean-ctx shell hook\" block
812 Binary missing? Aliases auto-fallback to original commands (safe)
813 Preview init? lean-ctx init --global --dry-run
814
815WEBSITE: https://leanctx.com
816GITHUB: https://github.com/yvgude/lean-ctx
817",
818 version = env!("CARGO_PKG_VERSION"),
819 );
820}