From ba1fb7eeb3855db50eff5cfb5999d77ffd66f17f Mon Sep 17 00:00:00 2001 From: kaitranntt Date: Sun, 25 Jan 2026 20:26:27 -0500 Subject: [PATCH] refactor(uninstall): stop modifying global settings.json - remove removeHookConfig() call from uninstallWebSearchHook() - add removeMigrationMarker() cleanup - update postuninstall.js to only clean CCS files - global ~/.claude/settings.json is never touched --- scripts/postuninstall.js | 56 +++++++++------------------ src/utils/websearch/hook-installer.ts | 13 +++++-- 2 files changed, 28 insertions(+), 41 deletions(-) diff --git a/scripts/postuninstall.js b/scripts/postuninstall.js index d7e1181e..4cd31d00 100644 --- a/scripts/postuninstall.js +++ b/scripts/postuninstall.js @@ -2,7 +2,9 @@ /** * CCS Postuninstall Script * - * Cleans up WebSearch hook from ~/.claude/settings.json after npm uninstall. + * Cleans up CCS-specific files after npm uninstall. + * Does NOT touch global ~/.claude/settings.json (hooks are per-profile now). + * * Self-contained, no external dependencies. */ @@ -10,51 +12,29 @@ const fs = require('fs'); const path = require('path'); const os = require('os'); -const SETTINGS_PATH = path.join(os.homedir(), '.claude', 'settings.json'); +const CCS_DIR = path.join(os.homedir(), '.ccs'); +const HOOKS_DIR = path.join(CCS_DIR, 'hooks'); +const MIGRATION_MARKER = path.join(CCS_DIR, '.hook-migrated'); -function cleanupHook() { +function cleanupCcsFiles() { try { - if (!fs.existsSync(SETTINGS_PATH)) { - return; // Nothing to clean + // Remove WebSearch hook file + const hookPath = path.join(HOOKS_DIR, 'websearch-transformer.cjs'); + if (fs.existsSync(hookPath)) { + fs.unlinkSync(hookPath); } - const content = fs.readFileSync(SETTINGS_PATH, 'utf8'); - let settings; - try { - settings = JSON.parse(content); - } catch { - return; // Malformed JSON, don't touch + // Remove migration marker (so fresh install re-runs migration) + if (fs.existsSync(MIGRATION_MARKER)) { + fs.unlinkSync(MIGRATION_MARKER); } - const hooks = settings.hooks; - if (!hooks?.PreToolUse) { - return; // No hooks to remove - } - - const originalLength = hooks.PreToolUse.length; - hooks.PreToolUse = hooks.PreToolUse.filter((h) => { - if (h.matcher !== 'WebSearch') return true; - const command = h.hooks?.[0]?.command; - if (!command) return true; - return !command.includes('.ccs/hooks/websearch-transformer'); - }); - - if (hooks.PreToolUse.length === originalLength) { - return; // Nothing changed - } - - // Clean up empty structures - if (hooks.PreToolUse.length === 0) { - delete hooks.PreToolUse; - } - if (Object.keys(hooks).length === 0) { - delete settings.hooks; - } - - fs.writeFileSync(SETTINGS_PATH, JSON.stringify(settings, null, 2), 'utf8'); + // Note: Do NOT touch ~/.claude/settings.json + // Per-profile hooks in ~/.ccs/*.settings.json will be cleaned up + // when the user removes ~/.ccs/ directory. } catch { // Silent fail - not critical } } -cleanupHook(); +cleanupCcsFiles(); diff --git a/src/utils/websearch/hook-installer.ts b/src/utils/websearch/hook-installer.ts index a9efbf06..8a0c3234 100644 --- a/src/utils/websearch/hook-installer.ts +++ b/src/utils/websearch/hook-installer.ts @@ -11,7 +11,8 @@ import * as path from 'path'; import * as os from 'os'; import { info, warn } from '../ui'; import { getWebSearchConfig } from '../../config/unified-config-loader'; -import { getHookPath, ensureHookConfig, removeHookConfig } from './hook-config'; +import { getHookPath, ensureHookConfig } from './hook-config'; +import { removeMigrationMarker } from './profile-hook-injector'; // Re-export from hook-config for backward compatibility export { getHookPath, getWebSearchHookConfig } from './hook-config'; @@ -102,6 +103,9 @@ export function installWebSearchHook(): boolean { /** * Uninstall WebSearch hook from ~/.ccs/hooks/ * + * Note: Does NOT touch global ~/.claude/settings.json. + * Profile-specific hooks are removed when ~/.ccs/ is deleted. + * * @returns true if hook uninstalled successfully */ export function uninstallWebSearchHook(): boolean { @@ -115,8 +119,11 @@ export function uninstallWebSearchHook(): boolean { } } - // Remove from settings.json - removeHookConfig(); + // Remove migration marker (so fresh install re-runs migration) + removeMigrationMarker(); + + // Note: Do NOT call removeHookConfig() - global settings should not be touched. + // Per-profile hooks in ~/.ccs/*.settings.json are cleaned up when ~/.ccs/ is deleted. return true; } catch (error) {