cc-safe-setup 1.5.1 → 1.5.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
@@ -82,6 +82,8 @@ Safe to run multiple times. Existing settings are preserved. A backup is created
82
82
 
83
83
  **Note:** Hooks are skipped when Claude Code runs with `--bare` or `--dangerously-skip-permissions`. These modes bypass all safety hooks by design.
84
84
 
85
+ **Known limitation:** In headless mode (`-p` / `--print`), hook exit code 2 may not block tool execution ([#36071](https://github.com/anthropics/claude-code/issues/36071)). For CI pipelines, use interactive mode with hooks rather than `-p` mode.
86
+
85
87
  ## Before / After
86
88
 
87
89
  Run `npx cc-health-check` to see the difference:
@@ -116,7 +118,7 @@ npx cc-health-check
116
118
 
117
119
  ## Full Kit
118
120
 
119
- cc-safe-setup gives you 7 essential hooks. For the complete autonomous operation toolkit:
121
+ cc-safe-setup gives you 8 essential hooks. For the complete autonomous operation toolkit:
120
122
 
121
123
  **[Claude Code Ops Kit](https://yurukusa.github.io/cc-ops-kit-landing/?utm_source=github&utm_medium=readme&utm_campaign=safe-setup)** — 16 hooks + 5 templates + 3 exclusive tools + install.sh. Production-ready in 15 minutes.
122
124
 
@@ -124,20 +126,36 @@ Or start with the free hooks: [claude-code-hooks](https://github.com/yurukusa/cl
124
126
 
125
127
  ## Examples
126
128
 
127
- Need custom hooks beyond the 7 built-in ones? See [`examples/`](examples/) for ready-to-use recipes:
129
+ Need custom hooks beyond the 8 built-in ones? See [`examples/`](examples/) for ready-to-use recipes:
128
130
 
129
131
  - **auto-approve-git-read.sh** — Auto-approve `git status`, `git log`, even with `-C` flags
130
132
  - **auto-approve-ssh.sh** — Auto-approve safe SSH commands (`uptime`, `whoami`, etc.)
131
133
  - **enforce-tests.sh** — Warn when source files change without corresponding test files
132
134
  - **notify-waiting.sh** — Desktop notification when Claude Code waits for input (macOS/Linux/WSL2)
135
+ - **edit-guard.sh** — Block Edit/Write to protected files (defense-in-depth for [#37210](https://github.com/anthropics/claude-code/issues/37210))
136
+ - **auto-approve-build.sh** — Auto-approve npm/yarn/cargo/go/python build, test, and lint commands
133
137
 
134
138
  ## Learn More
135
139
 
136
140
  - [Official Hooks Reference](https://code.claude.com/docs/en/hooks) — Claude Code hooks documentation
137
- - [Hooks Cookbook](https://github.com/yurukusa/claude-code-hooks/blob/main/COOKBOOK.md) — 8 ready-to-use recipes from real GitHub Issues
141
+ - [Hooks Cookbook](https://github.com/yurukusa/claude-code-hooks/blob/main/COOKBOOK.md) — 9 ready-to-use recipes from real GitHub Issues
138
142
  - [Japanese guide (Qiita)](https://qiita.com/yurukusa/items/a9714b33f5d974e8f1e8) — この記事の日本語解説
139
143
  - [The incident that inspired this tool](https://github.com/anthropics/claude-code/issues/36339) — NTFS junction rm -rf
140
144
 
145
+ ## FAQ
146
+
147
+ **Q: I installed hooks but Claude says "Unknown skill: claude-code-hooks:setup"**
148
+
149
+ cc-safe-setup installs **hooks**, not skills or plugins. Hooks run automatically in the background — you don't invoke them manually. After install + restart, try running a dangerous command; the hook will block it silently.
150
+
151
+ **Q: `cc-health-check` says to run `cc-safe-setup` but I already did**
152
+
153
+ cc-safe-setup covers Safety Guards (75-100%) and Monitoring (context-monitor). The other health check dimensions (Code Quality, Recovery, Coordination) require additional CLAUDE.md configuration or manual hook installation from [claude-code-hooks](https://github.com/yurukusa/claude-code-hooks).
154
+
155
+ **Q: Will hooks slow down Claude Code?**
156
+
157
+ No. Each hook runs in ~10ms. They only fire on specific events (before tool use, after edits, on stop). No polling, no background processes.
158
+
141
159
  ## Contributing
142
160
 
143
161
  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).
@@ -0,0 +1,43 @@
1
+ #!/bin/bash
2
+ # auto-approve-build.sh — Auto-approve build and test commands
3
+ #
4
+ # Solves: Permission prompts for npm/yarn/pnpm build/test/lint commands
5
+ # that slow down autonomous workflows
6
+ #
7
+ # Usage: Add to settings.json as a PreToolUse hook
8
+ #
9
+ # {
10
+ # "hooks": {
11
+ # "PreToolUse": [{
12
+ # "matcher": "Bash",
13
+ # "hooks": [{ "type": "command", "command": "~/.claude/hooks/auto-approve-build.sh" }]
14
+ # }]
15
+ # }
16
+ # }
17
+
18
+ INPUT=$(cat)
19
+ TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
20
+ [ "$TOOL" != "Bash" ] && exit 0
21
+
22
+ CMD=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
23
+ [ -z "$CMD" ] && exit 0
24
+
25
+ # Auto-approve safe build/test/lint commands
26
+ if echo "$CMD" | grep -qE '^\s*(npm|yarn|pnpm|bun|npx)\s+(run\s+)?(build|test|lint|check|typecheck|format|dev|start|ci)'; then
27
+ echo '{"decision":"approve"}'
28
+ exit 0
29
+ fi
30
+
31
+ # Auto-approve cargo/go/make build commands
32
+ if echo "$CMD" | grep -qE '^\s*(cargo\s+(build|test|check|clippy|fmt)|go\s+(build|test|vet|fmt)|make\s+(build|test|check|lint))'; then
33
+ echo '{"decision":"approve"}'
34
+ exit 0
35
+ fi
36
+
37
+ # Auto-approve python test/lint
38
+ if echo "$CMD" | grep -qE '^\s*(python|python3)\s+(-m\s+)?(pytest|unittest|mypy|ruff|black|isort|flake8)'; then
39
+ echo '{"decision":"approve"}'
40
+ exit 0
41
+ fi
42
+
43
+ exit 0
@@ -0,0 +1,48 @@
1
+ #!/bin/bash
2
+ # edit-guard.sh — Block Edit/Write to protected files
3
+ #
4
+ # Solves: PreToolUse deny being ignored for Edit/Write tools (#37210)
5
+ # Uses chmod as defense-in-depth — makes file read-only before deny
6
+ #
7
+ # GitHub Issue: #37210
8
+ #
9
+ # Usage: Add to settings.json as a PreToolUse hook
10
+ #
11
+ # {
12
+ # "hooks": {
13
+ # "PreToolUse": [{
14
+ # "matcher": "",
15
+ # "hooks": [{ "type": "command", "command": "~/.claude/hooks/edit-guard.sh" }]
16
+ # }]
17
+ # }
18
+ # }
19
+
20
+ INPUT=$(cat)
21
+ TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
22
+ FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
23
+
24
+ # Only check Edit and Write tools
25
+ if [[ "$TOOL" != "Edit" && "$TOOL" != "Write" ]]; then
26
+ exit 0
27
+ fi
28
+
29
+ # Define protected patterns (customize these)
30
+ PROTECTED_PATTERNS=(
31
+ "*.env*"
32
+ "*credentials*"
33
+ "*secrets*"
34
+ "*.pem"
35
+ "*.key"
36
+ "*/.claude/settings.json"
37
+ )
38
+
39
+ for pattern in "${PROTECTED_PATTERNS[@]}"; do
40
+ if [[ "$FILE" == $pattern ]]; then
41
+ # Defense-in-depth: make file read-only
42
+ chmod 444 "$FILE" 2>/dev/null
43
+ echo "BLOCKED: Edit/Write denied for protected file: $FILE" >&2
44
+ exit 2
45
+ fi
46
+ done
47
+
48
+ exit 0
package/index.mjs CHANGED
@@ -203,6 +203,10 @@ async function verify() {
203
203
  { hook: 'secret-guard', input: '{"tool_input":{"command":"git add .env"}}', expect: 2, desc: 'blocks git add .env' },
204
204
  { hook: 'secret-guard', input: '{"tool_input":{"command":"git add src/app.js"}}', expect: 0, desc: 'allows git add safe files' },
205
205
  { hook: 'api-error-alert', input: '{"stop_reason":"user"}', expect: 0, desc: 'ignores normal stops' },
206
+ { hook: 'destructive-guard', input: '{"tool_input":{"command":"cd /tmp && rm -rf /"}}', expect: 2, desc: 'blocks compound rm -rf' },
207
+ { hook: 'branch-guard', input: '{"tool_input":{"command":"git push --force origin feature"}}', expect: 2, desc: 'blocks force-push' },
208
+ { hook: 'destructive-guard', input: '{"tool_input":{"command":"git reset --hard HEAD~5"}}', expect: 2, desc: 'blocks git reset --hard' },
209
+ { hook: 'destructive-guard', input: '{"tool_input":{"command":"sudo rm -rf /var"}}', expect: 2, desc: 'blocks sudo + destructive' },
206
210
  ];
207
211
 
208
212
  let pass = 0, fail = 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cc-safe-setup",
3
- "version": "1.5.1",
3
+ "version": "1.5.3",
4
4
  "description": "One command to make Claude Code safe for autonomous operation. 8 hooks: destructive blocker, branch guard, force-push protection, secret leak prevention, syntax checks, and more.",
5
5
  "main": "index.mjs",
6
6
  "bin": {