cqs 1.25.0

Code intelligence and RAG for AI agents. Semantic search, call graphs, impact analysis, type dependencies, and smart context assembly — in single tool calls. 54 languages + L5X/L5K PLC exports, 91.2% Recall@1 (BGE-large), 0.951 MRR (296 queries). Local ML, GPU-accelerated.
Documentation
//! Init command for cqs
//!
//! Creates .cqs/ directory and downloads the embedding model.

use anyhow::{Context, Result};

use cqs::Embedder;

use crate::cli::{find_project_root, Cli};

/// Initialize cqs in a project directory
/// Creates `.cqs/` directory, downloads the embedding model, and warms up the embedder.
pub(crate) fn cmd_init(cli: &Cli) -> Result<()> {
    let _span = tracing::info_span!("cmd_init").entered();
    let root = find_project_root();
    let cqs_dir = root.join(cqs::INDEX_DIR);

    if !cli.quiet {
        println!("Initializing cqs...");
    }

    // Create .cqs directory
    std::fs::create_dir_all(&cqs_dir).context("Failed to create .cqs directory")?;

    // Set restrictive permissions on .cqs directory (Unix only)
    #[cfg(unix)]
    {
        use std::os::unix::fs::PermissionsExt;
        if let Err(e) = std::fs::set_permissions(&cqs_dir, std::fs::Permissions::from_mode(0o700)) {
            tracing::debug!(error = %e, "Failed to set .cqs directory permissions");
        }
    }

    // Create .gitignore
    let gitignore = cqs_dir.join(".gitignore");
    std::fs::write(
        &gitignore,
        "index.db\nindex.db-wal\nindex.db-shm\nindex.lock\nindex.hnsw.graph\nindex.hnsw.data\nindex.hnsw.ids\nindex.hnsw.checksum\nindex.hnsw.lock\n*.tmp\n",
    )
    .context("Failed to create .gitignore")?;

    // Download model
    if !cli.quiet {
        // Heuristic: BGE-large (dim=1024) is ~1.3GB, E5-base (dim=768) is ~547MB.
        // Custom models with unknown sizes will show whichever is closer by dimension.
        let size = if cli.try_model_config()?.dim >= 1024 {
            "~1.3GB"
        } else {
            "~547MB"
        };
        println!("Downloading model ({size})...");
    }

    let embedder =
        Embedder::new(cli.try_model_config()?.clone()).context("Failed to initialize embedder")?;

    if !cli.quiet {
        println!("Detecting hardware... {}", embedder.provider());
    }

    // Warm up
    embedder.warm()?;

    if !cli.quiet {
        println!("Created .cqs/");
        println!();
        println!("Run 'cqs index' to index your codebase.");
    }

    Ok(())
}