//! CodeCraft – web-based coding harness for AI models. mod api; mod app; mod auth; mod budget; mod config; mod files; mod git; mod images; mod mcp; mod permission; mod prompts; mod provider; mod runner; mod store; mod tools; mod types; use anyhow::Result; use tracing_subscriber::EnvFilter; #[tokio::main] async fn main() -> Result<()> { tracing_subscriber::fmt() .with_env_filter(EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info,codecraft=info"))) .init(); // In Docker, HOME lives on the data volume; make sure it exists for git/npm. if let Ok(home) = std::env::var("HOME") { let _ = std::fs::create_dir_all(home); } let path = config::config_path(); let (cfg, _) = config::load_or_init(&path)?; tracing::info!("config: {}", path.display()); tracing::info!("workspace: {}", cfg.workspace().display()); let bind = cfg.server.bind.clone(); let app = app::App::new(path, cfg).await?; let router = api::router(app); let listener = tokio::net::TcpListener::bind(&bind).await?; tracing::info!("listening on http://{bind}"); axum::serve(listener, router).with_graceful_shutdown(shutdown()).await?; Ok(()) } async fn shutdown() { let _ = tokio::signal::ctrl_c().await; tracing::info!("shutting down"); }