This repository has been archived on 2026-10-08. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
maestro/crates/maestro-daemon/src/cli.rs
T

96 lines
2.9 KiB
Rust

//! Clap-derive subcommand for the daemon, plus a runner that wires everything
//! together.
use std::error::Error;
use std::path::PathBuf;
use clap::Subcommand;
use tokio::net::TcpListener;
use crate::session::DEFAULT_LIVENESS_INTERVAL;
use crate::sidecar::SidecarStore;
use crate::tmux::Tmux;
use crate::worktree::WorktreeManager;
use crate::{
default_config_path, default_state_dir, load_config, local_api, EnvOverrides, SessionManager,
};
#[derive(Debug, Subcommand)]
pub enum DaemonCmd {
/// Start the daemon. Default when no subcommand is given.
Run,
}
/// Dispatch a parsed daemon subcommand. `config_override` is the unified
/// `--config` flag from the top-level CLI.
pub async fn dispatch(
config_override: Option<PathBuf>,
cmd: Option<DaemonCmd>,
) -> Result<(), Box<dyn Error>> {
match cmd.unwrap_or(DaemonCmd::Run) {
DaemonCmd::Run => run(config_override).await,
}
}
async fn run(config_override: Option<PathBuf>) -> Result<(), Box<dyn Error>> {
let config_path: PathBuf = match config_override {
Some(p) => p,
None => default_config_path()?,
};
let config = load_config(&config_path, EnvOverrides::from_env())?;
tracing::info!(
hostname = %config.hostname,
bind = %config.bind_addr,
"loaded config"
);
let _ = default_state_dir();
std::fs::create_dir_all(config.sidecar_dir())?;
std::fs::create_dir_all(config.fifo_dir())?;
// No worktree dir to pre-create: without an override the worktrees live
// under their base repos, created on demand (#56).
let sidecar = SidecarStore::new(config.sidecar_dir());
let worktree_mgr = WorktreeManager::new(config.worktree_root.clone());
let tmux = match config.tmux_tmpdir.clone() {
Some(p) => Tmux::new().with_tmpdir(p),
None => Tmux::new(),
};
let manager = SessionManager::new_with_replay(
std::sync::Arc::new(tmux),
sidecar,
worktree_mgr,
config.fifo_dir(),
config.pty_replay_bytes,
)
.with_spawn_history(crate::spawn_history::SpawnHistory::new(
config.spawn_history_path(),
config.spawn_history_days,
));
let recovered = manager.recover().await?;
tracing::info!(recovered, "adopted existing tmux sessions");
manager.start_liveness_watcher(DEFAULT_LIVENESS_INTERVAL);
let router = local_api::router(local_api::state_for(
manager,
config.hostname.clone(),
config.home_dir.clone(),
config.spawn_presets.clone(),
));
let listener = TcpListener::bind(config.bind_addr).await?;
let bound = listener.local_addr()?;
tracing::info!(addr = %bound, "API listening");
let shutdown = async {
let _ = tokio::signal::ctrl_c().await;
tracing::info!("ctrl-c received — shutting down");
};
axum::serve(listener, router)
.with_graceful_shutdown(shutdown)
.await?;
Ok(())
}