cc-safe-setup 6.1.0 → 6.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.
Files changed (2) hide show
  1. package/index.mjs +77 -0
  2. package/package.json +1 -1
package/index.mjs CHANGED
@@ -86,6 +86,7 @@ const SHARE = process.argv.includes('--share');
86
86
  const BENCHMARK = process.argv.includes('--benchmark');
87
87
  const DASHBOARD = process.argv.includes('--dashboard');
88
88
  const ISSUES = process.argv.includes('--issues');
89
+ const MIGRATE = process.argv.includes('--migrate');
89
90
  const COMPARE_IDX = process.argv.findIndex(a => a === '--compare');
90
91
  const COMPARE = COMPARE_IDX !== -1 ? { a: process.argv[COMPARE_IDX + 1], b: process.argv[COMPARE_IDX + 2] } : null;
91
92
  const CREATE_IDX = process.argv.findIndex(a => a === '--create');
@@ -109,6 +110,7 @@ if (HELP) {
109
110
  npx cc-safe-setup --audit --json Machine-readable output for CI/CD
110
111
  npx cc-safe-setup --scan Detect tech stack, recommend hooks
111
112
  npx cc-safe-setup --learn Learn from your block history
113
+ npx cc-safe-setup --migrate Detect hooks from other projects, suggest replacements
112
114
  npx cc-safe-setup --compare <a> <b> Compare two hooks side-by-side
113
115
  npx cc-safe-setup --issues Show GitHub Issues each hook addresses
114
116
  npx cc-safe-setup --dashboard Real-time status dashboard
@@ -824,6 +826,75 @@ async function fullSetup() {
824
826
  console.log();
825
827
  }
826
828
 
829
+ async function migrate() {
830
+ const { readdirSync } = await import('fs');
831
+
832
+ console.log();
833
+ console.log(c.bold + ' cc-safe-setup --migrate' + c.reset);
834
+ console.log(c.dim + ' Detecting hooks from other projects...' + c.reset);
835
+ console.log();
836
+
837
+ if (!existsSync(HOOKS_DIR)) {
838
+ console.log(c.dim + ' No hooks installed.' + c.reset);
839
+ process.exit(0);
840
+ }
841
+
842
+ const files = readdirSync(HOOKS_DIR).filter(f => f.endsWith('.sh') || f.endsWith('.js') || f.endsWith('.py'));
843
+
844
+ // Detection patterns for other projects
845
+ const detections = [
846
+ { pattern: /safety-net|cc-safety-net|SAFETY_LEVEL/i, project: 'claude-code-safety-net', replacement: 'npx cc-safe-setup (destructive-guard, branch-guard)' },
847
+ { pattern: /karanb192|block-dangerous-commands\.js/i, project: 'karanb192/claude-code-hooks', replacement: 'npx cc-safe-setup (destructive-guard)' },
848
+ { pattern: /hooks-mastery|disler|pre_tool_use\.py/i, project: 'disler/claude-code-hooks-mastery', replacement: 'npx cc-safe-setup (multiple hooks)' },
849
+ { pattern: /cchooks|from cchooks/i, project: 'GowayLee/cchooks', replacement: 'npx cc-safe-setup (bash equivalents)' },
850
+ { pattern: /lasso.*security|prompt.*injection.*pattern/i, project: 'lasso-security/claude-hooks', replacement: 'No direct equivalent (unique functionality)' },
851
+ ];
852
+
853
+ let found = 0;
854
+ const suggestions = [];
855
+
856
+ for (const file of files) {
857
+ const content = readFileSync(join(HOOKS_DIR, file), 'utf-8');
858
+
859
+ for (const det of detections) {
860
+ if (det.pattern.test(content) || det.pattern.test(file)) {
861
+ console.log(' ' + c.yellow + '!' + c.reset + ' ' + file + c.dim + ' ← from ' + det.project + c.reset);
862
+ console.log(' ' + c.dim + 'Replacement: ' + det.replacement + c.reset);
863
+ found++;
864
+ break;
865
+ }
866
+ }
867
+
868
+ // Detect hand-written hooks that duplicate built-in functionality
869
+ if (content.includes('rm -rf') && !file.includes('destructive-guard')) {
870
+ suggestions.push({ file, suggest: 'destructive-guard', reason: 'rm -rf detection already built-in' });
871
+ }
872
+ if (content.includes('git push') && content.includes('main') && !file.includes('branch-guard')) {
873
+ suggestions.push({ file, suggest: 'branch-guard', reason: 'branch protection already built-in' });
874
+ }
875
+ if (content.includes('.env') && content.includes('git add') && !file.includes('secret-guard')) {
876
+ suggestions.push({ file, suggest: 'secret-guard', reason: 'secret leak prevention already built-in' });
877
+ }
878
+ }
879
+
880
+ if (suggestions.length > 0) {
881
+ console.log();
882
+ console.log(c.bold + ' Duplicate functionality detected:' + c.reset);
883
+ for (const s of suggestions) {
884
+ console.log(' ' + c.dim + s.file + c.reset + ' → ' + c.green + s.suggest + c.reset);
885
+ console.log(' ' + c.dim + s.reason + c.reset);
886
+ }
887
+ }
888
+
889
+ console.log();
890
+ if (found === 0 && suggestions.length === 0) {
891
+ console.log(c.green + ' No migration needed. All hooks are cc-safe-setup native.' + c.reset);
892
+ } else {
893
+ console.log(c.dim + ' Run npx cc-safe-setup to install built-in replacements.' + c.reset);
894
+ }
895
+ console.log();
896
+ }
897
+
827
898
  async function compare(hookA, hookB) {
828
899
  const { spawnSync } = await import('child_process');
829
900
  const { statSync } = await import('fs');
@@ -937,6 +1008,11 @@ function issues() {
937
1008
  { hook: 'binary-file-guard', issues: ['Binary file corruption from Write tool'] },
938
1009
  { hook: 'stale-branch-guard', issues: ['Merge conflicts from stale branches'] },
939
1010
  { hook: 'reinject-claudemd', issues: ['#6354 CLAUDE.md lost after compaction (27r)'] },
1011
+ { hook: 'no-sudo-guard', issues: ['Privilege escalation prevention'] },
1012
+ { hook: 'no-install-global', issues: ['System package pollution'] },
1013
+ { hook: 'protect-claudemd', issues: ['AI modifying its own config files'] },
1014
+ { hook: 'git-tag-guard', issues: ['Accidental tag push'] },
1015
+ { hook: 'npm-publish-guard', issues: ['Accidental publish without version check'] },
940
1016
  ];
941
1017
 
942
1018
  console.log();
@@ -2432,6 +2508,7 @@ async function main() {
2432
2508
  if (FULL) return fullSetup();
2433
2509
  if (DOCTOR) return doctor();
2434
2510
  if (WATCH) return watch();
2511
+ if (MIGRATE) return migrate();
2435
2512
  if (COMPARE) return compare(COMPARE.a, COMPARE.b);
2436
2513
  if (ISSUES) return issues();
2437
2514
  if (DASHBOARD) return dashboard();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cc-safe-setup",
3
- "version": "6.1.0",
3
+ "version": "6.2.0",
4
4
  "description": "One command to make Claude Code safe for autonomous operation. 8 built-in + 39 examples. 23 commands including dashboard, issues, create, audit, lint, diff. 260 tests. 2,500+ daily npm downloads.",
5
5
  "main": "index.mjs",
6
6
  "bin": {