next_plaid_cli/install/
claude_code.rs

1use anyhow::{Context, Result};
2use colored::Colorize;
3use std::process::Command;
4
5/// The marketplace identifier for the plaid plugin
6/// Note: Must not conflict with plugin name on case-insensitive filesystems
7const MARKETPLACE_ID: &str = "lightonai-plaid";
8
9/// The plugin name as registered in Claude Code
10const PLUGIN_NAME: &str = "plaid";
11
12/// Minimum required Claude Code version for plugin support
13const MIN_CLAUDE_VERSION: &str = "2.0.36";
14
15/// Install the plaid plugin for Claude Code
16pub fn install_claude_code() -> Result<()> {
17    // Get the shell to use for command execution
18    let shell = get_shell();
19
20    // Step 1: Add plugin to marketplace
21    println!("Adding plaid to Claude Code marketplace...");
22    let marketplace_add = Command::new(&shell)
23        .args([
24            "-c",
25            &format!("claude plugin marketplace add {}", MARKETPLACE_ID),
26        ])
27        .output()
28        .context("Failed to execute claude CLI")?;
29
30    if !marketplace_add.status.success() {
31        let stderr = String::from_utf8_lossy(&marketplace_add.stderr);
32        eprintln!(
33            "{} Failed to add plugin to marketplace: {}",
34            "Error:".red(),
35            stderr
36        );
37        eprintln!(
38            "{}",
39            format!(
40                "Do you have Claude Code version {} or higher installed?",
41                MIN_CLAUDE_VERSION
42            )
43            .yellow()
44        );
45        anyhow::bail!("Failed to add plugin to marketplace");
46    }
47    println!("{} Added plaid plugin to the marketplace", "✓".green());
48
49    // Step 2: Install the plugin
50    println!("Installing plaid plugin...");
51    let plugin_install = Command::new(&shell)
52        .args(["-c", &format!("claude plugin install {}", PLUGIN_NAME)])
53        .output()
54        .context("Failed to execute claude CLI")?;
55
56    if !plugin_install.status.success() {
57        let stderr = String::from_utf8_lossy(&plugin_install.stderr);
58        eprintln!("{} Failed to install plugin: {}", "Error:".red(), stderr);
59        eprintln!(
60            "{}",
61            format!(
62                "Do you have Claude Code version {} or higher installed?",
63                MIN_CLAUDE_VERSION
64            )
65            .yellow()
66        );
67        anyhow::bail!("Failed to install plugin");
68    }
69    println!("{} Installed plaid plugin", "✓".green());
70
71    // Print success message and usage instructions
72    print_install_success();
73
74    Ok(())
75}
76
77/// Uninstall the plaid plugin from Claude Code
78pub fn uninstall_claude_code() -> Result<()> {
79    let shell = get_shell();
80
81    // Step 1: Uninstall the plugin
82    println!("Uninstalling plaid plugin...");
83    let plugin_uninstall = Command::new(&shell)
84        .args(["-c", &format!("claude plugin uninstall {}", PLUGIN_NAME)])
85        .output()
86        .context("Failed to execute claude CLI")?;
87
88    if !plugin_uninstall.status.success() {
89        let stderr = String::from_utf8_lossy(&plugin_uninstall.stderr);
90        eprintln!("{} Failed to uninstall plugin: {}", "Error:".red(), stderr);
91        eprintln!(
92            "{}",
93            format!(
94                "Do you have Claude Code version {} or higher installed?",
95                MIN_CLAUDE_VERSION
96            )
97            .yellow()
98        );
99        // Continue to try removing from marketplace anyway
100    } else {
101        println!("{} Uninstalled plaid plugin", "✓".green());
102    }
103
104    // Step 2: Remove from marketplace
105    println!("Removing plaid from marketplace...");
106    let marketplace_remove = Command::new(&shell)
107        .args([
108            "-c",
109            &format!("claude plugin marketplace remove {}", MARKETPLACE_ID),
110        ])
111        .output()
112        .context("Failed to execute claude CLI")?;
113
114    if !marketplace_remove.status.success() {
115        let stderr = String::from_utf8_lossy(&marketplace_remove.stderr);
116        eprintln!(
117            "{} Failed to remove plugin from marketplace: {}",
118            "Error:".red(),
119            stderr
120        );
121        eprintln!(
122            "{}",
123            format!(
124                "Do you have Claude Code version {} or higher installed?",
125                MIN_CLAUDE_VERSION
126            )
127            .yellow()
128        );
129        anyhow::bail!("Failed to remove plugin from marketplace");
130    }
131    println!("{} Removed plaid from marketplace", "✓".green());
132
133    println!();
134    println!("{}", "Plaid has been uninstalled from Claude Code.".green());
135
136    Ok(())
137}
138
139/// Get the appropriate shell for the current platform
140fn get_shell() -> String {
141    if cfg!(target_os = "windows") {
142        std::env::var("COMSPEC").unwrap_or_else(|_| "cmd.exe".to_string())
143    } else {
144        std::env::var("SHELL").unwrap_or_else(|_| "/bin/sh".to_string())
145    }
146}
147
148/// Print success message and usage instructions after installation
149fn print_install_success() {
150    let border = "═".repeat(70);
151
152    println!();
153    println!("{}", border.yellow());
154    println!();
155    println!(
156        "  {} {}",
157        "✓".green().bold(),
158        "PLAID INSTALLED FOR CLAUDE CODE".green().bold()
159    );
160    println!();
161    println!("  Plaid is now available as a semantic search tool in Claude Code.");
162    println!("  Claude will automatically use plaid for code searches.");
163    println!();
164    println!("  {}", "What happens:".cyan().bold());
165    println!("    • Plaid indexes your project on first search");
166    println!("    • Subsequent searches use the cached index");
167    println!("    • Index updates automatically when files change");
168    println!();
169    println!("  {}", "To uninstall:".cyan().bold());
170    println!("    {}", "plaid uninstall-claude-code".green());
171    println!();
172    println!("{}", border.yellow());
173    println!();
174}