cc-safe-setup 1.8.0 → 1.8.2
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 +4 -1
- package/examples/auto-approve-python.sh +47 -0
- package/examples/auto-snapshot.sh +51 -0
- package/index.mjs +2 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -25,6 +25,7 @@ Installs 8 production-tested safety hooks in ~10 seconds. Zero dependencies. No
|
|
|
25
25
|
✗ Force-push rewriting shared branch history
|
|
26
26
|
✗ API keys committed to public repos via git add .
|
|
27
27
|
✗ Syntax errors cascading through 30+ files
|
|
28
|
+
✗ Laravel migrate:fresh wiping production database
|
|
28
29
|
✗ Sessions losing all context with no warning
|
|
29
30
|
|
|
30
31
|
Hooks to install:
|
|
@@ -137,11 +138,13 @@ Need custom hooks beyond the 8 built-in ones? See [`examples/`](examples/) for r
|
|
|
137
138
|
- **auto-approve-build.sh** — Auto-approve npm/yarn/cargo/go/python build, test, and lint commands
|
|
138
139
|
- **auto-approve-docker.sh** — Auto-approve docker build, compose, ps, logs, and other safe commands
|
|
139
140
|
- **block-database-wipe.sh** — Block destructive database commands: Laravel `migrate:fresh`, Django `flush`, Rails `db:drop`, raw `DROP DATABASE` ([#37405](https://github.com/anthropics/claude-code/issues/37405) [#37439](https://github.com/anthropics/claude-code/issues/37439))
|
|
141
|
+
- **auto-approve-python.sh** — Auto-approve pytest, mypy, ruff, black, isort, flake8, pylint commands
|
|
142
|
+
- **auto-snapshot.sh** — Auto-save file snapshots before edits for rollback protection ([#37386](https://github.com/anthropics/claude-code/issues/37386) [#37457](https://github.com/anthropics/claude-code/issues/37457))
|
|
140
143
|
|
|
141
144
|
## Learn More
|
|
142
145
|
|
|
143
146
|
- [Official Hooks Reference](https://code.claude.com/docs/en/hooks) — Claude Code hooks documentation
|
|
144
|
-
- [Hooks Cookbook](https://github.com/yurukusa/claude-code-hooks/blob/main/COOKBOOK.md) —
|
|
147
|
+
- [Hooks Cookbook](https://github.com/yurukusa/claude-code-hooks/blob/main/COOKBOOK.md) — 12 ready-to-use recipes from real GitHub Issues
|
|
145
148
|
- [Japanese guide (Qiita)](https://qiita.com/yurukusa/items/a9714b33f5d974e8f1e8) — この記事の日本語解説
|
|
146
149
|
- [The incident that inspired this tool](https://github.com/anthropics/claude-code/issues/36339) — NTFS junction rm -rf
|
|
147
150
|
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# auto-approve-python.sh — Auto-approve Python development commands
|
|
3
|
+
#
|
|
4
|
+
# Solves: Permission prompts for pytest, mypy, ruff, black, isort
|
|
5
|
+
# that slow down autonomous Python development
|
|
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-python.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
|
+
# Python test runners
|
|
24
|
+
if echo "$COMMAND" | grep -qE '^\s*(pytest|python\s+-m\s+pytest|python\s+-m\s+unittest)(\s|$)'; then
|
|
25
|
+
jq -n '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow","permissionDecisionReason":"Python test auto-approved"}}'
|
|
26
|
+
exit 0
|
|
27
|
+
fi
|
|
28
|
+
|
|
29
|
+
# Linters and formatters
|
|
30
|
+
if echo "$COMMAND" | grep -qE '^\s*(ruff\s+(check|format)|black\s|isort\s|flake8\s|pylint\s|mypy\s|pyright\s)'; then
|
|
31
|
+
jq -n '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow","permissionDecisionReason":"Python lint/format auto-approved"}}'
|
|
32
|
+
exit 0
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
# Package management (read-only)
|
|
36
|
+
if echo "$COMMAND" | grep -qE '^\s*(pip\s+list|pip\s+show|pip\s+freeze|pipdeptree)(\s|$)'; then
|
|
37
|
+
jq -n '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow","permissionDecisionReason":"pip read-only auto-approved"}}'
|
|
38
|
+
exit 0
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
# Python syntax check
|
|
42
|
+
if echo "$COMMAND" | grep -qE '^\s*python3?\s+-m\s+py_compile\s'; then
|
|
43
|
+
jq -n '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow","permissionDecisionReason":"Python compile check auto-approved"}}'
|
|
44
|
+
exit 0
|
|
45
|
+
fi
|
|
46
|
+
|
|
47
|
+
exit 0
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# auto-snapshot.sh — Automatic file snapshots before every edit
|
|
3
|
+
#
|
|
4
|
+
# Solves: Claude reverting verified changes after encountering
|
|
5
|
+
# contradictory information (sycophantic capitulation)
|
|
6
|
+
# (#37386, #37457)
|
|
7
|
+
#
|
|
8
|
+
# How it works:
|
|
9
|
+
# - Runs as a PreToolUse hook on Edit/Write
|
|
10
|
+
# - Copies the file to ~/.claude/snapshots/ before modification
|
|
11
|
+
# - When Claude walks back correct work, diff the snapshot
|
|
12
|
+
# against the current file and restore
|
|
13
|
+
#
|
|
14
|
+
# Usage: Add to settings.json as a PreToolUse hook
|
|
15
|
+
#
|
|
16
|
+
# {
|
|
17
|
+
# "hooks": {
|
|
18
|
+
# "PreToolUse": [{
|
|
19
|
+
# "matcher": "",
|
|
20
|
+
# "hooks": [{ "type": "command", "command": "~/.claude/hooks/auto-snapshot.sh" }]
|
|
21
|
+
# }]
|
|
22
|
+
# }
|
|
23
|
+
# }
|
|
24
|
+
|
|
25
|
+
INPUT=$(cat)
|
|
26
|
+
TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
|
|
27
|
+
FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
|
|
28
|
+
|
|
29
|
+
# Only snapshot Edit and Write operations
|
|
30
|
+
if [[ "$TOOL" != "Edit" && "$TOOL" != "Write" ]]; then
|
|
31
|
+
exit 0
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
# Only snapshot existing files (Write to new files has nothing to save)
|
|
35
|
+
if [[ -z "$FILE" || ! -f "$FILE" ]]; then
|
|
36
|
+
exit 0
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
SNAP_DIR="$HOME/.claude/snapshots/$(date +%Y%m%d)"
|
|
40
|
+
mkdir -p "$SNAP_DIR" 2>/dev/null
|
|
41
|
+
|
|
42
|
+
# Use filename + timestamp to avoid collisions
|
|
43
|
+
BASENAME=$(basename "$FILE")
|
|
44
|
+
TIMESTAMP=$(date +%H%M%S)
|
|
45
|
+
cp "$FILE" "$SNAP_DIR/${BASENAME}.${TIMESTAMP}" 2>/dev/null
|
|
46
|
+
|
|
47
|
+
# Keep snapshots manageable — delete files older than 7 days
|
|
48
|
+
find "$HOME/.claude/snapshots" -type f -mtime +7 -delete 2>/dev/null
|
|
49
|
+
find "$HOME/.claude/snapshots" -type d -empty -delete 2>/dev/null
|
|
50
|
+
|
|
51
|
+
exit 0
|
package/index.mjs
CHANGED
|
@@ -261,6 +261,8 @@ function examples() {
|
|
|
261
261
|
'edit-guard.sh': 'Block Edit/Write to protected files (.env, credentials)',
|
|
262
262
|
'enforce-tests.sh': 'Warn when source files change without test files',
|
|
263
263
|
'notify-waiting.sh': 'Desktop notification when Claude waits for input',
|
|
264
|
+
'auto-approve-python.sh': 'Auto-approve pytest, mypy, ruff, black, isort commands',
|
|
265
|
+
'auto-snapshot.sh': 'Auto-save file snapshots before edits (rollback protection)',
|
|
264
266
|
};
|
|
265
267
|
|
|
266
268
|
console.log();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cc-safe-setup",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.2",
|
|
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": {
|