Skip to main content

cli_denoiser/hooks/
mod.rs

1pub mod claude;
2pub mod codex;
3pub mod gemini;
4
5use std::path::PathBuf;
6
7/// Result of a hook installation attempt.
8#[derive(Debug)]
9pub struct InstallResult {
10    pub agent: String,
11    pub config_path: PathBuf,
12    pub status: InstallStatus,
13}
14
15#[derive(Debug)]
16pub enum InstallStatus {
17    Installed,
18    AlreadyInstalled,
19    ConfigNotFound,
20    Failed(String),
21}
22
23impl std::fmt::Display for InstallResult {
24    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25        let icon = match &self.status {
26            InstallStatus::Installed => "OK",
27            InstallStatus::AlreadyInstalled => "SKIP",
28            InstallStatus::ConfigNotFound => "MISS",
29            InstallStatus::Failed(_) => "FAIL",
30        };
31        let detail = match &self.status {
32            InstallStatus::Installed => "hook installed".to_string(),
33            InstallStatus::AlreadyInstalled => "already installed".to_string(),
34            InstallStatus::ConfigNotFound => "config not found".to_string(),
35            InstallStatus::Failed(e) => format!("error: {e}"),
36        };
37        write!(
38            f,
39            "  [{icon}] {}: {} ({})",
40            self.agent,
41            detail,
42            self.config_path.display()
43        )
44    }
45}
46
47/// Install hooks for all supported agents.
48/// Returns results for each agent (never fails entirely).
49#[must_use]
50pub fn install_all() -> Vec<InstallResult> {
51    vec![claude::install(), codex::install(), gemini::install()]
52}
53
54/// Uninstall hooks from all supported agents.
55#[must_use]
56pub fn uninstall_all() -> Vec<InstallResult> {
57    vec![claude::uninstall(), codex::uninstall(), gemini::uninstall()]
58}