mod commands;
mod tui;
use clap::{Parser, Subcommand};
#[derive(Parser)]
#[command(
name = "bctx",
about = "better-ctx: context-aware execution runtime for LLM agents",
version
)]
struct Cli {
#[command(subcommand)]
command: Cmd,
}
#[derive(Subcommand)]
enum Cmd {
#[command(external_subcommand)]
Run(Vec<String>),
Mcp {
#[arg(long, help = "Use HTTP transport instead of stdio")]
http: bool,
#[arg(long, default_value = "3000", help = "HTTP port (when --http)")]
port: u16,
},
Index {
#[arg(default_value = ".", help = "Project root to index")]
path: String,
#[arg(long, help = "Force full re-index")]
force: bool,
},
Search {
#[arg(help = "Search query")]
query: String,
#[arg(long, default_value = "10", help = "Max results")]
top_k: usize,
},
Gain,
Dashboard,
Init {
#[arg(long, default_value = "claude", help = "Agent to configure hooks for")]
agent: String,
},
Doctor,
Recall {
#[arg(help = "Query string")]
query: String,
#[arg(long, default_value = "5", help = "Max facts to return")]
top_k: usize,
},
Login {
#[arg(long, help = "Custom cloud endpoint URL")]
endpoint: Option<String>,
#[arg(long, help = "Log out and remove stored credentials")]
logout: bool,
},
Status,
Sync {
#[arg(
long,
help = "Push local crystallized facts to cloud (default when neither flag set)"
)]
push: bool,
#[arg(long, help = "Pull facts from cloud and merge into local Vault")]
pull: bool,
#[arg(long, help = "Project identifier (default: hash of current directory)")]
project: Option<String>,
},
}
fn main() {
std::thread::spawn(forge::budget::estimator::TokenEstimator::warmup);
let cli = Cli::parse();
let result = match cli.command {
Cmd::Run(args) => commands::run::handle(args),
Cmd::Mcp { http, port } => commands::mcp::handle(http, port),
Cmd::Index { path, force } => commands::index::handle(path, force),
Cmd::Search { query, top_k } => commands::search::handle(query, top_k),
Cmd::Gain => commands::gain::handle(),
Cmd::Dashboard => commands::dashboard::handle(),
Cmd::Init { agent } => commands::init::handle(agent),
Cmd::Doctor => commands::doctor::handle(),
Cmd::Recall { query, top_k } => commands::recall::handle(query, top_k),
Cmd::Login { endpoint, logout } => commands::login::handle(endpoint, logout),
Cmd::Status => commands::login::handle_status(),
Cmd::Sync {
push,
pull,
project,
} => commands::sync::handle(push, pull, project),
};
if let Err(e) = result {
eprintln!("error: {e}");
std::process::exit(1);
}
}