cc-hook-registry 1.0.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.
Files changed (3) hide show
  1. package/README.md +64 -0
  2. package/index.mjs +225 -0
  3. package/package.json +26 -0
package/README.md ADDED
@@ -0,0 +1,64 @@
1
+ # cc-hook-registry
2
+
3
+ Search, browse, and install Claude Code hooks from the community.
4
+
5
+ ```bash
6
+ npx cc-hook-registry search database
7
+ ```
8
+
9
+ ```
10
+ Search: "database" — 1 result(s)
11
+
12
+ block-database-wipe [safety]
13
+ Blocks migrate:fresh, DROP DATABASE, prisma migrate reset
14
+ Install: npx cc-safe-setup --install-example block-database-wipe
15
+ ```
16
+
17
+ ## Commands
18
+
19
+ ```bash
20
+ npx cc-hook-registry search <keyword> # Find hooks by keyword
21
+ npx cc-hook-registry browse [category] # Browse by category
22
+ npx cc-hook-registry install <id> # Install a hook
23
+ npx cc-hook-registry info <id> # Show hook details
24
+ npx cc-hook-registry stats # Registry statistics
25
+ ```
26
+
27
+ ## Categories
28
+
29
+ | Category | Hooks | What They Do |
30
+ |----------|-------|-------------|
31
+ | safety | 11 | Block destructive commands, protect files |
32
+ | quality | 4 | Syntax checks, commit quality, edit validation |
33
+ | utility | 3 | Cleanup, debugging, session handoff |
34
+ | monitoring | 2 | Context window, cost tracking |
35
+ | approve | 1 | Auto-approve safe compound commands |
36
+ | ux | 1 | Desktop notifications |
37
+ | framework | 1 | Python hook framework |
38
+ | security | 1 | Prompt injection defense |
39
+
40
+ ## 24 Hooks
41
+
42
+ The registry includes hooks from:
43
+ - **cc-safe-setup** (21 hooks) — `npx cc-safe-setup`
44
+ - **claude-code-safety-net** (1,185★) — TypeScript safety hooks
45
+ - **claude-code-hooks-mastery** (3,386★) — Python hook framework
46
+ - **claude-hooks** by lasso-security — Prompt injection defense
47
+
48
+ ## How It Works
49
+
50
+ The registry is a curated list embedded in the package. No server, no API calls, no network required. Install commands run `npx cc-safe-setup --install-example` for compatible hooks.
51
+
52
+ ## Submit Your Hook
53
+
54
+ Want to add your hook to the registry? Open a PR on [GitHub](https://github.com/yurukusa/cc-hook-registry) adding an entry to the REGISTRY array in `index.mjs`.
55
+
56
+ ## Related
57
+
58
+ - [cc-safe-setup](https://github.com/yurukusa/cc-safe-setup) — Install 8 safety hooks in one command
59
+ - [cc-hook-test](https://github.com/yurukusa/cc-hook-test) — Test runner for hooks
60
+ - [COOKBOOK](https://github.com/yurukusa/claude-code-hooks/blob/main/COOKBOOK.md) — 25 hook recipes
61
+
62
+ ## License
63
+
64
+ MIT
package/index.mjs ADDED
@@ -0,0 +1,225 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * cc-hook-registry — Search, browse, and install Claude Code hooks from the community
5
+ *
6
+ * Usage:
7
+ * npx cc-hook-registry search <keyword> Find hooks by keyword
8
+ * npx cc-hook-registry browse [category] Browse all hooks by category
9
+ * npx cc-hook-registry install <id> Install a hook from the registry
10
+ * npx cc-hook-registry info <id> Show hook details
11
+ * npx cc-hook-registry submit Submit your hook to the registry
12
+ * npx cc-hook-registry stats Registry statistics
13
+ *
14
+ * The registry is a JSON file hosted on GitHub. No server needed.
15
+ * Hooks are fetched directly from their source repositories.
16
+ */
17
+
18
+ import { readFileSync, writeFileSync, mkdirSync, existsSync, chmodSync } from 'fs';
19
+ import { join, dirname } from 'path';
20
+ import { homedir } from 'os';
21
+ import { execSync } from 'child_process';
22
+
23
+ const HOME = homedir();
24
+ const HOOKS_DIR = join(HOME, '.claude', 'hooks');
25
+ const SETTINGS_PATH = join(HOME, '.claude', 'settings.json');
26
+ const CACHE_PATH = join(HOME, '.claude', 'hook-registry-cache.json');
27
+ const CACHE_TTL = 3600000; // 1 hour
28
+
29
+ const c = {
30
+ reset: '\x1b[0m', bold: '\x1b[1m', dim: '\x1b[2m',
31
+ red: '\x1b[31m', green: '\x1b[32m', yellow: '\x1b[33m',
32
+ blue: '\x1b[36m',
33
+ };
34
+
35
+ // Registry: curated list of hooks from the community
36
+ // This is the "database" — stored as a constant, updated via npm releases
37
+ const REGISTRY = [
38
+ // cc-safe-setup built-in hooks
39
+ { id: 'destructive-guard', name: 'Destructive Command Blocker', category: 'safety', source: 'cc-safe-setup', trigger: 'PreToolUse', desc: 'Blocks rm -rf /, git reset --hard, git clean, PowerShell Remove-Item', tags: ['rm', 'delete', 'reset', 'clean'], install: 'npx cc-safe-setup' },
40
+ { id: 'branch-guard', name: 'Branch Push Protector', category: 'safety', source: 'cc-safe-setup', trigger: 'PreToolUse', desc: 'Blocks push to main/master and force-push on all branches', tags: ['git', 'push', 'force', 'main'], install: 'npx cc-safe-setup' },
41
+ { id: 'secret-guard', name: 'Secret Leak Prevention', category: 'safety', source: 'cc-safe-setup', trigger: 'PreToolUse', desc: 'Blocks git add .env, credential files', tags: ['env', 'secret', 'credential', 'key'], install: 'npx cc-safe-setup' },
42
+ { id: 'syntax-check', name: 'Post-Edit Syntax Validator', category: 'quality', source: 'cc-safe-setup', trigger: 'PostToolUse', desc: 'Checks Python/Shell/JSON/YAML/JS syntax after edits', tags: ['syntax', 'python', 'json', 'lint'], install: 'npx cc-safe-setup' },
43
+ { id: 'context-monitor', name: 'Context Window Monitor', category: 'monitoring', source: 'cc-safe-setup', trigger: 'PostToolUse', desc: 'Graduated warnings at 40%/25%/20%/15% context remaining', tags: ['context', 'memory', 'compact'], install: 'npx cc-safe-setup' },
44
+
45
+ // cc-safe-setup examples
46
+ { id: 'block-database-wipe', name: 'Database Wipe Protection', category: 'safety', source: 'cc-safe-setup', trigger: 'PreToolUse', desc: 'Blocks migrate:fresh, DROP DATABASE, prisma migrate reset', tags: ['database', 'migrate', 'drop', 'prisma', 'laravel', 'django', 'rails'], install: 'npx cc-safe-setup --install-example block-database-wipe', issue: '#37405' },
47
+ { id: 'compound-command-approver', name: 'Compound Command Approver', category: 'approve', source: 'cc-safe-setup', trigger: 'PreToolUse', desc: 'Auto-approve safe compound commands (cd && git log) that permissions cant match', tags: ['compound', 'cd', 'permission', 'approve'], install: 'npx cc-safe-setup --install-example compound-command-approver', issue: '#30519' },
48
+ { id: 'case-sensitive-guard', name: 'Case-Insensitive FS Guard', category: 'safety', source: 'cc-safe-setup', trigger: 'PreToolUse', desc: 'Detect exFAT/NTFS case collisions before rm/mkdir', tags: ['exfat', 'ntfs', 'case', 'filesystem'], install: 'npx cc-safe-setup --install-example case-sensitive-guard', issue: '#37875' },
49
+ { id: 'tmp-cleanup', name: 'Temp File Cleanup', category: 'utility', source: 'cc-safe-setup', trigger: 'Stop', desc: 'Clean up /tmp/claude-*-cwd files on session end', tags: ['tmp', 'cleanup', 'leak', 'memory'], install: 'npx cc-safe-setup --install-example tmp-cleanup', issue: '#8856' },
50
+ { id: 'loop-detector', name: 'Command Loop Detector', category: 'safety', source: 'cc-safe-setup', trigger: 'PreToolUse', desc: 'Detect and break command repetition loops (warn at 3, block at 5)', tags: ['loop', 'repeat', 'infinite'], install: 'npx cc-safe-setup --install-example loop-detector' },
51
+ { id: 'session-handoff', name: 'Session State Handoff', category: 'utility', source: 'cc-safe-setup', trigger: 'Stop', desc: 'Auto-save git state and session info for next session', tags: ['session', 'handoff', 'compact', 'resume'], install: 'npx cc-safe-setup --install-example session-handoff' },
52
+ { id: 'cost-tracker', name: 'Session Cost Estimator', category: 'monitoring', source: 'cc-safe-setup', trigger: 'PostToolUse', desc: 'Estimate session token cost and warn at thresholds', tags: ['cost', 'token', 'money', 'budget'], install: 'npx cc-safe-setup --install-example cost-tracker' },
53
+ { id: 'diff-size-guard', name: 'Mega-Commit Guard', category: 'quality', source: 'cc-safe-setup', trigger: 'PreToolUse', desc: 'Warn/block when committing too many files at once', tags: ['commit', 'diff', 'large', 'review'], install: 'npx cc-safe-setup --install-example diff-size-guard' },
54
+ { id: 'hook-debug-wrapper', name: 'Hook Debug Wrapper', category: 'utility', source: 'cc-safe-setup', trigger: 'Any', desc: 'Wrap any hook to log input/output/exit/timing', tags: ['debug', 'log', 'test', 'wrapper'], install: 'npx cc-safe-setup --install-example hook-debug-wrapper' },
55
+ { id: 'dependency-audit', name: 'Dependency Audit', category: 'safety', source: 'cc-safe-setup', trigger: 'PreToolUse', desc: 'Warn when installing packages not in manifest', tags: ['npm', 'pip', 'cargo', 'install', 'supply-chain'], install: 'npx cc-safe-setup --install-example dependency-audit' },
56
+ { id: 'deploy-guard', name: 'Deploy Without Commit Guard', category: 'safety', source: 'cc-safe-setup', trigger: 'PreToolUse', desc: 'Block deploy commands when uncommitted changes exist', tags: ['deploy', 'vercel', 'netlify', 'firebase'], install: 'npx cc-safe-setup --install-example deploy-guard', issue: '#37314' },
57
+ { id: 'protect-dotfiles', name: 'Dotfile Protector', category: 'safety', source: 'cc-safe-setup', trigger: 'PreToolUse', desc: 'Block modifications to ~/.bashrc, ~/.aws/, ~/.ssh/', tags: ['dotfiles', 'bashrc', 'aws', 'ssh', 'config'], install: 'npx cc-safe-setup --install-example protect-dotfiles', issue: '#37478' },
58
+ { id: 'scope-guard', name: 'Project Scope Guard', category: 'safety', source: 'cc-safe-setup', trigger: 'PreToolUse', desc: 'Block file operations outside project directory', tags: ['scope', 'path', 'directory', 'escape'], install: 'npx cc-safe-setup --install-example scope-guard', issue: '#36233' },
59
+ { id: 'notify-waiting', name: 'Desktop Notification', category: 'ux', source: 'cc-safe-setup', trigger: 'Notification', desc: 'Desktop notification when Claude waits for input', tags: ['notification', 'desktop', 'alert', 'waiting'], install: 'npx cc-safe-setup --install-example notify-waiting' },
60
+ { id: 'read-before-edit', name: 'Read Before Edit Warning', category: 'quality', source: 'cc-safe-setup', trigger: 'PreToolUse', desc: 'Warn when editing files not recently read', tags: ['read', 'edit', 'mismatch', 'old_string'], install: 'npx cc-safe-setup --install-example read-before-edit' },
61
+ { id: 'commit-quality-gate', name: 'Commit Message Quality', category: 'quality', source: 'cc-safe-setup', trigger: 'PreToolUse', desc: 'Warn on vague commit messages and long subjects', tags: ['commit', 'message', 'quality', 'conventional'], install: 'npx cc-safe-setup --install-example commit-quality-gate' },
62
+
63
+ // External projects
64
+ { id: 'safety-net', name: 'Safety Net (Full Suite)', category: 'safety', source: 'kenryu42/claude-code-safety-net', trigger: 'PreToolUse', desc: 'TypeScript safety hooks with configurable severity levels', tags: ['typescript', 'safety', 'configurable'], install: 'npx @anthropic-ai/claude-code-safety-net', stars: 1185 },
65
+ { id: 'hooks-mastery', name: 'Hooks Mastery (Python)', category: 'framework', source: 'disler/claude-code-hooks-mastery', trigger: 'All', desc: 'Python hooks covering all hook events + LLM integration', tags: ['python', 'mastery', 'all-events', 'llm'], install: 'git clone + copy', stars: 3386 },
66
+ { id: 'prompt-injection-defender', name: 'Prompt Injection Defender', category: 'security', source: 'lasso-security/claude-hooks', trigger: 'PreToolUse', desc: 'YAML-based prompt injection pattern matching', tags: ['prompt-injection', 'security', 'yaml'], install: 'git clone + install.sh', stars: 161 },
67
+ ];
68
+
69
+ const args = process.argv.slice(2);
70
+ const command = args[0];
71
+
72
+ if (!command || command === '--help' || command === '-h') {
73
+ console.log(`
74
+ cc-hook-registry — Find and install Claude Code hooks
75
+
76
+ Commands:
77
+ search <keyword> Find hooks (e.g. "database", "git", "deploy")
78
+ browse [category] Browse by category (safety, quality, approve, utility, monitoring, ux)
79
+ install <id> Install a hook
80
+ info <id> Show hook details
81
+ stats Registry statistics
82
+
83
+ Examples:
84
+ npx cc-hook-registry search database
85
+ npx cc-hook-registry browse safety
86
+ npx cc-hook-registry install block-database-wipe
87
+ npx cc-hook-registry info compound-command-approver
88
+ `);
89
+ process.exit(0);
90
+ }
91
+
92
+ if (command === 'search') {
93
+ const query = args.slice(1).join(' ').toLowerCase();
94
+ if (!query) { console.log(c.red + ' Usage: cc-hook-registry search <keyword>' + c.reset); process.exit(1); }
95
+
96
+ const results = REGISTRY.filter(h =>
97
+ h.name.toLowerCase().includes(query) ||
98
+ h.desc.toLowerCase().includes(query) ||
99
+ h.tags.some(t => t.includes(query)) ||
100
+ h.id.includes(query)
101
+ );
102
+
103
+ console.log();
104
+ console.log(c.bold + ' Search: "' + query + '"' + c.reset + ' — ' + results.length + ' result(s)');
105
+ console.log();
106
+
107
+ if (results.length === 0) {
108
+ console.log(c.dim + ' No hooks found. Try a different keyword.' + c.reset);
109
+ } else {
110
+ for (const h of results) {
111
+ console.log(' ' + c.green + h.id + c.reset + c.dim + ' [' + h.category + ']' + c.reset);
112
+ console.log(' ' + h.desc);
113
+ console.log(' ' + c.dim + 'Install: ' + h.install + c.reset);
114
+ console.log();
115
+ }
116
+ }
117
+ }
118
+
119
+ else if (command === 'browse') {
120
+ const cat = args[1]?.toLowerCase();
121
+ const categories = {};
122
+ for (const h of REGISTRY) {
123
+ if (cat && h.category !== cat) continue;
124
+ if (!categories[h.category]) categories[h.category] = [];
125
+ categories[h.category].push(h);
126
+ }
127
+
128
+ console.log();
129
+ console.log(c.bold + ' Claude Code Hooks Registry' + c.reset + ' — ' + REGISTRY.length + ' hooks');
130
+ console.log();
131
+
132
+ for (const [category, hooks] of Object.entries(categories)) {
133
+ console.log(' ' + c.bold + c.blue + category.charAt(0).toUpperCase() + category.slice(1) + c.reset + ' (' + hooks.length + ')');
134
+ for (const h of hooks) {
135
+ const stars = h.stars ? ' ' + h.stars + '★' : '';
136
+ console.log(' ' + c.green + h.id.padEnd(28) + c.reset + h.desc.slice(0, 50) + stars);
137
+ }
138
+ console.log();
139
+ }
140
+ }
141
+
142
+ else if (command === 'install') {
143
+ const id = args[1];
144
+ if (!id) { console.log(c.red + ' Usage: cc-hook-registry install <id>' + c.reset); process.exit(1); }
145
+
146
+ const hook = REGISTRY.find(h => h.id === id);
147
+ if (!hook) {
148
+ console.log(c.red + ' Hook not found: ' + id + c.reset);
149
+ console.log(c.dim + ' Use "cc-hook-registry search" to find hooks.' + c.reset);
150
+ process.exit(1);
151
+ }
152
+
153
+ console.log();
154
+ console.log(c.bold + ' Installing: ' + hook.name + c.reset);
155
+ console.log(c.dim + ' ' + hook.desc + c.reset);
156
+ console.log();
157
+ console.log(' Run: ' + c.bold + hook.install + c.reset);
158
+ console.log();
159
+
160
+ if (hook.install.startsWith('npx cc-safe-setup')) {
161
+ try {
162
+ execSync(hook.install, { stdio: 'inherit' });
163
+ } catch (e) {
164
+ console.log(c.yellow + ' Run the command manually: ' + hook.install + c.reset);
165
+ }
166
+ } else {
167
+ console.log(c.dim + ' This hook requires manual installation. Follow the instructions above.' + c.reset);
168
+ }
169
+ }
170
+
171
+ else if (command === 'info') {
172
+ const id = args[1];
173
+ if (!id) { console.log(c.red + ' Usage: cc-hook-registry info <id>' + c.reset); process.exit(1); }
174
+
175
+ const hook = REGISTRY.find(h => h.id === id);
176
+ if (!hook) {
177
+ console.log(c.red + ' Hook not found: ' + id + c.reset);
178
+ process.exit(1);
179
+ }
180
+
181
+ console.log();
182
+ console.log(c.bold + ' ' + hook.name + c.reset);
183
+ console.log(' ' + hook.desc);
184
+ console.log();
185
+ console.log(' ID: ' + hook.id);
186
+ console.log(' Category: ' + hook.category);
187
+ console.log(' Trigger: ' + hook.trigger);
188
+ console.log(' Source: ' + hook.source);
189
+ console.log(' Install: ' + c.bold + hook.install + c.reset);
190
+ if (hook.issue) console.log(' Issue: https://github.com/anthropics/claude-code/issues/' + hook.issue.replace('#', ''));
191
+ if (hook.stars) console.log(' Stars: ' + hook.stars);
192
+ console.log(' Tags: ' + hook.tags.join(', '));
193
+ console.log();
194
+ }
195
+
196
+ else if (command === 'stats') {
197
+ const categories = {};
198
+ const sources = {};
199
+ for (const h of REGISTRY) {
200
+ categories[h.category] = (categories[h.category] || 0) + 1;
201
+ sources[h.source] = (sources[h.source] || 0) + 1;
202
+ }
203
+
204
+ console.log();
205
+ console.log(c.bold + ' Registry Statistics' + c.reset);
206
+ console.log();
207
+ console.log(' Total hooks: ' + c.bold + REGISTRY.length + c.reset);
208
+ console.log();
209
+ console.log(' By category:');
210
+ for (const [cat, count] of Object.entries(categories).sort((a, b) => b[1] - a[1])) {
211
+ console.log(' ' + cat.padEnd(15) + count);
212
+ }
213
+ console.log();
214
+ console.log(' By source:');
215
+ for (const [src, count] of Object.entries(sources).sort((a, b) => b[1] - a[1])) {
216
+ console.log(' ' + src.padEnd(40) + count);
217
+ }
218
+ console.log();
219
+ }
220
+
221
+ else {
222
+ console.log(c.red + ' Unknown command: ' + command + c.reset);
223
+ console.log(c.dim + ' Run cc-hook-registry --help for usage.' + c.reset);
224
+ process.exit(1);
225
+ }
package/package.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "cc-hook-registry",
3
+ "version": "1.0.0",
4
+ "description": "Search, browse, and install Claude Code hooks from the community. GitHub-based registry, no server needed.",
5
+ "main": "index.mjs",
6
+ "bin": {
7
+ "cc-hook-registry": "index.mjs"
8
+ },
9
+ "keywords": [
10
+ "claude-code",
11
+ "hooks",
12
+ "registry",
13
+ "marketplace",
14
+ "safety",
15
+ "cli"
16
+ ],
17
+ "scripts": {
18
+ "test": "node index.mjs --help"
19
+ },
20
+ "author": "yurukusa",
21
+ "license": "MIT",
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "https://github.com/yurukusa/cc-hook-registry"
25
+ }
26
+ }