use std::net::SocketAddr;
use std::path::PathBuf;
use anyhow::Result;
use clap::Parser;
use interlink::bus::Broker;
use interlink::store::Store;
use tokio::net::TcpListener;
#[derive(Parser)]
#[command(about = "Message broker for Claude Code agents")]
struct Args {
#[arg(long, env = "INTERLINK_ADDR", default_value = "127.0.0.1:9440")]
addr: SocketAddr,
#[arg(long, env = "INTERLINK_DB")]
db: Option<PathBuf>,
#[arg(long, env = "INTERLINK_QUEUE_CAP", default_value_t = 1024)]
queue_cap: usize,
}
#[tokio::main]
async fn main() -> Result<()> {
tracing_subscriber::fmt()
.with_env_filter(
tracing_subscriber::EnvFilter::try_from_default_env()
.unwrap_or_else(|_| "interlink=info".into()),
)
.init();
let args = Args::parse();
if !args.addr.ip().is_loopback() {
tracing::warn!(
addr = %args.addr,
"bus is not bound to loopback; any host reaching this port can enqueue"
);
}
let store = match &args.db {
Some(path) => {
tracing::info!(db = %path.display(), "durable queue");
Store::on_disk(path)?
}
None => {
tracing::warn!("no --db: in-memory queue, lost on restart");
Store::in_memory()?
}
};
let app = Broker::new(store, args.queue_cap).router();
let listener = TcpListener::bind(args.addr).await?;
tracing::info!(addr = %args.addr, cap = args.queue_cap, "bus listening");
axum::serve(listener, app).await?;
Ok(())
}