MCPcopy Create free account
hub / github.com/colbymchenry/codegraph / removeHookCommandsMatching

Function removeHookCommandsMatching

src/installer/targets/claude.ts:334–378  ·  view source on GitHub ↗

* Remove stale codegraph auto-sync hooks from Claude `settings.json`. * * Surgical at the individual-command level: only entries matching * `isLegacyCodegraphHookCommand` are dropped, so a sibling hook sharing * a matcher group (or the Stop event) with ours survives. We prune a * matcher group

(
  loc: Location,
  match: (command: unknown) => boolean,
)

Source from the content-addressed store, hash-verified

332 * `install` (an upgrade self-heals) and `uninstall`.
333 */
334function removeHookCommandsMatching(
335 loc: Location,
336 match: (command: unknown) => boolean,
337): WriteResult['files'][number] {
338 const file = settingsJsonPath(loc);
339 if (!fs.existsSync(file)) return { path: file, action: 'not-found' };
340
341 const settings = readJsonFile(file);
342 const hooks = settings.hooks;
343 if (!hooks || typeof hooks !== 'object' || Array.isArray(hooks)) {
344 return { path: file, action: 'unchanged' };
345 }
346
347 // Pass 1: drop matching command(s) from inside every matcher group.
348 let removedAny = false;
349 for (const event of Object.keys(hooks)) {
350 const groups = hooks[event];
351 if (!Array.isArray(groups)) continue;
352 for (const group of groups) {
353 if (!group || !Array.isArray(group.hooks)) continue;
354 const before = group.hooks.length;
355 group.hooks = group.hooks.filter((h: any) => !match(h?.command));
356 if (group.hooks.length !== before) removedAny = true;
357 }
358 }
359
360 if (!removedAny) return { path: file, action: 'unchanged' };
361
362 // Pass 2: prune empty matcher groups, then events with no groups left,
363 // then an empty top-level `hooks`. Guarded by `removedAny` so we never
364 // restructure a settings.json that had no matching hooks. Sibling hooks
365 // (a different command in the group, or a different event) survive.
366 for (const event of Object.keys(hooks)) {
367 const groups = hooks[event];
368 if (!Array.isArray(groups)) continue;
369 hooks[event] = groups.filter(
370 (g: any) => !(g && Array.isArray(g.hooks) && g.hooks.length === 0),
371 );
372 if (hooks[event].length === 0) delete hooks[event];
373 }
374 if (Object.keys(hooks).length === 0) delete settings.hooks;
375
376 writeJsonFile(file, settings);
377 return { path: file, action: 'removed' };
378}
379
380/**
381 * Remove stale codegraph auto-sync hooks (`mark-dirty` / `sync-if-dirty`) that a

Callers 2

cleanupLegacyHooksFunction · 0.85
removePromptHookEntryFunction · 0.85

Calls 3

readJsonFileFunction · 0.90
writeJsonFileFunction · 0.90
settingsJsonPathFunction · 0.70

Tested by

no test coverage detected