@@ -7646,6 +7646,93 @@ static void uninstall_tiered_profile_prompts(const char *label, const char *veri
76467646 cbm_graph_profile_dialect_t dialect,
76477647 const char *legacy_verify_content, bool dry_run);
76487648
7649+ static int remove_claude_owned_hook_scripts(const char *config_dir, const char *binary_path,
7650+ bool uninstall) {
7651+ char current_gate[CLI_BUF_8K];
7652+ char current_session[CLI_BUF_8K];
7653+ char current_subagent[CLI_BUF_8K];
7654+ char released_gate[CLI_BUF_8K];
7655+ const char *const gate_legacy[] = {released_gate};
7656+ const char *const session_legacy[] = {cmm_released_session_script};
7657+ const char *const subagent_legacy[] = {cmm_released_subagent_script};
7658+ size_t gate_legacy_count =
7659+ cbm_build_released_gate_script(binary_path, released_gate, sizeof(released_gate)) == CLI_OK
7660+ ? 1U
7661+ : 0U;
7662+ static const struct {
7663+ const char *name;
7664+ const char *legacy_name;
7665+ const char *prefix;
7666+ } hook_types[] = {
7667+ {CMM_HOOK_GATE_SCRIPT, CMM_HOOK_GATE_SCRIPT_LEGACY, cmm_gate_script_prefix},
7668+ {CMM_SESSION_REMINDER_SCRIPT, CMM_SESSION_REMINDER_SCRIPT_LEGACY,
7669+ cmm_session_script_prefix},
7670+ {CMM_SUBAGENT_REMINDER_SCRIPT, CMM_SUBAGENT_REMINDER_SCRIPT_LEGACY,
7671+ cmm_subagent_script_prefix},
7672+ };
7673+ struct {
7674+ const char *name;
7675+ const char *legacy_name;
7676+ const char *current;
7677+ const char *const *legacy;
7678+ size_t legacy_count;
7679+ bool current_valid;
7680+ } owned_scripts[] = {
7681+ {hook_types[0].name, hook_types[0].legacy_name, current_gate, gate_legacy,
7682+ gate_legacy_count,
7683+ cbm_build_current_hook_script(hook_types[0].prefix, binary_path, current_gate,
7684+ sizeof(current_gate)) == CLI_OK},
7685+ {hook_types[1].name, hook_types[1].legacy_name, current_session, session_legacy, 1U,
7686+ cbm_build_current_hook_script(hook_types[1].prefix, binary_path, current_session,
7687+ sizeof(current_session)) == CLI_OK},
7688+ {hook_types[2].name, hook_types[2].legacy_name, current_subagent, subagent_legacy, 1U,
7689+ cbm_build_current_hook_script(hook_types[2].prefix, binary_path, current_subagent,
7690+ sizeof(current_subagent)) == CLI_OK},
7691+ };
7692+ char hooks_dir[CLI_BUF_1K];
7693+ int hooks_written = snprintf(hooks_dir, sizeof(hooks_dir), "%s/hooks", config_dir);
7694+ bool hooks_dir_valid = hooks_written > 0 && (size_t)hooks_written < sizeof(hooks_dir);
7695+ int rc = CLI_OK;
7696+ const char *op = uninstall ? "hook_script_uninstall" : "hook_script_disable";
7697+ for (size_t i = 0; i < sizeof(owned_scripts) / sizeof(owned_scripts[0]); i++) {
7698+ char script_path[CLI_BUF_1K];
7699+ int script_written = hooks_dir_valid ? snprintf(script_path, sizeof(script_path), "%s/%s",
7700+ hooks_dir, owned_scripts[i].name)
7701+ : CLI_ERR;
7702+ bool script_path_valid = script_written > 0 && (size_t)script_written < sizeof(script_path);
7703+ if (!owned_scripts[i].current_valid) {
7704+ record_agent_config_error(uninstall, "Claude Code", op, owned_scripts[i].name);
7705+ rc = CLI_ERR;
7706+ continue;
7707+ }
7708+ if (!script_path_valid ||
7709+ cbm_remove_owned_hook_script(script_path, owned_scripts[i].current,
7710+ owned_scripts[i].legacy,
7711+ owned_scripts[i].legacy_count) < CLI_OK) {
7712+ record_agent_config_error(uninstall, "Claude Code", op,
7713+ script_path_valid ? script_path : owned_scripts[i].name);
7714+ rc = CLI_ERR;
7715+ }
7716+ #ifdef _WIN32
7717+ if (!hooks_dir_valid ||
7718+ cbm_remove_owned_legacy_hook_script(hooks_dir, owned_scripts[i].legacy_name,
7719+ owned_scripts[i].current, owned_scripts[i].legacy,
7720+ owned_scripts[i].legacy_count) != CLI_OK) {
7721+ char legacy_path[CLI_BUF_1K];
7722+ int written = hooks_dir_valid ? snprintf(legacy_path, sizeof(legacy_path), "%s/%s",
7723+ hooks_dir, owned_scripts[i].legacy_name)
7724+ : CLI_ERR;
7725+ record_agent_config_error(uninstall, "Claude Code", "legacy_hook_script_uninstall",
7726+ written > 0 && (size_t)written < sizeof(legacy_path)
7727+ ? legacy_path
7728+ : owned_scripts[i].legacy_name);
7729+ rc = CLI_ERR;
7730+ }
7731+ #endif
7732+ }
7733+ return rc;
7734+ }
7735+
76497736static void install_claude_code_config(const char *home, const char *binary_path, bool force,
76507737 bool dry_run) {
76517738 char config_dir[CLI_BUF_1K];
@@ -7735,6 +7822,7 @@ static void install_claude_code_config(const char *home, const char *binary_path
77357822 if (cbm_remove_claude_subagent_hooks(settings_path) != CLI_OK) {
77367823 record_agent_config_error(false, "Claude Code", "hook_disable", settings_path);
77377824 }
7825+ remove_claude_owned_hook_scripts(config_dir, binary_path, false);
77387826 }
77397827 print_hooks_skipped();
77407828 goto claude_hooks_done;
@@ -10707,86 +10795,7 @@ static void uninstall_claude_code(const char *home, bool dry_run) {
1070710795 record_agent_config_error(true, "Claude Code", "subagent_hook_uninstall",
1070810796 settings_path);
1070910797 }
10710- char current_gate[CLI_BUF_8K];
10711- char current_session[CLI_BUF_8K];
10712- char current_subagent[CLI_BUF_8K];
10713- char released_gate[CLI_BUF_8K];
10714- const char *const gate_legacy[] = {released_gate};
10715- const char *const session_legacy[] = {cmm_released_session_script};
10716- const char *const subagent_legacy[] = {cmm_released_subagent_script};
10717- size_t gate_legacy_count = cbm_build_released_gate_script(installed_binary, released_gate,
10718- sizeof(released_gate)) == CLI_OK
10719- ? 1U
10720- : 0U;
10721- static const struct {
10722- const char *name;
10723- const char *legacy_name;
10724- const char *prefix;
10725- } hook_types[] = {
10726- {CMM_HOOK_GATE_SCRIPT, CMM_HOOK_GATE_SCRIPT_LEGACY, cmm_gate_script_prefix},
10727- {CMM_SESSION_REMINDER_SCRIPT, CMM_SESSION_REMINDER_SCRIPT_LEGACY,
10728- cmm_session_script_prefix},
10729- {CMM_SUBAGENT_REMINDER_SCRIPT, CMM_SUBAGENT_REMINDER_SCRIPT_LEGACY,
10730- cmm_subagent_script_prefix},
10731- };
10732- struct {
10733- const char *name;
10734- const char *legacy_name;
10735- const char *current;
10736- const char *const *legacy;
10737- size_t legacy_count;
10738- bool current_valid;
10739- } owned_scripts[] = {
10740- {hook_types[0].name, hook_types[0].legacy_name, current_gate, gate_legacy,
10741- gate_legacy_count,
10742- cbm_build_current_hook_script(hook_types[0].prefix, installed_binary, current_gate,
10743- sizeof(current_gate)) == CLI_OK},
10744- {hook_types[1].name, hook_types[1].legacy_name, current_session, session_legacy, 1U,
10745- cbm_build_current_hook_script(hook_types[1].prefix, installed_binary, current_session,
10746- sizeof(current_session)) == CLI_OK},
10747- {hook_types[2].name, hook_types[2].legacy_name, current_subagent, subagent_legacy, 1U,
10748- cbm_build_current_hook_script(hook_types[2].prefix, installed_binary, current_subagent,
10749- sizeof(current_subagent)) == CLI_OK},
10750- };
10751- char hooks_dir[CLI_BUF_1K];
10752- int hooks_written = snprintf(hooks_dir, sizeof(hooks_dir), "%s/hooks", config_dir);
10753- bool hooks_dir_valid = hooks_written > 0 && (size_t)hooks_written < sizeof(hooks_dir);
10754- for (size_t i = 0; i < sizeof(owned_scripts) / sizeof(owned_scripts[0]); i++) {
10755- char script_path[CLI_BUF_1K];
10756- int script_written = hooks_dir_valid
10757- ? snprintf(script_path, sizeof(script_path), "%s/%s",
10758- hooks_dir, owned_scripts[i].name)
10759- : CLI_ERR;
10760- bool script_path_valid =
10761- script_written > 0 && (size_t)script_written < sizeof(script_path);
10762- if (!owned_scripts[i].current_valid) {
10763- record_agent_config_error(true, "Claude Code", "hook_script_uninstall",
10764- owned_scripts[i].name);
10765- continue;
10766- }
10767- if (!script_path_valid ||
10768- cbm_remove_owned_hook_script(script_path, owned_scripts[i].current,
10769- owned_scripts[i].legacy,
10770- owned_scripts[i].legacy_count) < CLI_OK) {
10771- record_agent_config_error(true, "Claude Code", "hook_script_uninstall",
10772- script_path_valid ? script_path : owned_scripts[i].name);
10773- }
10774- #ifdef _WIN32
10775- if (!hooks_dir_valid ||
10776- cbm_remove_owned_legacy_hook_script(
10777- hooks_dir, owned_scripts[i].legacy_name, owned_scripts[i].current,
10778- owned_scripts[i].legacy, owned_scripts[i].legacy_count) != CLI_OK) {
10779- char legacy_path[CLI_BUF_1K];
10780- int written = hooks_dir_valid ? snprintf(legacy_path, sizeof(legacy_path), "%s/%s",
10781- hooks_dir, owned_scripts[i].legacy_name)
10782- : CLI_ERR;
10783- record_agent_config_error(true, "Claude Code", "legacy_hook_script_uninstall",
10784- written > 0 && (size_t)written < sizeof(legacy_path)
10785- ? legacy_path
10786- : owned_scripts[i].legacy_name);
10787- }
10788- #endif
10789- }
10798+ remove_claude_owned_hook_scripts(config_dir, installed_binary, true);
1079010799 }
1079110800 printf(" removed PreToolUse + SessionStart + SubagentStart hooks\n");
1079210801}
0 commit comments