use clap::Parser;
use std::env;
mod api_client;
mod commands;
mod config;
mod credentials;
mod hooks;
#[derive(Parser)]
#[command(name = "tracevault", version, about = "AI code governance platform")]
enum Cli {
Init {
#[arg(long)]
server_url: Option<String>,
},
Status,
Hook {
#[arg(long)]
event: String,
},
Stream {
#[arg(long)]
event: String,
},
Check,
Push,
Sync,
Stats,
Login {
#[arg(long)]
server_url: String,
},
Logout,
CommitPush,
Flush,
Verify {
#[arg(long)]
commits: Option<String>,
#[arg(long)]
range: Option<String>,
},
}
#[tokio::main]
async fn main() {
let cli = Cli::parse();
match cli {
Cli::Init { server_url } => {
let cwd = env::current_dir().expect("Cannot determine current directory");
match commands::init::init_in_directory(&cwd, server_url.as_deref()).await {
Ok(()) => {
println!("TraceVault initialized in {}", cwd.display());
println!("Claude Code hooks installed in .claude/settings.json");
println!("Git pre-push hook installed");
}
Err(e) => eprintln!("Error: {e}"),
}
}
Cli::Status => println!("tracevault status - not yet implemented"),
Cli::Hook { event: _ } => {
let cwd = env::current_dir().expect("Cannot determine current directory");
if let Err(e) = commands::hook::handle_hook_from_stdin(&cwd) {
eprintln!("Hook error: {e}");
}
}
Cli::Stream { event } => {
let cwd = env::current_dir().expect("Cannot determine current directory");
if let Err(e) = commands::stream::run_stream(&cwd, &event).await {
eprintln!("Stream error: {e}");
}
}
Cli::Check => {
let cwd = env::current_dir().expect("Cannot determine current directory");
if let Err(e) = commands::check::check_policies(&cwd).await {
eprintln!("Check error: {e}");
std::process::exit(1);
}
}
Cli::Push => {
let cwd = env::current_dir().expect("Cannot determine current directory");
if let Err(e) = commands::push::push_traces(&cwd).await {
eprintln!("Push error: {e}");
std::process::exit(1);
}
}
Cli::Sync => {
let cwd = env::current_dir().expect("Cannot determine current directory");
if let Err(e) = commands::sync::sync_repo(&cwd).await {
eprintln!("Sync error: {e}");
}
}
Cli::Stats => {
let cwd = env::current_dir().expect("Cannot determine current directory");
if let Err(e) = commands::stats::show_stats(&cwd) {
eprintln!("Stats error: {e}");
}
}
Cli::Login { server_url } => {
if let Err(e) = commands::login::login(&server_url).await {
eprintln!("Login error: {e}");
}
}
Cli::Logout => {
if let Err(e) = commands::logout::logout().await {
eprintln!("Logout error: {e}");
}
}
Cli::CommitPush => {
let cwd = env::current_dir().expect("Cannot determine current directory");
if let Err(e) = commands::commit_push::run_commit_push(&cwd).await {
eprintln!("Commit push error: {e}");
}
}
Cli::Flush => {
let cwd = env::current_dir().expect("Cannot determine current directory");
if let Err(e) = commands::flush::run_flush(&cwd).await {
eprintln!("Flush error: {e}");
}
}
Cli::Verify { commits, range } => {
let cwd = env::current_dir().expect("Cannot determine current directory");
if let Err(e) =
commands::verify::verify(&cwd, commits.as_deref(), range.as_deref()).await
{
eprintln!("Verify error: {e}");
std::process::exit(1);
}
}
}
}