cc-safe-setup 28.6.0 → 28.8.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.
package/README.md
CHANGED
|
@@ -87,7 +87,7 @@ Each hook exists because a real incident happened without it.
|
|
|
87
87
|
| `--scan [--apply]` | Tech stack detection |
|
|
88
88
|
| `--export / --import` | Team config sharing |
|
|
89
89
|
| `--verify` | Test each hook |
|
|
90
|
-
| `--install-example <name>` | Install from
|
|
90
|
+
| `--install-example <name>` | Install from 336 examples |
|
|
91
91
|
| `--examples [filter]` | Browse examples by keyword |
|
|
92
92
|
| `--full` | All-in-one setup |
|
|
93
93
|
| `--status` | Check installed hooks |
|
package/TROUBLESHOOTING.md
CHANGED
|
@@ -232,6 +232,22 @@ echo "[$(date -Iseconds)] BLOCKED: reason | cmd: $COMMAND" >> "$LOG"
|
|
|
232
232
|
|
|
233
233
|
Then view with: `npx cc-safe-setup --watch` or `npx cc-safe-setup --stats`
|
|
234
234
|
|
|
235
|
+
## "claude -p returns empty output when Stop hook is configured"
|
|
236
|
+
|
|
237
|
+
This is a known Claude Code v2.1.83 bug ([#38651](https://github.com/anthropics/claude-code/issues/38651)), not a cc-safe-setup issue. Any Stop hook — even `true` — causes `-p` (print mode) to return empty stdout.
|
|
238
|
+
|
|
239
|
+
**Workaround:** Temporarily remove Stop hooks when using `-p` mode:
|
|
240
|
+
|
|
241
|
+
```bash
|
|
242
|
+
# Quick toggle: comment out Stop hooks before -p commands
|
|
243
|
+
npx cc-safe-setup --status # See which hooks are active
|
|
244
|
+
# Manually comment out Stop hooks in ~/.claude/settings.json
|
|
245
|
+
# Run your -p command
|
|
246
|
+
# Uncomment Stop hooks after
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
This should be fixed in a future Claude Code release.
|
|
250
|
+
|
|
235
251
|
## Still Stuck?
|
|
236
252
|
|
|
237
253
|
1. Wrap the hook with debug wrapper: `npx cc-safe-setup --install-example hook-debug-wrapper`
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# allow-claude-settings.sh — PermissionRequest hook
|
|
3
|
+
# Trigger: PermissionRequest
|
|
4
|
+
# Matcher: Edit|Write
|
|
5
|
+
#
|
|
6
|
+
# Auto-approves writes to .claude/ configuration files.
|
|
7
|
+
# Use this in isolated environments (containers, VMs) where
|
|
8
|
+
# bypassPermissions is enabled but .claude/ writes still prompt.
|
|
9
|
+
#
|
|
10
|
+
# See: https://github.com/anthropics/claude-code/issues/36044
|
|
11
|
+
# See: https://github.com/anthropics/claude-code/issues/37765
|
|
12
|
+
#
|
|
13
|
+
# WARNING: Only use in environments where you trust Claude's edits
|
|
14
|
+
# to your configuration. In shared or production environments,
|
|
15
|
+
# keep the default prompts.
|
|
16
|
+
|
|
17
|
+
INPUT=$(cat)
|
|
18
|
+
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
|
|
19
|
+
[ -z "$FILE_PATH" ] && exit 0
|
|
20
|
+
|
|
21
|
+
# Allow .claude/ writes (settings, rules, agents, skills, hooks)
|
|
22
|
+
if echo "$FILE_PATH" | grep -qE '\.claude/'; then
|
|
23
|
+
jq -n '{
|
|
24
|
+
hookSpecificOutput: {
|
|
25
|
+
hookEventName: "PermissionRequest",
|
|
26
|
+
permissionDecision: "allow",
|
|
27
|
+
permissionDecisionReason: "Allowed: .claude/ directory (isolated environment)"
|
|
28
|
+
}
|
|
29
|
+
}'
|
|
30
|
+
exit 0
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
exit 0
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# allow-protected-dirs.sh — PermissionRequest hook
|
|
3
|
+
# Trigger: PermissionRequest
|
|
4
|
+
# Matcher: Edit|Write
|
|
5
|
+
#
|
|
6
|
+
# Auto-approves writes to ALL protected directories (.claude/, .git/,
|
|
7
|
+
# .vscode/, .idea/). Equivalent to full bypassPermissions for file edits.
|
|
8
|
+
#
|
|
9
|
+
# USE CASE: Docker containers, CI/CD, disposable VMs where you want
|
|
10
|
+
# zero prompts and understand the risks.
|
|
11
|
+
#
|
|
12
|
+
# WARNING: This is the most permissive PermissionRequest hook possible.
|
|
13
|
+
# It bypasses ALL built-in file protection. Do NOT use in shared or
|
|
14
|
+
# production environments. Prefer allow-git-hooks-dir.sh or
|
|
15
|
+
# allow-claude-settings.sh for targeted bypass.
|
|
16
|
+
|
|
17
|
+
INPUT=$(cat)
|
|
18
|
+
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
|
|
19
|
+
[ -z "$FILE_PATH" ] && exit 0
|
|
20
|
+
|
|
21
|
+
if echo "$FILE_PATH" | grep -qE '\.(claude|git|vscode|idea)/'; then
|
|
22
|
+
jq -n '{
|
|
23
|
+
hookSpecificOutput: {
|
|
24
|
+
hookEventName: "PermissionRequest",
|
|
25
|
+
permissionDecision: "allow",
|
|
26
|
+
permissionDecisionReason: "Allowed: protected directory (full bypass)"
|
|
27
|
+
}
|
|
28
|
+
}'
|
|
29
|
+
exit 0
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
exit 0
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# auto-approve-compound-git.sh — PermissionRequest hook
|
|
3
|
+
# Trigger: PermissionRequest
|
|
4
|
+
# Matcher: Bash
|
|
5
|
+
#
|
|
6
|
+
# Auto-approves compound git commands that the built-in permission
|
|
7
|
+
# system fails to match. The wildcard pattern Bash(git:*) only matches
|
|
8
|
+
# simple commands like "git status" but not "cd src && git log" or
|
|
9
|
+
# "git add file.txt && git commit -m 'fix'".
|
|
10
|
+
#
|
|
11
|
+
# This hook runs AFTER the built-in permission check fails (because
|
|
12
|
+
# compound commands don't match Bash(git:*)), and approves if ALL
|
|
13
|
+
# individual commands in the chain are safe git operations.
|
|
14
|
+
#
|
|
15
|
+
# See: https://github.com/anthropics/claude-code/issues/30519
|
|
16
|
+
# See: https://github.com/anthropics/claude-code/issues/16561
|
|
17
|
+
|
|
18
|
+
INPUT=$(cat)
|
|
19
|
+
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
20
|
+
[ -z "$COMMAND" ] && exit 0
|
|
21
|
+
|
|
22
|
+
# Split on && ; || and check each part
|
|
23
|
+
# Only approve if EVERY component is a safe git command or cd
|
|
24
|
+
SAFE=true
|
|
25
|
+
while IFS= read -r part; do
|
|
26
|
+
# Trim whitespace
|
|
27
|
+
part=$(echo "$part" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
|
|
28
|
+
[ -z "$part" ] && continue
|
|
29
|
+
|
|
30
|
+
# Allow: cd, git (read ops), git add, git commit, git stash, git branch
|
|
31
|
+
if echo "$part" | grep -qE '^(cd |git (status|log|diff|show|branch|tag|stash|add|commit|fetch|pull|checkout|switch|restore|rebase|merge|cherry-pick|remote|config) )'; then
|
|
32
|
+
continue
|
|
33
|
+
fi
|
|
34
|
+
# Allow simple git commands without args
|
|
35
|
+
if echo "$part" | grep -qE '^git (status|log|diff|show|branch|tag|stash|fetch|pull)$'; then
|
|
36
|
+
continue
|
|
37
|
+
fi
|
|
38
|
+
# Any non-git command = not safe
|
|
39
|
+
SAFE=false
|
|
40
|
+
break
|
|
41
|
+
done < <(echo "$COMMAND" | tr '&' '\n' | tr ';' '\n' | tr '|' '\n')
|
|
42
|
+
|
|
43
|
+
if [ "$SAFE" = "true" ]; then
|
|
44
|
+
jq -n '{
|
|
45
|
+
hookSpecificOutput: {
|
|
46
|
+
hookEventName: "PermissionRequest",
|
|
47
|
+
permissionDecision: "allow",
|
|
48
|
+
permissionDecisionReason: "Allowed: compound git command (all parts are safe git ops)"
|
|
49
|
+
}
|
|
50
|
+
}'
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
exit 0
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cc-safe-setup",
|
|
3
|
-
"version": "28.
|
|
4
|
-
"description": "One command to make Claude Code safe.
|
|
3
|
+
"version": "28.8.0",
|
|
4
|
+
"description": "One command to make Claude Code safe. 344 hooks (8 built-in + 336 examples). 49 CLI commands. 1018 tests. 5 languages.",
|
|
5
5
|
"main": "index.mjs",
|
|
6
6
|
"bin": {
|
|
7
7
|
"cc-safe-setup": "index.mjs"
|