1use crate::hooks::to_bash_compatible_path;
2
3pub(crate) fn quiet_enabled() -> bool {
4 matches!(std::env::var("LEAN_CTX_QUIET"), Ok(v) if v.trim() == "1")
5}
6
7macro_rules! qprintln {
8 ($($t:tt)*) => {
9 if !quiet_enabled() {
10 println!($($t)*);
11 }
12 };
13}
14
15pub fn cmd_init(args: &[String]) {
16 let global = args.iter().any(|a| a == "--global" || a == "-g");
17 let dry_run = args.iter().any(|a| a == "--dry-run");
18 let no_hook = args.iter().any(|a| a == "--no-shell-hook")
19 || crate::core::config::Config::load().shell_hook_disabled_effective();
20
21 let agents: Vec<&str> = args
22 .windows(2)
23 .filter(|w| w[0] == "--agent")
24 .map(|w| w[1].as_str())
25 .collect();
26
27 if !agents.is_empty() {
28 for agent_name in &agents {
29 crate::hooks::install_agent_hook(agent_name, global);
30 if let Err(e) = crate::setup::configure_agent_mcp(agent_name) {
31 eprintln!("MCP config for '{agent_name}' not updated: {e}");
32 }
33 }
34 if !global {
35 crate::hooks::install_project_rules();
36 }
37 qprintln!("\nRun 'lean-ctx gain' after using some commands to see your savings.");
38 return;
39 }
40
41 let eval_shell = args
42 .iter()
43 .find(|a| matches!(a.as_str(), "bash" | "zsh" | "fish" | "powershell" | "pwsh"));
44 if let Some(shell) = eval_shell {
45 if !global {
46 super::shell_init::print_hook_stdout(shell);
47 return;
48 }
49 }
50
51 let shell_name = std::env::var("SHELL").unwrap_or_default();
52 let is_zsh = shell_name.contains("zsh");
53 let is_fish = shell_name.contains("fish");
54 let is_powershell = cfg!(windows) && shell_name.is_empty();
55
56 let binary = crate::core::portable_binary::resolve_portable_binary();
57
58 if dry_run {
59 let rc = if is_powershell {
60 "Documents/PowerShell/Microsoft.PowerShell_profile.ps1".to_string()
61 } else if is_fish {
62 "~/.config/fish/config.fish".to_string()
63 } else if is_zsh {
64 "~/.zshrc".to_string()
65 } else {
66 "~/.bashrc".to_string()
67 };
68 qprintln!("\nlean-ctx init --dry-run\n");
69 qprintln!(" Would modify: {rc}");
70 qprintln!(" Would backup: {rc}.lean-ctx.bak");
71 qprintln!(" Would alias: git npm pnpm yarn cargo docker docker-compose kubectl");
72 qprintln!(" gh pip pip3 ruff go golangci-lint eslint prettier tsc");
73 qprintln!(" curl wget php composer (24 commands + k)");
74 let data_dir = crate::core::data_dir::lean_ctx_data_dir().map_or_else(
75 |_| "~/.config/lean-ctx/".to_string(),
76 |p| p.to_string_lossy().to_string(),
77 );
78 qprintln!(" Would create: {data_dir}");
79 qprintln!(" Binary: {binary}");
80 qprintln!("\n Safety: aliases auto-fallback to original command if lean-ctx is removed.");
81 qprintln!("\n Run without --dry-run to apply.");
82 return;
83 }
84
85 if no_hook {
86 qprintln!("Shell hook disabled (--no-shell-hook or shell_hook_disabled config).");
87 qprintln!("MCP tools remain active. Set LEAN_CTX_NO_HOOK=1 to disable at runtime.");
88 } else if is_powershell {
89 super::shell_init::init_powershell(&binary);
90 } else {
91 let bash_binary = to_bash_compatible_path(&binary);
92 if is_fish {
93 super::shell_init::init_fish(&bash_binary);
94 } else {
95 super::shell_init::init_posix(is_zsh, &bash_binary);
96 }
97 }
98
99 if let Ok(lean_dir) = crate::core::data_dir::lean_ctx_data_dir() {
100 if !lean_dir.exists() {
101 let _ = std::fs::create_dir_all(&lean_dir);
102 qprintln!("Created {}", lean_dir.display());
103 }
104 }
105
106 let rc = if is_powershell {
107 "$PROFILE"
108 } else if is_fish {
109 "config.fish"
110 } else if is_zsh {
111 ".zshrc"
112 } else {
113 ".bashrc"
114 };
115
116 qprintln!("\nlean-ctx init complete (24 aliases installed)");
117 qprintln!();
118 qprintln!(" Disable temporarily: lean-ctx-off");
119 qprintln!(" Re-enable: lean-ctx-on");
120 qprintln!(" Check status: lean-ctx-status");
121 qprintln!(" Full uninstall: lean-ctx uninstall");
122 qprintln!(" Diagnose issues: lean-ctx doctor");
123 qprintln!(" Preview changes: lean-ctx init --global --dry-run");
124 qprintln!();
125 if is_powershell {
126 qprintln!(" Restart PowerShell or run: . {rc}");
127 } else {
128 qprintln!(" Restart your shell or run: source ~/{rc}");
129 }
130 qprintln!();
131 qprintln!("For AI tool integration: lean-ctx init --agent <tool>");
132 qprintln!(" Supported: aider, amazonq, amp, antigravity, claude, cline, codex, copilot,");
133 qprintln!(" crush, cursor, emacs, gemini, hermes, jetbrains, kiro, neovim, opencode,");
134 qprintln!(" pi, qwen, roo, sublime, trae, verdent, windsurf");
135}
136
137pub fn cmd_init_quiet(args: &[String]) {
138 std::env::set_var("LEAN_CTX_QUIET", "1");
139 cmd_init(args);
140 std::env::remove_var("LEAN_CTX_QUIET");
141}