//! dingger: agent state watching for tmux panes. mod manifest_update; mod notify; mod tmux; mod watcher; use clap::{Parser, Subcommand}; use tracing_subscriber::EnvFilter; #[derive(Parser)] #[command(name = "dingger", about = "Agent state watching for tmux panes")] struct Cli { #[command(subcommand)] command: Command, } #[derive(Subcommand)] enum Command { /// Watch all tmux panes and notify on agent state transitions. Watch { /// Poll interval in seconds. #[arg(long, default_value_t = 1)] interval_secs: u64, /// Disable notification sounds. #[arg(long)] no_sounds: bool, }, /// Print the current agent state of every tmux pane. Status, /// Refresh detection manifests from herdr's published catalog. Manifests { #[command(subcommand)] command: ManifestCommand, }, } #[derive(Subcommand)] enum ManifestCommand { /// Download newer manifests from herdr's published catalog into the /// local remote store; bundled manifests are the offline fallback. /// Restart `dingger watch` to pick them up. Update, } fn main() { tracing_subscriber::fmt() .with_env_filter(EnvFilter::try_from_default_env().unwrap_or_else(|_| "info".into())) .init(); match Cli::parse().command { Command::Watch { interval_secs, no_sounds, } => { let mut watcher = watcher::Watcher::new(interval_secs, !no_sounds); if let Err(err) = watcher.run() { eprintln!("dingger: {err}"); std::process::exit(1); } } Command::Status => { if let Err(err) = status() { eprintln!("dingger: {err}"); std::process::exit(1); } } Command::Manifests { command } => match command { ManifestCommand::Update => { if let Err(err) = manifest_update::update() { eprintln!("dingger: {err}"); std::process::exit(1); } } }, } } fn status() -> Result<(), String> { let panes = tmux::list_panes()?; if panes.is_empty() { println!("no tmux panes"); return Ok(()); } println!("{:<22} {:<10} {:<12} COMMAND", "TARGET", "AGENT", "STATE"); for pane in panes { println!( "{:<22} {:<10} {:<12} {}", pane.target, pane.agent.map(detect_core::agent_label).unwrap_or("-"), if pane.written_state.is_empty() { "-" } else { &pane.written_state }, pane.current_command, ); } Ok(()) }