Install hooks globally to `~/.claude/settings.json`. # Returns The number of hooks installed (0 if already up to date).
(&self, force: bool)
| 76 | /// |
| 77 | /// The number of hooks installed (0 if already up to date). |
| 78 | pub fn install_global(&self, force: bool) -> AgentResult<usize> { |
| 79 | let settings_path = |
| 80 | Self::global_settings_path().ok_or_else(|| AgentError::ConfigError { |
| 81 | operation: "resolve home".to_string(), |
| 82 | path: PathBuf::from("~/.claude/settings.json"), |
| 83 | reason: "Could not determine home directory".to_string(), |
| 84 | })?; |
| 85 | |
| 86 | // Create ~/.claude/ if needed |
| 87 | if let Some(parent) = settings_path.parent() { |
| 88 | if !parent.exists() { |
| 89 | std::fs::create_dir_all(parent).map_err(|e| AgentError::ConfigError { |
| 90 | operation: "create directory".to_string(), |
| 91 | path: parent.to_path_buf(), |
| 92 | reason: e.to_string(), |
| 93 | })?; |
| 94 | } |
| 95 | } |
| 96 | |
| 97 | let (mut raw, mut hooks) = settings::read_settings(&settings_path)?; |
| 98 | |
| 99 | // If forcing, remove existing atomic hooks first |
| 100 | if force { |
| 101 | settings::remove_atomic_hooks(&mut hooks.session_start); |
| 102 | settings::remove_atomic_hooks(&mut hooks.session_end); |
| 103 | settings::remove_atomic_hooks(&mut hooks.stop); |
| 104 | settings::remove_atomic_hooks(&mut hooks.user_prompt_submit); |
| 105 | settings::remove_atomic_hooks(&mut hooks.pre_tool_use); |
| 106 | settings::remove_atomic_hooks(&mut hooks.post_tool_use); |
| 107 | } |
| 108 | |
| 109 | let count = install_hooks_into(&mut hooks, &settings_path)?; |
| 110 | |
| 111 | // Add permissions.deny rule |
| 112 | let permissions_changed = settings::ensure_deny_rule(&mut raw); |
| 113 | |
| 114 | if count == 0 && !permissions_changed { |
| 115 | return Ok(0); |
| 116 | } |
| 117 | |
| 118 | // Serialize hooks back into raw settings |
| 119 | let hooks_val = serde_json::to_value(&hooks).map_err(|e| AgentError::ConfigError { |
| 120 | operation: "serialize hooks".to_string(), |
| 121 | path: settings_path.clone(), |
| 122 | reason: e.to_string(), |
| 123 | })?; |
| 124 | raw.insert("hooks".to_string(), hooks_val); |
| 125 | settings::write_settings(&settings_path, &raw)?; |
| 126 | |
| 127 | Ok(count) |
| 128 | } |
| 129 | |
| 130 | /// Remove hooks from the global `~/.claude/settings.json`. |
| 131 | pub fn uninstall_global(&self) -> AgentResult<()> { |
nothing calls this directly
no test coverage detected