cc-hook-registry 3.0.0 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -1
- package/index.mjs +98 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -19,11 +19,39 @@ npx cc-hook-registry search database
|
|
|
19
19
|
```bash
|
|
20
20
|
npx cc-hook-registry search <keyword> # Find hooks by keyword
|
|
21
21
|
npx cc-hook-registry browse [category] # Browse by category
|
|
22
|
-
npx cc-hook-registry install <id> # Install a hook
|
|
22
|
+
npx cc-hook-registry install <id> # Install a hook (direct download)
|
|
23
|
+
npx cc-hook-registry recommend # Recommend hooks for your project
|
|
23
24
|
npx cc-hook-registry info <id> # Show hook details
|
|
24
25
|
npx cc-hook-registry stats # Registry statistics
|
|
25
26
|
```
|
|
26
27
|
|
|
28
|
+
### recommend
|
|
29
|
+
|
|
30
|
+
Scans your project for `package.json`, `requirements.txt`, `Dockerfile`, `.env`, `Gemfile`, `artisan` and recommends hooks based on your tech stack:
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
npx cc-hook-registry recommend
|
|
34
|
+
|
|
35
|
+
✓ destructive-guard (installed)
|
|
36
|
+
Essential — prevents rm -rf disasters
|
|
37
|
+
|
|
38
|
+
○ auto-approve-build
|
|
39
|
+
Node.js project detected
|
|
40
|
+
Install: npx cc-hook-registry install auto-approve-build
|
|
41
|
+
|
|
42
|
+
○ block-database-wipe
|
|
43
|
+
Prisma detected — protect against migrate reset
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### install (direct download)
|
|
47
|
+
|
|
48
|
+
Hooks are downloaded directly from GitHub — no `cc-safe-setup` dependency needed:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
npx cc-hook-registry install block-database-wipe
|
|
52
|
+
# Downloads script, saves to ~/.claude/hooks/, registers in settings.json
|
|
53
|
+
```
|
|
54
|
+
|
|
27
55
|
## Categories
|
|
28
56
|
|
|
29
57
|
| Category | Hooks | What They Do |
|
package/index.mjs
CHANGED
|
@@ -113,6 +113,8 @@ if (!command || command === '--help' || command === '-h') {
|
|
|
113
113
|
install <id> Install a hook
|
|
114
114
|
info <id> Show hook details
|
|
115
115
|
recommend Recommend hooks for current project
|
|
116
|
+
uninstall <id> Remove an installed hook
|
|
117
|
+
outdated Check installed hooks for updates
|
|
116
118
|
stats Registry statistics
|
|
117
119
|
|
|
118
120
|
Examples:
|
|
@@ -367,6 +369,102 @@ else if (command === 'recommend') {
|
|
|
367
369
|
console.log();
|
|
368
370
|
}
|
|
369
371
|
|
|
372
|
+
else if (command === 'uninstall') {
|
|
373
|
+
const id = args[1];
|
|
374
|
+
if (!id) { console.log(c.red + ' Usage: cc-hook-registry uninstall <id>' + c.reset); process.exit(1); }
|
|
375
|
+
|
|
376
|
+
const hookPath = join(HOOKS_DIR, id + '.sh');
|
|
377
|
+
console.log();
|
|
378
|
+
|
|
379
|
+
if (!existsSync(hookPath)) {
|
|
380
|
+
console.log(c.red + ' Hook not installed: ' + id + c.reset);
|
|
381
|
+
process.exit(1);
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// Remove script
|
|
385
|
+
const { unlinkSync } = await import('fs');
|
|
386
|
+
unlinkSync(hookPath);
|
|
387
|
+
console.log(c.green + ' ✓ Removed: ' + hookPath + c.reset);
|
|
388
|
+
|
|
389
|
+
// Remove from settings.json
|
|
390
|
+
if (existsSync(SETTINGS_PATH)) {
|
|
391
|
+
try {
|
|
392
|
+
const settings = JSON.parse(readFileSync(SETTINGS_PATH, 'utf-8'));
|
|
393
|
+
for (const trigger of Object.keys(settings.hooks || {})) {
|
|
394
|
+
settings.hooks[trigger] = settings.hooks[trigger].filter(entry =>
|
|
395
|
+
!(entry.hooks || []).some(h => (h.command || '').includes(id))
|
|
396
|
+
);
|
|
397
|
+
if (settings.hooks[trigger].length === 0) delete settings.hooks[trigger];
|
|
398
|
+
}
|
|
399
|
+
writeFileSync(SETTINGS_PATH, JSON.stringify(settings, null, 2));
|
|
400
|
+
console.log(c.green + ' ✓ Removed from settings.json' + c.reset);
|
|
401
|
+
} catch {}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
console.log(c.dim + ' Restart Claude Code to take effect.' + c.reset);
|
|
405
|
+
console.log();
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
else if (command === 'outdated') {
|
|
409
|
+
console.log();
|
|
410
|
+
console.log(c.bold + ' Checking installed hooks for updates...' + c.reset);
|
|
411
|
+
console.log();
|
|
412
|
+
|
|
413
|
+
if (!existsSync(HOOKS_DIR)) {
|
|
414
|
+
console.log(c.dim + ' No hooks installed.' + c.reset);
|
|
415
|
+
process.exit(0);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
const { readdirSync } = await import('fs');
|
|
419
|
+
const installed = readdirSync(HOOKS_DIR).filter(f => f.endsWith('.sh'));
|
|
420
|
+
let outdated = 0;
|
|
421
|
+
let upToDate = 0;
|
|
422
|
+
let unknown = 0;
|
|
423
|
+
|
|
424
|
+
for (const file of installed) {
|
|
425
|
+
const name = file.replace('.sh', '');
|
|
426
|
+
const hook = REGISTRY.find(h => h.id === name);
|
|
427
|
+
const localContent = readFileSync(join(HOOKS_DIR, file), 'utf-8');
|
|
428
|
+
const localLines = localContent.split('\n').length;
|
|
429
|
+
|
|
430
|
+
if (!hook) {
|
|
431
|
+
// Custom hook, not in registry
|
|
432
|
+
console.log(' ' + c.dim + '?' + c.reset + ' ' + file + c.dim + ' (custom, not in registry)' + c.reset);
|
|
433
|
+
unknown++;
|
|
434
|
+
continue;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
// Check against GitHub for cc-safe-setup hooks
|
|
438
|
+
if (hook.source === 'cc-safe-setup' && hook.install.includes('--install-example')) {
|
|
439
|
+
try {
|
|
440
|
+
const rawUrl = `https://raw.githubusercontent.com/yurukusa/cc-safe-setup/main/examples/${name}.sh`;
|
|
441
|
+
const remote = execSync(`curl -sL "${rawUrl}" 2>/dev/null`, { encoding: 'utf-8', timeout: 5000 });
|
|
442
|
+
const remoteLines = remote.split('\n').length;
|
|
443
|
+
|
|
444
|
+
if (remote.trim() === localContent.trim()) {
|
|
445
|
+
console.log(' ' + c.green + '✓' + c.reset + ' ' + file + c.dim + ' (up to date)' + c.reset);
|
|
446
|
+
upToDate++;
|
|
447
|
+
} else {
|
|
448
|
+
const diff = remoteLines - localLines;
|
|
449
|
+
console.log(' ' + c.yellow + '↑' + c.reset + ' ' + file + c.yellow + ' (update available: ' + (diff > 0 ? '+' : '') + diff + ' lines)' + c.reset);
|
|
450
|
+
console.log(' ' + c.dim + 'Update: npx cc-hook-registry install ' + name + c.reset);
|
|
451
|
+
outdated++;
|
|
452
|
+
}
|
|
453
|
+
} catch {
|
|
454
|
+
console.log(' ' + c.dim + '?' + c.reset + ' ' + file + c.dim + ' (could not check)' + c.reset);
|
|
455
|
+
unknown++;
|
|
456
|
+
}
|
|
457
|
+
} else {
|
|
458
|
+
console.log(' ' + c.dim + '—' + c.reset + ' ' + file + c.dim + ' (external: ' + hook.source + ')' + c.reset);
|
|
459
|
+
unknown++;
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
console.log();
|
|
464
|
+
console.log(' ' + c.green + upToDate + ' up to date' + c.reset + ' ' + c.yellow + outdated + ' outdated' + c.reset + ' ' + c.dim + unknown + ' unchecked' + c.reset);
|
|
465
|
+
console.log();
|
|
466
|
+
}
|
|
467
|
+
|
|
370
468
|
else if (command === 'stats') {
|
|
371
469
|
const categories = {};
|
|
372
470
|
const sources = {};
|