cc-safe-setup 1.1.1 → 1.1.3

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.
package/README.md CHANGED
@@ -6,6 +6,8 @@
6
6
 
7
7
  **One command to make Claude Code safe for autonomous operation.**
8
8
 
9
+ Not just a destructive command blocker — 7 hooks covering safety, quality, monitoring, and developer experience.
10
+
9
11
  ```bash
10
12
  npx cc-safe-setup
11
13
  ```
@@ -73,6 +75,19 @@ Safe to run multiple times. Existing settings are preserved. A backup is created
73
75
 
74
76
  **Requires:** [jq](https://jqlang.github.io/jq/) for JSON parsing (`brew install jq` / `apt install jq`).
75
77
 
78
+ ## Before / After
79
+
80
+ Run `npx cc-health-check` to see the difference:
81
+
82
+ | | Before | After |
83
+ |---|--------|-------|
84
+ | Safety Guards | 25% | **75%** |
85
+ | Overall Score | 50/100 | **95/100** |
86
+ | Destructive commands | Unprotected | Blocked |
87
+ | Force push | Allowed | Blocked |
88
+ | `.env` in git | Possible | Blocked |
89
+ | Context warnings | None | 4-stage alerts |
90
+
76
91
  ## Configuration
77
92
 
78
93
  | Variable | Hook | Default |
@@ -96,7 +111,7 @@ npx cc-health-check
96
111
 
97
112
  cc-safe-setup gives you 7 essential hooks. For the complete autonomous operation toolkit:
98
113
 
99
- **[Claude Code Ops Kit](https://yurukusa.github.io/cc-ops-kit-landing/?utm_source=github&utm_medium=readme&utm_campaign=safe-setup)** — 15 hooks + 6 templates + 3 exclusive tools + install.sh. Production-ready in 15 minutes.
114
+ **[Claude Code Ops Kit](https://yurukusa.github.io/cc-ops-kit-landing/?utm_source=github&utm_medium=readme&utm_campaign=safe-setup)** — 16 hooks + 6 templates + 3 exclusive tools + install.sh. Production-ready in 15 minutes.
100
115
 
101
116
  Or start with the free hooks: [claude-code-hooks](https://github.com/yurukusa/claude-code-hooks)
102
117
 
@@ -105,6 +120,12 @@ Or start with the free hooks: [claude-code-hooks](https://github.com/yurukusa/cl
105
120
  - [Japanese guide (Qiita)](https://qiita.com/yurukusa/items/a9714b33f5d974e8f1e8) — この記事の日本語解説
106
121
  - [The incident that inspired this tool](https://github.com/anthropics/claude-code/issues/36339) — NTFS junction rm -rf
107
122
 
123
+ ## Contributing
124
+
125
+ Found a false positive? Open an [issue](https://github.com/yurukusa/cc-safe-setup/issues/new?template=false_positive.md). Want a new hook? Open a [feature request](https://github.com/yurukusa/cc-safe-setup/issues/new?template=bug_report.md).
126
+
127
+ If cc-safe-setup saved your project from a destructive command, consider giving it a star — it helps others find this tool.
128
+
108
129
  ## License
109
130
 
110
131
  MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cc-safe-setup",
3
- "version": "1.1.1",
3
+ "version": "1.1.3",
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": {
@@ -8,12 +8,25 @@
8
8
  },
9
9
  "keywords": [
10
10
  "claude-code",
11
+ "claude",
12
+ "anthropic",
11
13
  "ai",
12
14
  "safety",
13
15
  "hooks",
14
16
  "autonomous",
15
- "cli"
17
+ "cli",
18
+ "pretooluse",
19
+ "guard",
20
+ "rm-rf",
21
+ "git-push",
22
+ "env",
23
+ "secrets",
24
+ "syntax-check",
25
+ "context-window"
16
26
  ],
27
+ "scripts": {
28
+ "test": "bash test.sh"
29
+ },
17
30
  "author": "yurukusa",
18
31
  "license": "MIT",
19
32
  "repository": {
@@ -1,3 +0,0 @@
1
- github: yurukusa
2
- ko_fi: yurukusa
3
- custom: ["https://yurukusa.github.io/cc-ops-kit-landing/?ref=safe-setup"]
@@ -1,20 +0,0 @@
1
- ---
2
- name: Bug Report
3
- about: Something isn't working as expected
4
- title: "[BUG] "
5
- labels: bug
6
- ---
7
-
8
- **What happened?**
9
-
10
- **What did you expect?**
11
-
12
- **Environment:**
13
- - OS:
14
- - Node version:
15
- - Claude Code version:
16
- - jq installed: yes/no
17
-
18
- **Steps to reproduce:**
19
- 1. `npx cc-safe-setup`
20
- 2. ...
@@ -1,12 +0,0 @@
1
- ---
2
- name: False Positive
3
- about: A safe command was blocked
4
- title: "[FALSE POSITIVE] "
5
- labels: false-positive
6
- ---
7
-
8
- **Which hook blocked the command?**
9
-
10
- **What was the command?**
11
-
12
- **Why should it be allowed?**
@@ -1,14 +0,0 @@
1
- name: Tests
2
- on: [push, pull_request]
3
- jobs:
4
- test:
5
- runs-on: ubuntu-latest
6
- steps:
7
- - uses: actions/checkout@v4
8
- - uses: actions/setup-node@v4
9
- with:
10
- node-version: '20'
11
- - run: sudo apt-get install -y jq
12
- - run: node index.mjs --help
13
- - run: node index.mjs --dry-run
14
- - run: bash test.sh
package/test.sh DELETED
@@ -1,135 +0,0 @@
1
- #!/bin/bash
2
- # cc-safe-setup hook tests
3
- # Run: bash test.sh
4
- # All hooks are tested by piping JSON input and checking exit codes
5
-
6
- set -euo pipefail
7
-
8
- PASS=0
9
- FAIL=0
10
- SCRIPTS_JSON="$(dirname "$0")/scripts.json"
11
-
12
- # Extract hook scripts from scripts.json
13
- extract_hook() {
14
- python3 -c "import json; print(json.load(open('$SCRIPTS_JSON'))['$1'])" > "/tmp/test-$1.sh"
15
- chmod +x "/tmp/test-$1.sh"
16
- }
17
-
18
- test_hook() {
19
- local name="$1" input="$2" expected_exit="$3" desc="$4"
20
- local actual_exit=0
21
- echo "$input" | bash "/tmp/test-$name.sh" > /dev/null 2>/dev/null || actual_exit=$?
22
- if [ "$actual_exit" -eq "$expected_exit" ]; then
23
- echo " PASS: $desc"
24
- PASS=$((PASS + 1))
25
- else
26
- echo " FAIL: $desc (expected exit $expected_exit, got $actual_exit)"
27
- FAIL=$((FAIL + 1))
28
- fi
29
- }
30
-
31
- echo "cc-safe-setup hook tests"
32
- echo "========================"
33
- echo ""
34
-
35
- # --- destructive-guard ---
36
- echo "destructive-guard:"
37
- extract_hook "destructive-guard"
38
- test_hook "destructive-guard" '{"tool_input":{"command":"ls -la"}}' 0 "safe command passes"
39
- test_hook "destructive-guard" '{"tool_input":{"command":"rm -rf /"}}' 2 "rm -rf / blocked"
40
- test_hook "destructive-guard" '{"tool_input":{"command":"rm -rf ~/"}}' 2 "rm -rf ~/ blocked"
41
- test_hook "destructive-guard" '{"tool_input":{"command":"rm -rf ../"}}' 2 "rm -rf ../ blocked"
42
- test_hook "destructive-guard" '{"tool_input":{"command":"rm -rf node_modules"}}' 0 "rm -rf node_modules allowed"
43
- test_hook "destructive-guard" '{"tool_input":{"command":"git reset --hard"}}' 2 "git reset --hard blocked"
44
- test_hook "destructive-guard" '{"tool_input":{"command":"git reset --soft HEAD~1"}}' 0 "git reset --soft allowed"
45
- test_hook "destructive-guard" '{"tool_input":{"command":"git clean -fd"}}' 2 "git clean -fd blocked"
46
- test_hook "destructive-guard" '{"tool_input":{"command":"chmod -R 777 /"}}' 2 "chmod 777 / blocked"
47
- test_hook "destructive-guard" '{"tool_input":{"command":"find / -delete"}}' 2 "find / -delete blocked"
48
- test_hook "destructive-guard" '{"tool_input":{"command":"echo git reset --hard"}}' 0 "git reset in echo not blocked"
49
- test_hook "destructive-guard" '{"tool_input":{"command":"sudo rm -rf /home"}}' 2 "sudo rm -rf blocked"
50
- test_hook "destructive-guard" '{"tool_input":{"command":"sudo apt install jq"}}' 0 "safe sudo command allowed"
51
- echo ""
52
-
53
- # --- branch-guard ---
54
- echo "branch-guard:"
55
- extract_hook "branch-guard"
56
- test_hook "branch-guard" '{"tool_input":{"command":"git push origin feature-branch"}}' 0 "push to feature allowed"
57
- test_hook "branch-guard" '{"tool_input":{"command":"git push -u origin my-branch"}}' 0 "push -u to branch allowed"
58
- test_hook "branch-guard" '{"tool_input":{"command":"git push origin main"}}' 2 "push to main blocked"
59
- test_hook "branch-guard" '{"tool_input":{"command":"git push origin master"}}' 2 "push to master blocked"
60
- test_hook "branch-guard" '{"tool_input":{"command":"git push --force origin feature"}}' 2 "force push blocked"
61
- test_hook "branch-guard" '{"tool_input":{"command":"git push -f origin feature"}}' 2 "force push -f blocked"
62
- test_hook "branch-guard" '{"tool_input":{"command":"git push --force-with-lease origin feature"}}' 2 "force-with-lease blocked"
63
- test_hook "branch-guard" '{"tool_input":{"command":"git status"}}' 0 "non-push git command passes"
64
- test_hook "branch-guard" '{"tool_input":{"command":"npm install"}}' 0 "non-git command passes"
65
- echo ""
66
-
67
- # --- secret-guard ---
68
- echo "secret-guard:"
69
- extract_hook "secret-guard"
70
- test_hook "secret-guard" '{"tool_input":{"command":"git add src/index.js"}}' 0 "git add normal file allowed"
71
- test_hook "secret-guard" '{"tool_input":{"command":"git add .env"}}' 2 "git add .env blocked"
72
- test_hook "secret-guard" '{"tool_input":{"command":"git add .env.local"}}' 2 "git add .env.local blocked"
73
- test_hook "secret-guard" '{"tool_input":{"command":"git add credentials.json"}}' 2 "git add credentials.json blocked"
74
- test_hook "secret-guard" '{"tool_input":{"command":"git add id_rsa"}}' 2 "git add id_rsa blocked"
75
- test_hook "secret-guard" '{"tool_input":{"command":"git add server.key"}}' 2 "git add .key file blocked"
76
- test_hook "secret-guard" '{"tool_input":{"command":"npm install"}}' 0 "non-git command passes"
77
- test_hook "secret-guard" '{"tool_input":{"command":"git commit -m test"}}' 0 "git commit passes"
78
- echo ""
79
-
80
- # --- comment-strip ---
81
- echo "comment-strip:"
82
- extract_hook "comment-strip"
83
- # comment-strip outputs JSON on stdout when it modifies, exit 0 always
84
- local_exit=0
85
- result=$(echo '{"tool_input":{"command":"# check status\ngit status"}}' | bash /tmp/test-comment-strip.sh 2>/dev/null) || local_exit=$?
86
- if [ "$local_exit" -eq 0 ] && echo "$result" | python3 -c "import json,sys; d=json.load(sys.stdin); assert 'git status' in d['hookSpecificOutput']['updatedInput']['command']" 2>/dev/null; then
87
- echo " PASS: strips comment, returns clean command"
88
- PASS=$((PASS + 1))
89
- else
90
- echo " FAIL: comment stripping"
91
- FAIL=$((FAIL + 1))
92
- fi
93
- result2=$(echo '{"tool_input":{"command":"git status"}}' | bash /tmp/test-comment-strip.sh 2>/dev/null) || true
94
- if [ -z "$result2" ]; then
95
- echo " PASS: no-comment command passes through unchanged"
96
- PASS=$((PASS + 1))
97
- else
98
- echo " FAIL: should pass through without modification"
99
- FAIL=$((FAIL + 1))
100
- fi
101
- echo ""
102
-
103
- # --- cd-git-allow ---
104
- echo "cd-git-allow:"
105
- extract_hook "cd-git-allow"
106
- local_exit=0
107
- result=$(echo '{"tool_input":{"command":"cd /tmp && git log"}}' | bash /tmp/test-cd-git-allow.sh 2>/dev/null) || local_exit=$?
108
- if [ "$local_exit" -eq 0 ] && echo "$result" | grep -q "permissionDecision"; then
109
- echo " PASS: cd+git log auto-approved"
110
- PASS=$((PASS + 1))
111
- else
112
- echo " FAIL: cd+git log should be auto-approved"
113
- FAIL=$((FAIL + 1))
114
- fi
115
- result2=$(echo '{"tool_input":{"command":"cd /tmp && git push origin main"}}' | bash /tmp/test-cd-git-allow.sh 2>/dev/null) || true
116
- if ! echo "$result2" | grep -q "permissionDecision" 2>/dev/null; then
117
- echo " PASS: cd+git push NOT auto-approved"
118
- PASS=$((PASS + 1))
119
- else
120
- echo " FAIL: cd+git push should not be auto-approved"
121
- FAIL=$((FAIL + 1))
122
- fi
123
- test_hook "cd-git-allow" '{"tool_input":{"command":"npm install"}}' 0 "non-cd command passes"
124
- echo ""
125
-
126
- # --- Summary ---
127
- echo "========================"
128
- TOTAL=$((PASS + FAIL))
129
- echo "Results: $PASS/$TOTAL passed"
130
- if [ "$FAIL" -gt 0 ]; then
131
- echo "FAILURES: $FAIL"
132
- exit 1
133
- else
134
- echo "All tests passed!"
135
- fi