mod bench;
mod cache;
mod chunker;
mod cli;
mod constants;
mod daemon;
mod db_discovery;
mod embed;
mod file;
mod fts;
mod index;
mod logger;
mod mcp;
mod output;
mod rerank;
mod search;
mod server;
mod vectordb;
mod watch;
use anyhow::Result;
use std::sync::atomic::Ordering;
use tokio_util::sync::CancellationToken;
use tracing::info;
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
#[tokio::main]
async fn main() -> Result<()> {
let args: Vec<String> = std::env::args().collect();
let is_quiet = args.iter().any(|a| a == "-q" || a == "--quiet");
let is_json = args.iter().any(|a| a == "--json");
let loglevel = args
.iter()
.position(|a| a == "-l" || a == "--loglevel")
.and_then(|pos| args.get(pos + 1))
.cloned()
.unwrap_or_else(|| "info".to_string());
let log_level = logger::LogLevel::parse(&loglevel).unwrap_or(logger::LogLevel::Info);
let log_level_str = log_level.as_str();
let cancel_token = CancellationToken::new();
let cancel_clone = cancel_token.clone();
ctrlc::set_handler(move || {
if constants::SHUTDOWN_REQUESTED.load(Ordering::SeqCst) {
eprintln!("\n⚠️ Force shutdown!");
std::process::exit(130);
}
if !is_quiet && !is_json {
eprintln!("\n🛑 Shutting down gracefully... (press Ctrl-C again to force)");
}
constants::SHUTDOWN_REQUESTED.store(true, Ordering::SeqCst);
cancel_clone.cancel();
})
.expect("Failed to set CTRL-C handler");
let is_mcp_or_serve = args.iter().any(|a| a == "mcp" || a == "serve" || a == "daemon");
if !is_quiet && !is_json && !is_mcp_or_serve {
tracing_subscriber::registry()
.with(
tracing_subscriber::EnvFilter::try_from_default_env()
.unwrap_or_else(|_| format!("codesearch={}", log_level_str).into()),
)
.with(tracing_subscriber::fmt::layer().with_writer(std::io::stderr))
.init();
info!(
"Starting codesearch v{} (loglevel: {})",
env!("CARGO_PKG_VERSION_FULL"),
log_level_str
);
}
cli::run(cancel_token).await
}