stemedb/applications/aphoria/src/main.rs
jordan c849627620 feat: add Aphoria dashboard scans and corpus UI
- Add scans panel with finding details, verdict badges, and filters
- Add corpus panel for managing knowledge sources
- Add scan cache for API state management
- Update sidebar navigation with new routes
- Extend API types for scans and corpus endpoints
- Add .aphoria/ to gitignore (contains project keys)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-07 15:56:49 -07:00

59 lines
1.6 KiB
Rust

//! Aphoria CLI - A code-level truth linter powered by Episteme
//!
//! CLI binaries use println! for user-facing output (not tracing)
#![allow(clippy::print_stdout, clippy::print_stderr)]
use std::process::ExitCode;
use clap::Parser;
use tracing_subscriber::EnvFilter;
use aphoria::AphoriaConfig;
mod cli;
mod handlers;
use cli::Cli;
#[tokio::main]
async fn main() -> ExitCode {
let cli = Cli::parse();
// Initialize tracing only if verbose or RUST_LOG is set
// Default: silent (clean CLI output)
if cli.verbose || std::env::var("RUST_LOG").is_ok() {
let filter =
EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("aphoria=info"));
tracing_subscriber::fmt().with_env_filter(filter).init();
}
// Load configuration
let config = match load_config(cli.config.as_deref()) {
Ok(cfg) => cfg,
Err(e) => {
eprintln!("Error loading configuration: {e}");
return ExitCode::from(3);
}
};
handlers::handle_command(cli.command, &config).await
}
/// Load configuration from file or use defaults.
fn load_config(path: Option<&std::path::Path>) -> Result<AphoriaConfig, aphoria::AphoriaError> {
if let Some(p) = path {
AphoriaConfig::from_file(p)
} else {
// Try default locations
let default_paths = ["aphoria.toml", ".aphoria/config.toml"];
for default in default_paths {
let p = std::path::Path::new(default);
if p.exists() {
return AphoriaConfig::from_file(p);
}
}
// No config file found, use defaults
Ok(AphoriaConfig::default())
}
}