cc-safe-setup 1.2.1 → 1.3.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 (2) hide show
  1. package/index.mjs +59 -0
  2. package/package.json +2 -2
package/index.mjs CHANGED
@@ -59,6 +59,7 @@ const HOOKS = {
59
59
 
60
60
  const HELP = process.argv.includes('--help') || process.argv.includes('-h');
61
61
  const STATUS = process.argv.includes('--status') || process.argv.includes('-s');
62
+ const VERIFY = process.argv.includes('--verify') || process.argv.includes('-v');
62
63
 
63
64
  if (HELP) {
64
65
  console.log(`
@@ -67,6 +68,7 @@ if (HELP) {
67
68
  Usage:
68
69
  npx cc-safe-setup Install 7 safety hooks
69
70
  npx cc-safe-setup --status Check installed hooks
71
+ npx cc-safe-setup --verify Test each hook with sample inputs
70
72
  npx cc-safe-setup --dry-run Preview without installing
71
73
  npx cc-safe-setup --uninstall Remove all installed hooks
72
74
  npx cc-safe-setup --help Show this help
@@ -174,10 +176,67 @@ function status() {
174
176
  console.log(' ' + c.dim + 'Run: npx cc-safe-setup' + c.reset);
175
177
  }
176
178
  console.log();
179
+
180
+ // Exit code for CI: 0 = all installed, 1 = missing hooks
181
+ if (missing > 0) process.exit(1);
182
+ }
183
+
184
+ async function verify() {
185
+ const { execSync } = await import('child_process');
186
+ console.log();
187
+ console.log(c.bold + ' cc-safe-setup --verify' + c.reset);
188
+ console.log(c.dim + ' Testing each hook with sample inputs...' + c.reset);
189
+ console.log();
190
+
191
+ const tests = [
192
+ { hook: 'destructive-guard', input: '{"tool_input":{"command":"rm -rf /"}}', expect: 2, desc: 'blocks rm -rf /' },
193
+ { hook: 'destructive-guard', input: '{"tool_input":{"command":"ls -la"}}', expect: 0, desc: 'allows safe commands' },
194
+ { hook: 'branch-guard', input: '{"tool_input":{"command":"git push origin main"}}', expect: 2, desc: 'blocks push to main' },
195
+ { hook: 'branch-guard', input: '{"tool_input":{"command":"git push origin feature"}}', expect: 0, desc: 'allows push to feature' },
196
+ { hook: 'secret-guard', input: '{"tool_input":{"command":"git add .env"}}', expect: 2, desc: 'blocks git add .env' },
197
+ { hook: 'secret-guard', input: '{"tool_input":{"command":"git add src/app.js"}}', expect: 0, desc: 'allows git add safe files' },
198
+ ];
199
+
200
+ let pass = 0, fail = 0;
201
+ for (const t of tests) {
202
+ const hookPath = join(HOOKS_DIR, t.hook + '.sh');
203
+ if (!existsSync(hookPath)) {
204
+ console.log(' ' + c.red + '✗' + c.reset + ' ' + t.hook + ': ' + t.desc + c.dim + ' (not installed)' + c.reset);
205
+ fail++;
206
+ continue;
207
+ }
208
+ try {
209
+ execSync(`echo '${t.input}' | bash "${hookPath}"`, { stdio: 'pipe' });
210
+ if (t.expect === 0) {
211
+ console.log(' ' + c.green + '✓' + c.reset + ' ' + t.hook + ': ' + t.desc);
212
+ pass++;
213
+ } else {
214
+ console.log(' ' + c.red + '✗' + c.reset + ' ' + t.hook + ': ' + t.desc + ' (should have blocked)');
215
+ fail++;
216
+ }
217
+ } catch(e) {
218
+ if (e.status === t.expect) {
219
+ console.log(' ' + c.green + '✓' + c.reset + ' ' + t.hook + ': ' + t.desc);
220
+ pass++;
221
+ } else {
222
+ console.log(' ' + c.red + '✗' + c.reset + ' ' + t.hook + ': ' + t.desc + ' (exit ' + e.status + ', expected ' + t.expect + ')');
223
+ fail++;
224
+ }
225
+ }
226
+ }
227
+
228
+ console.log();
229
+ console.log(c.bold + ' ' + pass + '/' + (pass + fail) + ' tests passed.' + c.reset);
230
+ if (fail > 0) {
231
+ console.log(' ' + c.red + fail + ' failures.' + c.reset + ' Run ' + c.blue + 'npx cc-safe-setup' + c.reset + ' to reinstall.');
232
+ process.exit(1);
233
+ }
234
+ console.log();
177
235
  }
178
236
 
179
237
  async function main() {
180
238
  if (UNINSTALL) return uninstall();
239
+ if (VERIFY) return verify();
181
240
  if (STATUS) return status();
182
241
 
183
242
  console.log();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cc-safe-setup",
3
- "version": "1.2.1",
3
+ "version": "1.3.0",
4
4
  "description": "One command to make Claude Code safe for autonomous operation. 7 hooks: destructive blocker, branch guard, force-push protection, secret leak prevention, syntax checks, and more.",
5
5
  "main": "index.mjs",
6
6
  "bin": {
@@ -34,4 +34,4 @@
34
34
  "url": "https://github.com/yurukusa/cc-safe-setup"
35
35
  },
36
36
  "homepage": "https://github.com/yurukusa/cc-safe-setup"
37
- }
37
+ }