Skip to main content

colgrep/install/
opencode.rs

1use anyhow::{Context, Result};
2use colored::Colorize;
3use std::fs;
4use std::path::PathBuf;
5
6use super::SKILL_MD;
7
8/// Marker to identify colgrep section in AGENTS.md
9const COLGREP_MARKER_START: &str = "<!-- COLGREP_START -->";
10const COLGREP_MARKER_END: &str = "<!-- COLGREP_END -->";
11
12/// Get the OpenCode directory
13fn get_opencode_dir() -> Result<PathBuf> {
14    let home = dirs::home_dir().context("Could not determine home directory")?;
15    Ok(home.join(".config").join("opencode"))
16}
17
18/// Get the AGENTS.md path for OpenCode
19fn get_agents_md_path() -> Result<PathBuf> {
20    let opencode_dir = get_opencode_dir()?;
21    Ok(opencode_dir.join("AGENTS.md"))
22}
23
24/// Add colgrep instructions to AGENTS.md
25fn add_to_agents_md() -> Result<()> {
26    let opencode_dir = get_opencode_dir()?;
27    fs::create_dir_all(&opencode_dir)?;
28
29    let agents_path = get_agents_md_path()?;
30
31    let mut content = if agents_path.exists() {
32        fs::read_to_string(&agents_path)?
33    } else {
34        String::from("# OpenCode Agent Tools\n\n")
35    };
36
37    // Check if colgrep is already installed
38    if content.contains(COLGREP_MARKER_START) {
39        // Remove existing colgrep section first
40        if let (Some(start), Some(end)) = (
41            content.find(COLGREP_MARKER_START),
42            content.find(COLGREP_MARKER_END),
43        ) {
44            let end_pos = end + COLGREP_MARKER_END.len();
45            content = format!("{}{}", &content[..start], &content[end_pos..]);
46        }
47    }
48
49    // Add colgrep section
50    let colgrep_section = format!(
51        "{}\n{}\n{}\n",
52        COLGREP_MARKER_START, SKILL_MD, COLGREP_MARKER_END
53    );
54    content.push_str(&colgrep_section);
55
56    fs::write(&agents_path, content)?;
57    Ok(())
58}
59
60/// Remove colgrep from AGENTS.md
61fn remove_from_agents_md() -> Result<()> {
62    let agents_path = get_agents_md_path()?;
63
64    if !agents_path.exists() {
65        return Ok(());
66    }
67
68    let content = fs::read_to_string(&agents_path)?;
69
70    if let (Some(start), Some(end)) = (
71        content.find(COLGREP_MARKER_START),
72        content.find(COLGREP_MARKER_END),
73    ) {
74        let end_pos = end + COLGREP_MARKER_END.len();
75        let new_content = format!("{}{}", &content[..start], &content[end_pos..]);
76
77        // Clean up extra newlines
78        let cleaned = new_content.trim().to_string();
79
80        if cleaned.is_empty() || cleaned == "# OpenCode Agent Tools" {
81            // Remove file if empty
82            fs::remove_file(&agents_path)?;
83        } else {
84            fs::write(&agents_path, format!("{}\n", cleaned))?;
85        }
86    }
87
88    Ok(())
89}
90
91/// Install colgrep for OpenCode
92pub fn install_opencode() -> Result<()> {
93    println!("Installing colgrep for OpenCode...");
94
95    // Add instructions to AGENTS.md
96    add_to_agents_md()?;
97    let agents_path = get_agents_md_path()?;
98    println!(
99        "{} Added colgrep instructions to {}",
100        "✓".green(),
101        agents_path.display()
102    );
103
104    print_opencode_success();
105    Ok(())
106}
107
108/// Uninstall colgrep from OpenCode
109pub fn uninstall_opencode() -> Result<()> {
110    println!("Uninstalling colgrep from OpenCode...");
111
112    remove_from_agents_md()?;
113    println!("{} Removed colgrep from AGENTS.md", "✓".green());
114
115    println!();
116    println!("{}", "Colgrep has been uninstalled from OpenCode.".green());
117    Ok(())
118}
119
120fn print_opencode_success() {
121    println!();
122    println!("{}", "═".repeat(70).cyan());
123    println!();
124    println!(
125        "  {} {}",
126        "✓".green().bold(),
127        "COLGREP INSTALLED FOR OPENCODE".green().bold()
128    );
129    println!();
130    println!(
131        "  {}",
132        "Colgrep is now available as a semantic search tool in OpenCode.".white()
133    );
134    println!();
135    println!("  {}", "Usage in OpenCode:".cyan().bold());
136    println!(
137        "    {}",
138        "Use natural language to search your codebase.".white()
139    );
140    println!("    {}", "Example: \"find error handling logic\"".white());
141    println!();
142    println!("  {}", "To uninstall:".cyan().bold());
143    println!("    {}", "colgrep --uninstall-opencode".green());
144    println!();
145    println!("{}", "═".repeat(70).cyan());
146}