cc-safe-setup 10.8.0 → 10.9.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 +68 -0
  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 + 104 examples = **118 hooks**. 38 CLI commands. 531 tests. 5 languages. [**Hub**](https://yurukusa.github.io/cc-safe-setup/hub.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 + 104 examples = **118 hooks**. 39 CLI commands. 531 tests. 5 languages. [**Hub**](https://yurukusa.github.io/cc-safe-setup/hub.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
@@ -108,6 +108,8 @@ const COMPARE = COMPARE_IDX !== -1 ? { a: process.argv[COMPARE_IDX + 1], b: proc
108
108
  const REPLAY = process.argv.includes('--replay');
109
109
  const CREATE_IDX = process.argv.findIndex(a => a === '--create');
110
110
  const CREATE_DESC = CREATE_IDX !== -1 ? process.argv.slice(CREATE_IDX + 1).join(' ') : null;
111
+ const WHY_IDX = process.argv.findIndex(a => a === '--why');
112
+ const WHY_HOOK = WHY_IDX !== -1 ? process.argv[WHY_IDX + 1] : null;
111
113
 
112
114
  if (HELP) {
113
115
  console.log(`
@@ -139,6 +141,7 @@ if (HELP) {
139
141
  npx cc-safe-setup --doctor Diagnose why hooks aren't working
140
142
  npx cc-safe-setup --watch Live dashboard of blocked commands
141
143
  npx cc-safe-setup --create "<desc>" Generate a custom hook from description
144
+ npx cc-safe-setup --why <hook> Why this hook exists (real incident + issue link)
142
145
  npx cc-safe-setup --replay Replay blocked commands timeline (demo/review)
143
146
  npx cc-safe-setup --guard "<rule>" Instantly enforce a rule (generate + install + activate)
144
147
  npx cc-safe-setup --diff-hooks <path> Compare hooks between two settings files
@@ -922,6 +925,70 @@ async function fullSetup() {
922
925
  console.log();
923
926
  }
924
927
 
928
+ async function why(hookName) {
929
+ const WHY_DATA = {
930
+ 'destructive-guard': { issue: '#36339', incident: 'User lost entire C:\\Users directory — rm -rf followed NTFS junctions', url: 'https://github.com/anthropics/claude-code/issues/36339' },
931
+ 'branch-guard': { issue: '#36640', incident: 'Autonomous Claude pushed untested code to main at 3am', url: 'https://github.com/anthropics/claude-code/issues/36640' },
932
+ 'secret-guard': { issue: '#16561', incident: 'API keys committed to public repo via git add .', url: 'https://github.com/anthropics/claude-code/issues/16561' },
933
+ 'block-database-wipe': { issue: '#37405', incident: 'Production database wiped by migrate:fresh', url: 'https://github.com/anthropics/claude-code/issues/37405' },
934
+ 'uncommitted-work-guard': { issue: '#37888', incident: 'Claude destroyed uncommitted work twice in same session', url: 'https://github.com/anthropics/claude-code/issues/37888' },
935
+ 'test-deletion-guard': { issue: '#38050', incident: 'Claude deleted failing tests instead of fixing code', url: 'https://github.com/anthropics/claude-code/issues/38050' },
936
+ 'fact-check-gate': { issue: '#38057', incident: 'Claude wrote false claims in technical docs without reading source', url: 'https://github.com/anthropics/claude-code/issues/38057' },
937
+ 'token-budget-guard': { issue: '#38029', incident: 'Session consumed $342 in tokens without user knowing', url: 'https://github.com/anthropics/claude-code/issues/38029' },
938
+ 'protect-dotfiles': { issue: '#37478', incident: '.bashrc and environment files overwritten', url: 'https://github.com/anthropics/claude-code/issues/37478' },
939
+ 'scope-guard': { issue: '#36233', incident: 'Entire Mac filesystem deleted by out-of-scope operation', url: 'https://github.com/anthropics/claude-code/issues/36233' },
940
+ 'case-sensitive-guard': { issue: '#37875', incident: 'exFAT case collision caused data loss via rm -rf', url: 'https://github.com/anthropics/claude-code/issues/37875' },
941
+ 'prompt-injection-guard': { issue: '#38046', incident: 'Prompt injection found in /insights output', url: 'https://github.com/anthropics/claude-code/issues/38046' },
942
+ 'overwrite-guard': { issue: '#37595', incident: '/export overwrites existing files without warning', url: 'https://github.com/anthropics/claude-code/issues/37595' },
943
+ 'memory-write-guard': { issue: '#38040', incident: 'No way to see what Claude writes to ~/.claude/', url: 'https://github.com/anthropics/claude-code/issues/38040' },
944
+ 'context-monitor': { issue: '#6527', incident: 'Sessions silently lost all state after 150+ tool calls', url: 'https://github.com/anthropics/claude-code/issues/6527' },
945
+ 'comment-strip': { issue: '#29582', incident: 'Bash comments in hook commands broke permission matching', url: 'https://github.com/anthropics/claude-code/issues/29582' },
946
+ 'cd-git-allow': { issue: '#32985', incident: 'cd+git compounds spammed permission prompts endlessly', url: 'https://github.com/anthropics/claude-code/issues/32985' },
947
+ 'strict-allowlist': { issue: '#37471', incident: 'Denylist model creates arms race — Claude finds bypasses', url: 'https://github.com/anthropics/claude-code/issues/37471' },
948
+ 'error-memory-guard': { issue: 'common', incident: 'Claude retries the same failing command 10+ times' },
949
+ 'typosquat-guard': { issue: 'supply-chain', incident: 'Misspelled package names can install malware' },
950
+ };
951
+
952
+ console.log();
953
+ if (!hookName) {
954
+ console.log(c.bold + ' cc-safe-setup --why <hook-name>' + c.reset);
955
+ console.log(c.dim + ' Show why a hook exists — the real incident that inspired it.' + c.reset);
956
+ console.log();
957
+ console.log(' Examples:');
958
+ console.log(c.dim + ' npx cc-safe-setup --why destructive-guard' + c.reset);
959
+ console.log(c.dim + ' npx cc-safe-setup --why token-budget-guard' + c.reset);
960
+ console.log();
961
+ console.log(` ${Object.keys(WHY_DATA).length} hooks have documented incidents.`);
962
+ return;
963
+ }
964
+
965
+ const name = hookName.replace('.sh', '');
966
+ const data = WHY_DATA[name];
967
+ if (!data) {
968
+ console.log(c.yellow + ` No incident documented for "${name}".` + c.reset);
969
+ console.log(c.dim + ' This hook may have been created proactively.' + c.reset);
970
+ console.log();
971
+ console.log(c.dim + ` Hooks with documented incidents: ${Object.keys(WHY_DATA).join(', ')}` + c.reset);
972
+ return;
973
+ }
974
+
975
+ console.log(c.bold + ` Why "${name}" exists` + c.reset);
976
+ console.log();
977
+ console.log(c.red + ' Incident:' + c.reset);
978
+ console.log(' ' + data.incident);
979
+ console.log();
980
+ if (data.url) {
981
+ console.log(c.blue + ' Source:' + c.reset);
982
+ console.log(' ' + data.url);
983
+ }
984
+ if (data.issue && data.issue !== 'common' && data.issue !== 'supply-chain') {
985
+ console.log(c.dim + ` GitHub Issue: ${data.issue}` + c.reset);
986
+ }
987
+ console.log();
988
+ console.log(c.dim + ' Install: npx cc-safe-setup --install-example ' + name + c.reset);
989
+ console.log();
990
+ }
991
+
925
992
  async function replay() {
926
993
  console.log();
927
994
  console.log(c.bold + ' cc-safe-setup --replay' + c.reset);
@@ -4051,6 +4118,7 @@ async function main() {
4051
4118
  if (FULL) return fullSetup();
4052
4119
  if (DOCTOR) return doctor();
4053
4120
  if (WATCH) return watch();
4121
+ if (WHY_IDX !== -1) return why(WHY_HOOK);
4054
4122
  if (REPLAY) return replay();
4055
4123
  if (GUARD_IDX !== -1) return guard(GUARD_DESC);
4056
4124
  if (DIFF_HOOKS_IDX !== -1) return diffHooks(DIFF_HOOKS);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cc-safe-setup",
3
- "version": "10.8.0",
3
+ "version": "10.9.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": {