minni 0.1.0

Local memory, task, and codebase indexing tool for AI agents
Documentation
use crate::db::Database;
use crate::journal::JournalManager;
use anyhow::Result;
use colored::Colorize;
use std::env;
use std::path::Path;

pub fn run() -> Result<()> {
    let cwd = env::current_dir()?;

    if Database::minni_dir_exists(&cwd) {
        println!(
            "{} Minni is already initialized in this directory",
            "!".yellow()
        );
        return Ok(());
    }

    let _db = Database::initialize(&cwd)?;

    println!("{} Initialized minni in {}", "".green(), cwd.display());
    println!();
    println!("Next steps:");
    println!("  {} Index your codebase", "minni index".cyan());
    println!("  {} Search for code", "minni search \"your query\"".cyan());
    println!("  {} Save session context", "minni context save".cyan());

    Ok(())
}

/// Auto-initialize minni if not already done. Returns true if initialization was performed.
/// Optionally installs git hooks and runs initial index.
pub fn ensure_initialized(project_root: &Path, full_setup: bool) -> Result<bool> {
    if Database::minni_dir_exists(project_root) {
        return Ok(false);
    }

    println!("{} Auto-initializing minni...", "".blue());
    let _db = Database::initialize(project_root)?;
    println!(
        "{} Initialized minni in {}",
        "".green(),
        project_root.display()
    );

    // Add .minni to .gitignore if not already present
    add_to_gitignore(project_root)?;

    if full_setup {
        // Install git hooks if this is a git repo
        let git_dir = project_root.join(".git");
        if git_dir.exists() {
            let journal = JournalManager::new(project_root);
            if journal.install_hooks().is_ok() {
                println!("{} Git hooks installed for auto-journaling", "".green());
            }
        }

        // Run initial index
        println!("{} Running initial index...", "".blue());
        crate::cli::index::run(Some(project_root.to_path_buf()), false)?;
    }

    Ok(true)
}

/// Add .minni/ to .gitignore if not already present
fn add_to_gitignore(project_root: &Path) -> Result<()> {
    let gitignore_path = project_root.join(".gitignore");

    let content = if gitignore_path.exists() {
        std::fs::read_to_string(&gitignore_path)?
    } else {
        String::new()
    };

    // Check if .minni is already ignored
    if content.lines().any(|line| {
        let trimmed = line.trim();
        trimmed == ".minni" || trimmed == ".minni/" || trimmed == "/.minni" || trimmed == "/.minni/"
    }) {
        return Ok(());
    }

    // Append .minni/ to .gitignore
    let mut new_content = content;
    if !new_content.is_empty() && !new_content.ends_with('\n') {
        new_content.push('\n');
    }
    if !new_content.is_empty() {
        new_content.push('\n');
    }
    new_content.push_str("# Minni - local codebase index (https://github.com/youruser/minni)\n");
    new_content.push_str(".minni/\n");

    std::fs::write(&gitignore_path, new_content)?;
    println!("{} Added .minni/ to .gitignore", "".green());

    Ok(())
}