cc-safe-setup 13.2.0 → 13.4.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 +1 -1
  2. package/index.mjs +63 -2
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  **One command to make Claude Code safe for autonomous operation.** [日本語](docs/README.ja.md)
8
8
 
9
- 8 built-in + 124 examples = **138 hooks**. 43 CLI commands. 561 tests. 5 languages. [**Hub**](https://yurukusa.github.io/cc-safe-setup/hub.html) · [Wizard](https://yurukusa.github.io/cc-safe-setup/wizard.html) · [Cheat Sheet](https://yurukusa.github.io/cc-safe-setup/hooks-cheatsheet.html) · [Builder](https://yurukusa.github.io/cc-safe-setup/builder.html) · [FAQ](https://yurukusa.github.io/cc-safe-setup/faq.html) · [Examples](https://yurukusa.github.io/cc-safe-setup/by-example.html) · [Matrix](https://yurukusa.github.io/cc-safe-setup/matrix.html) · [Playground](https://yurukusa.github.io/cc-hook-registry/playground.html)
9
+ 8 built-in + 124 examples = **138 hooks**. 44 CLI commands. 561 tests. 5 languages. [**Hub**](https://yurukusa.github.io/cc-safe-setup/hub.html) · [Wizard](https://yurukusa.github.io/cc-safe-setup/wizard.html) · [Cheat Sheet](https://yurukusa.github.io/cc-safe-setup/hooks-cheatsheet.html) · [Builder](https://yurukusa.github.io/cc-safe-setup/builder.html) · [FAQ](https://yurukusa.github.io/cc-safe-setup/faq.html) · [Examples](https://yurukusa.github.io/cc-safe-setup/by-example.html) · [Matrix](https://yurukusa.github.io/cc-safe-setup/matrix.html) · [Playground](https://yurukusa.github.io/cc-hook-registry/playground.html)
10
10
 
11
11
  ```bash
12
12
  npx cc-safe-setup
package/index.mjs CHANGED
@@ -112,6 +112,7 @@ const CREATE_IDX = process.argv.findIndex(a => a === '--create');
112
112
  const CREATE_DESC = CREATE_IDX !== -1 ? process.argv.slice(CREATE_IDX + 1).join(' ') : null;
113
113
  const SUGGEST = process.argv.includes('--suggest');
114
114
  const INIT_PROJECT = process.argv.includes('--init-project');
115
+ const SCORE_ONLY = process.argv.includes('--score');
115
116
  const TEST_HOOK_IDX = process.argv.findIndex(a => a === '--test-hook');
116
117
  const TEST_HOOK = TEST_HOOK_IDX !== -1 ? process.argv[TEST_HOOK_IDX + 1] : null;
117
118
  const WHY_IDX = process.argv.findIndex(a => a === '--why');
@@ -149,6 +150,7 @@ if (HELP) {
149
150
  npx cc-safe-setup --create "<desc>" Generate a custom hook from description
150
151
  npx cc-safe-setup --test-hook <name> Test a specific hook with sample inputs
151
152
  npx cc-safe-setup --save-profile <name> Save current hooks as a named profile
153
+ npx cc-safe-setup --score Print safety score (0-100) and exit
152
154
  npx cc-safe-setup --init-project Complete project setup (CLAUDE.md + hooks + CI + .gitignore)
153
155
  npx cc-safe-setup --suggest Analyze project and predict risks → suggest hooks
154
156
  npx cc-safe-setup --why <hook> Why this hook exists (real incident + issue link)
@@ -537,8 +539,28 @@ function examples() {
537
539
  console.log();
538
540
  }
539
541
 
540
- console.log();
541
- console.log(c.dim + ' Copy any example to ~/.claude/hooks/ and add to settings.json.' + c.reset);
542
+ // Show batch install command if filtered
543
+ const allFiltered = [];
544
+ for (const [cat, hooks] of Object.entries(CATEGORIES)) {
545
+ const fh = filter
546
+ ? Object.entries(hooks).filter(([file, desc]) =>
547
+ cat.toLowerCase().includes(filter) ||
548
+ file.toLowerCase().includes(filter) ||
549
+ desc.toLowerCase().includes(filter))
550
+ : Object.entries(hooks);
551
+ for (const [file] of fh) allFiltered.push(file.replace('.sh', ''));
552
+ }
553
+
554
+ if (filter && allFiltered.length > 0 && allFiltered.length <= 20) {
555
+ console.log(c.dim + ' Install all filtered hooks:' + c.reset);
556
+ for (const h of allFiltered) {
557
+ console.log(c.dim + ` npx cc-safe-setup --install-example ${h}` + c.reset);
558
+ }
559
+ console.log();
560
+ }
561
+
562
+ console.log(c.dim + ' Or install any single hook:' + c.reset);
563
+ console.log(c.dim + ' npx cc-safe-setup --install-example <name>' + c.reset);
542
564
  console.log(c.dim + ' Source: ' + c.blue + 'https://github.com/yurukusa/cc-safe-setup/tree/main/examples' + c.reset);
543
565
  console.log();
544
566
  }
@@ -1072,6 +1094,44 @@ async function saveProfile(name) {
1072
1094
  console.log();
1073
1095
  }
1074
1096
 
1097
+ async function scoreOnly() {
1098
+ const { readdirSync } = await import('fs');
1099
+ let score = 0;
1100
+
1101
+ // Hooks installed (max 50 points)
1102
+ const hookDir = join(HOME, '.claude', 'hooks');
1103
+ const hookCount = existsSync(hookDir) ? readdirSync(hookDir).filter(f => f.endsWith('.sh') || f.endsWith('.py')).length : 0;
1104
+ score += Math.min(hookCount * 3, 50);
1105
+
1106
+ // Critical hooks (max 20 points)
1107
+ const critical = ['destructive-guard', 'branch-guard', 'secret-guard'];
1108
+ if (existsSync(SETTINGS_PATH)) {
1109
+ try {
1110
+ const s = JSON.parse(readFileSync(SETTINGS_PATH, 'utf-8'));
1111
+ const cmds = JSON.stringify(s.hooks || {});
1112
+ for (const h of critical) {
1113
+ if (cmds.includes(h)) score += 7;
1114
+ }
1115
+ } catch {}
1116
+ }
1117
+
1118
+ // CLAUDE.md exists (10 points)
1119
+ if (existsSync(join(process.cwd(), 'CLAUDE.md'))) score += 10;
1120
+
1121
+ // .gitignore has .env (10 points)
1122
+ const gi = existsSync(join(process.cwd(), '.gitignore')) ? readFileSync(join(process.cwd(), '.gitignore'), 'utf-8') : '';
1123
+ if (gi.includes('.env')) score += 10;
1124
+
1125
+ // CI workflow (10 points)
1126
+ if (existsSync(join(process.cwd(), '.github', 'workflows', 'claude-code-safety.yml'))) score += 10;
1127
+
1128
+ score = Math.min(score, 100);
1129
+
1130
+ // Output just the score for piping
1131
+ console.log(score);
1132
+ process.exit(score >= 70 ? 0 : 1);
1133
+ }
1134
+
1075
1135
  async function initProject() {
1076
1136
  console.log();
1077
1137
  console.log(c.bold + ' cc-safe-setup --init-project' + c.reset);
@@ -4498,6 +4558,7 @@ async function main() {
4498
4558
  if (WATCH) return watch();
4499
4559
  if (TEST_HOOK_IDX !== -1) return testHook(TEST_HOOK);
4500
4560
  if (SAVE_PROFILE_IDX !== -1) return saveProfile(SAVE_PROFILE);
4561
+ if (SCORE_ONLY) return scoreOnly();
4501
4562
  if (INIT_PROJECT) return initProject();
4502
4563
  if (SUGGEST) return suggest();
4503
4564
  if (WHY_IDX !== -1) return why(WHY_HOOK);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cc-safe-setup",
3
- "version": "13.2.0",
3
+ "version": "13.4.0",
4
4
  "description": "One command to make Claude Code safe. 59 hooks (8 built-in + 51 examples). 26 CLI commands: dashboard, create, audit, lint, diff, migrate, compare, generate-ci. 284 tests.",
5
5
  "main": "index.mjs",
6
6
  "bin": {