From 4c9409a785162555d973557acb10ccd40a60b3f1 Mon Sep 17 00:00:00 2001 From: Miguel Palhas Date: Mon, 24 Aug 2026 22:14:15 +0100 Subject: [PATCH] feat(maestro): add [hooks] auto_install config section --- crates/maestro-config/src/lib.rs | 38 ++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/crates/maestro-config/src/lib.rs b/crates/maestro-config/src/lib.rs index e7d6520..87b2bb5 100644 --- a/crates/maestro-config/src/lib.rs +++ b/crates/maestro-config/src/lib.rs @@ -64,6 +64,24 @@ pub struct MaestroConfigFile { pub tui: TuiSection, #[serde(default)] pub spawn: SpawnSection, + #[serde(default)] + pub hooks: HooksSection, +} + +/// `[hooks]` — agent-hook installation settings (#106). +#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize)] +pub struct HooksSection { + /// Whether the daemon installs the Claude Code activity hook into + /// `~/.claude/settings.json` on first start when no maestro hook is + /// there yet. Default `true`; set `auto_install = false` to opt out. + #[serde(default)] + pub auto_install: Option, +} + +impl HooksSection { + pub fn auto_install(&self) -> bool { + self.auto_install.unwrap_or(true) + } } #[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize)] @@ -375,6 +393,26 @@ mod tests { assert_eq!(cfg, MaestroConfigFile::default()); } + #[test] + fn hooks_auto_install_defaults_true_and_is_opt_out() { + // Absent file / absent [hooks] ⇒ auto_install on. + assert!(HooksSection::default().auto_install()); + let dir = tempfile::tempdir().unwrap(); + let path = dir.path().join("config.toml"); + std::fs::write(&path, "").unwrap(); + assert!(MaestroConfigFile::load(&path).unwrap().hooks.auto_install()); + + std::fs::write( + &path, + r#" +[hooks] +auto_install = false +"#, + ) + .unwrap(); + assert!(!MaestroConfigFile::load(&path).unwrap().hooks.auto_install()); + } + #[test] fn spawn_presets_default_to_builtins_plus_custom() { // Absent [spawn].presets → built-ins, with the implicit custom tile last.