cc-safe-setup 2.0.2 → 2.0.4
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 +3 -1
- package/examples/README.md +2 -0
- package/examples/branch-name-check.sh +46 -0
- package/examples/timeout-guard.sh +63 -0
- package/index.mjs +5 -3
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -156,11 +156,13 @@ Or browse all available examples in [`examples/`](examples/):
|
|
|
156
156
|
- **test-before-push.sh** — Block `git push` when tests haven't been run ([#36970](https://github.com/anthropics/claude-code/issues/36970))
|
|
157
157
|
- **large-file-guard.sh** — Warn when Write tool creates files over 500KB
|
|
158
158
|
- **commit-message-check.sh** — Warn on non-conventional commit messages (feat:, fix:, docs:, etc.)
|
|
159
|
+
- **env-var-check.sh** — Block hardcoded API keys (sk-, ghp_, glpat-) in export commands
|
|
160
|
+
- **timeout-guard.sh** — Warn before long-running commands (npm start, rails s, docker-compose up)
|
|
159
161
|
|
|
160
162
|
## Learn More
|
|
161
163
|
|
|
162
164
|
- [Official Hooks Reference](https://code.claude.com/docs/en/hooks) — Claude Code hooks documentation
|
|
163
|
-
- [Hooks Cookbook](https://github.com/yurukusa/claude-code-hooks/blob/main/COOKBOOK.md) —
|
|
165
|
+
- [Hooks Cookbook](https://github.com/yurukusa/claude-code-hooks/blob/main/COOKBOOK.md) — 17 ready-to-use recipes from real GitHub Issues
|
|
164
166
|
- [Japanese guide (Qiita)](https://qiita.com/yurukusa/items/a9714b33f5d974e8f1e8) — この記事の日本語解説
|
|
165
167
|
- [The incident that inspired this tool](https://github.com/anthropics/claude-code/issues/36339) — NTFS junction rm -rf
|
|
166
168
|
|
package/examples/README.md
CHANGED
|
@@ -25,6 +25,7 @@ npx cc-safe-setup --examples
|
|
|
25
25
|
| **protect-dotfiles.sh** | Block changes to ~/.bashrc, ~/.aws/, ~/.ssh/ | [#37478](https://github.com/anthropics/claude-code/issues/37478) |
|
|
26
26
|
| **scope-guard.sh** | Block operations outside project directory | [#36233](https://github.com/anthropics/claude-code/issues/36233) |
|
|
27
27
|
| **test-before-push.sh** | Block git push without tests | [#36970](https://github.com/anthropics/claude-code/issues/36970) |
|
|
28
|
+
| **timeout-guard.sh** | Warn before long-running commands (servers, watchers) | |
|
|
28
29
|
|
|
29
30
|
## Auto-Approve
|
|
30
31
|
|
|
@@ -40,6 +41,7 @@ npx cc-safe-setup --examples
|
|
|
40
41
|
|
|
41
42
|
| Hook | Purpose | Issue |
|
|
42
43
|
|------|---------|-------|
|
|
44
|
+
| **branch-name-check.sh** | Warn on non-conventional branch names | |
|
|
43
45
|
| **commit-message-check.sh** | Warn on non-conventional commit messages | |
|
|
44
46
|
| **edit-guard.sh** | Block Edit/Write to protected files | [#37210](https://github.com/anthropics/claude-code/issues/37210) |
|
|
45
47
|
| **enforce-tests.sh** | Warn when source changes without tests | |
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# branch-name-check.sh — Warn when creating branches with non-standard names
|
|
3
|
+
#
|
|
4
|
+
# Checks for conventional branch naming (feature/, fix/, hotfix/, etc.)
|
|
5
|
+
# and blocks branches with spaces, uppercase, or special characters.
|
|
6
|
+
#
|
|
7
|
+
# Usage: Add to settings.json as a PostToolUse hook
|
|
8
|
+
#
|
|
9
|
+
# {
|
|
10
|
+
# "hooks": {
|
|
11
|
+
# "PostToolUse": [{
|
|
12
|
+
# "matcher": "Bash",
|
|
13
|
+
# "hooks": [{ "type": "command", "command": "~/.claude/hooks/branch-name-check.sh" }]
|
|
14
|
+
# }]
|
|
15
|
+
# }
|
|
16
|
+
# }
|
|
17
|
+
|
|
18
|
+
INPUT=$(cat)
|
|
19
|
+
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
20
|
+
|
|
21
|
+
[[ -z "$COMMAND" ]] && exit 0
|
|
22
|
+
|
|
23
|
+
# Only check branch creation commands
|
|
24
|
+
if ! echo "$COMMAND" | grep -qE 'git\s+(checkout\s+-b|branch|switch\s+-c)\s'; then
|
|
25
|
+
exit 0
|
|
26
|
+
fi
|
|
27
|
+
|
|
28
|
+
# Extract branch name
|
|
29
|
+
BRANCH=$(echo "$COMMAND" | grep -oP '(?:checkout\s+-b|branch|switch\s+-c)\s+\K\S+')
|
|
30
|
+
[[ -z "$BRANCH" ]] && exit 0
|
|
31
|
+
|
|
32
|
+
# Check for spaces or special characters
|
|
33
|
+
if echo "$BRANCH" | grep -qP '[^a-zA-Z0-9/_.-]'; then
|
|
34
|
+
echo "" >&2
|
|
35
|
+
echo "WARNING: Branch name contains special characters: $BRANCH" >&2
|
|
36
|
+
echo "Use only: a-z, 0-9, /, -, ., _" >&2
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
# Check for conventional prefix
|
|
40
|
+
if ! echo "$BRANCH" | grep -qE '^(feature|fix|hotfix|bugfix|release|chore|docs|refactor|test|ci)/'; then
|
|
41
|
+
echo "" >&2
|
|
42
|
+
echo "NOTE: Branch doesn't follow conventional naming." >&2
|
|
43
|
+
echo "Consider: feature/, fix/, hotfix/, chore/, docs/" >&2
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
exit 0
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# timeout-guard.sh — Warn before long-running commands
|
|
3
|
+
#
|
|
4
|
+
# Solves: Claude running commands that hang indefinitely
|
|
5
|
+
# (e.g., servers, watchers, interactive tools) without
|
|
6
|
+
# using run_in_background.
|
|
7
|
+
#
|
|
8
|
+
# Usage: Add to settings.json as a PreToolUse hook
|
|
9
|
+
#
|
|
10
|
+
# {
|
|
11
|
+
# "hooks": {
|
|
12
|
+
# "PreToolUse": [{
|
|
13
|
+
# "matcher": "Bash",
|
|
14
|
+
# "hooks": [{ "type": "command", "command": "~/.claude/hooks/timeout-guard.sh" }]
|
|
15
|
+
# }]
|
|
16
|
+
# }
|
|
17
|
+
# }
|
|
18
|
+
|
|
19
|
+
INPUT=$(cat)
|
|
20
|
+
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
21
|
+
|
|
22
|
+
[[ -z "$COMMAND" ]] && exit 0
|
|
23
|
+
|
|
24
|
+
# Detect commands that typically run forever
|
|
25
|
+
FOREVER_PATTERNS=(
|
|
26
|
+
"npm start"
|
|
27
|
+
"npm run dev"
|
|
28
|
+
"npm run serve"
|
|
29
|
+
"yarn start"
|
|
30
|
+
"yarn dev"
|
|
31
|
+
"python -m http.server"
|
|
32
|
+
"python manage.py runserver"
|
|
33
|
+
"flask run"
|
|
34
|
+
"uvicorn"
|
|
35
|
+
"nodemon"
|
|
36
|
+
"webpack serve"
|
|
37
|
+
"vite"
|
|
38
|
+
"next dev"
|
|
39
|
+
"ng serve"
|
|
40
|
+
"rails server"
|
|
41
|
+
"rails s"
|
|
42
|
+
"php artisan serve"
|
|
43
|
+
"cargo watch"
|
|
44
|
+
"go run.*server"
|
|
45
|
+
"docker-compose up$"
|
|
46
|
+
"tail -f"
|
|
47
|
+
"watch "
|
|
48
|
+
"inotifywait"
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
for pattern in "${FOREVER_PATTERNS[@]}"; do
|
|
52
|
+
if echo "$COMMAND" | grep -qiE "$pattern"; then
|
|
53
|
+
RUN_BG=$(echo "$INPUT" | jq -r '.tool_input.run_in_background // false' 2>/dev/null)
|
|
54
|
+
if [[ "$RUN_BG" != "true" ]]; then
|
|
55
|
+
echo "" >&2
|
|
56
|
+
echo "WARNING: This command may run indefinitely: $pattern" >&2
|
|
57
|
+
echo "Consider using run_in_background: true" >&2
|
|
58
|
+
fi
|
|
59
|
+
break
|
|
60
|
+
fi
|
|
61
|
+
done
|
|
62
|
+
|
|
63
|
+
exit 0
|
package/index.mjs
CHANGED
|
@@ -183,10 +183,10 @@ function status() {
|
|
|
183
183
|
const exampleFiles = [
|
|
184
184
|
'allowlist.sh', 'auto-approve-build.sh', 'auto-approve-docker.sh',
|
|
185
185
|
'auto-approve-git-read.sh', 'auto-approve-python.sh', 'auto-approve-ssh.sh',
|
|
186
|
-
'auto-checkpoint.sh', 'auto-snapshot.sh', 'block-database-wipe.sh', 'commit-message-check.sh',
|
|
186
|
+
'auto-checkpoint.sh', 'auto-snapshot.sh', 'block-database-wipe.sh', 'commit-message-check.sh', 'env-var-check.sh',
|
|
187
187
|
'deploy-guard.sh', 'edit-guard.sh', 'enforce-tests.sh', 'git-config-guard.sh',
|
|
188
188
|
'large-file-guard.sh', 'network-guard.sh', 'notify-waiting.sh',
|
|
189
|
-
'protect-dotfiles.sh', 'scope-guard.sh', 'test-before-push.sh',
|
|
189
|
+
'protect-dotfiles.sh', 'scope-guard.sh', 'test-before-push.sh', 'timeout-guard.sh',
|
|
190
190
|
];
|
|
191
191
|
const installedExamples = exampleFiles.filter(f => existsSync(join(HOOKS_DIR, f)));
|
|
192
192
|
if (installedExamples.length > 0) {
|
|
@@ -286,6 +286,7 @@ function examples() {
|
|
|
286
286
|
'protect-dotfiles.sh': 'Block modifications to ~/.bashrc, ~/.aws/, ~/.ssh/',
|
|
287
287
|
'scope-guard.sh': 'Block file operations outside project directory',
|
|
288
288
|
'test-before-push.sh': 'Block git push when tests have not passed',
|
|
289
|
+
'timeout-guard.sh': 'Warn before long-running commands (servers, watchers)',
|
|
289
290
|
'git-config-guard.sh': 'Block git config --global modifications',
|
|
290
291
|
},
|
|
291
292
|
'Auto-Approve': {
|
|
@@ -296,6 +297,7 @@ function examples() {
|
|
|
296
297
|
'auto-approve-ssh.sh': 'Auto-approve safe SSH commands (uptime, whoami)',
|
|
297
298
|
},
|
|
298
299
|
'Quality': {
|
|
300
|
+
'branch-name-check.sh': 'Warn on non-conventional branch names',
|
|
299
301
|
'commit-message-check.sh': 'Warn on non-conventional commit messages',
|
|
300
302
|
'edit-guard.sh': 'Block Edit/Write to protected files (.env, credentials)',
|
|
301
303
|
'enforce-tests.sh': 'Warn when source files change without test files',
|
|
@@ -312,7 +314,7 @@ function examples() {
|
|
|
312
314
|
|
|
313
315
|
console.log();
|
|
314
316
|
console.log(c.bold + ' cc-safe-setup --examples' + c.reset);
|
|
315
|
-
console.log(c.dim + '
|
|
317
|
+
console.log(c.dim + ' 23 hooks beyond the 8 built-in ones' + c.reset);
|
|
316
318
|
console.log();
|
|
317
319
|
|
|
318
320
|
for (const [cat, hooks] of Object.entries(CATEGORIES)) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cc-safe-setup",
|
|
3
|
-
"version": "2.0.
|
|
4
|
-
"description": "One command to make Claude Code safe for autonomous operation. 8 built-in hooks +
|
|
3
|
+
"version": "2.0.4",
|
|
4
|
+
"description": "One command to make Claude Code safe for autonomous operation. 8 built-in hooks + 23 installable examples. Destructive blocker, branch guard, database wipe protection, dotfile guard, and more.",
|
|
5
5
|
"main": "index.mjs",
|
|
6
6
|
"bin": {
|
|
7
7
|
"cc-safe-setup": "index.mjs"
|