codebase-recall 0.7.0

CLI based application for codebase dumper for LLMs and fast review/recall project
use anyhow::Result;
use std::collections::HashSet;
use std::fs;
use std::path::PathBuf;

use crate::cli::{DumpArgs, GraphQuery};
use crate::commands::graph::build_graph;
use crate::dump::{formatter, walker};

pub fn run(args: DumpArgs) -> Result<()> {
    let (tree_paths, files, metadata_header) = if let Some(focus_target) = &args.relation {
        let query = GraphQuery {
            project: args.path.clone(),
            scope: "both".to_string(),
            kinds: vec![
                "imports".to_string(),
                "calls".to_string(),
                "contains".to_string(),
            ],
            path: None,
            focus: Some(focus_target.clone()),
            depth: args.depth,
            min_confidence: 0.4,
            include_external: false,
            max_nodes: 4000,
            no_sync: args.no_sync,
        };

        let graph = build_graph(&query)?;

        let target_rel_paths: Vec<PathBuf> = graph
            .nodes
            .iter()
            .filter_map(|n| n.path.as_deref())
            .map(PathBuf::from)
            .collect::<HashSet<_>>()
            .into_iter()
            .collect();

        println!(
            "Focused dump: target '{}' (depth {}) -> {} connected files",
            focus_target,
            args.depth,
            target_rel_paths.len()
        );

        let (tree_paths, files) =
            walker::collect_related_files(&args.path, &target_rel_paths, args.max_size_kb);

        let header = format!(
            "> **Targeted dump**: focused on `{}` with depth {}. \n\n",
            focus_target, args.depth
        );

        (tree_paths, files, header)
    } else {
        let (tree_paths, files) = walker::collect_files(&args.path, args.max_size_kb)?;
        (tree_paths, files, String::new())
    };
    let tree_view = formatter::build_tree_view(&tree_paths);
    let mut file_view = formatter::build_content_view(&tree_view, &files);

    if !metadata_header.is_empty() {
        file_view = format!("{}{}", metadata_header, file_view);
    }

    fs::write(&args.output, &file_view)?;
    println!(
        "Codebase context successfully written to: {}",
        args.output.display()
    );

    Ok(())
}