cc-safe-setup 7.6.0 → 7.7.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
@@ -6,7 +6,7 @@
6
6
 
7
7
  **One command to make Claude Code safe for autonomous operation.** [日本語](docs/README.ja.md)
8
8
 
9
- 8 built-in + 71 examples = **79 hooks**. 28 CLI commands. 405 tests. [Web Tool](https://yurukusa.github.io/cc-safe-setup/) · [Hooks Cheat Sheet](https://yurukusa.github.io/cc-safe-setup/hooks-cheatsheet.html) · [Playground](https://yurukusa.github.io/cc-hook-registry/playground.html) · [Troubleshooting](TROUBLESHOOTING.md)
9
+ 8 built-in + 72 examples = **80 hooks**. 28 CLI commands. 409 tests. [Web Tool](https://yurukusa.github.io/cc-safe-setup/) · [Hooks Cheat Sheet](https://yurukusa.github.io/cc-safe-setup/hooks-cheatsheet.html) · [Playground](https://yurukusa.github.io/cc-hook-registry/playground.html) · [Troubleshooting](TROUBLESHOOTING.md)
10
10
 
11
11
  ```bash
12
12
  npx cc-safe-setup
@@ -0,0 +1,49 @@
1
+ #!/bin/bash
2
+ # ================================================================
3
+ # error-memory-guard.sh — Detect repeated failed commands
4
+ # ================================================================
5
+ # PURPOSE:
6
+ # Claude often retries the exact same command that just failed,
7
+ # sometimes 5-10 times before trying a different approach.
8
+ # This hook tracks command+error pairs and blocks retries of
9
+ # commands that have already failed with the same error.
10
+ #
11
+ # TRIGGER: PostToolUse MATCHER: "Bash"
12
+ #
13
+ # Unlike loop-detector (which catches any repetition), this
14
+ # specifically targets the "same command, same error" pattern.
15
+ # ================================================================
16
+
17
+ INPUT=$(cat)
18
+ COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
19
+ [ -z "$COMMAND" ] && exit 0
20
+
21
+ EXIT_CODE=$(echo "$INPUT" | jq -r '.tool_result_exit_code // 0' 2>/dev/null)
22
+ ERROR=$(echo "$INPUT" | jq -r '.tool_result // empty' 2>/dev/null | tail -5)
23
+
24
+ # Only track failures
25
+ [ "$EXIT_CODE" = "0" ] && exit 0
26
+
27
+ STATE="/tmp/cc-error-memory-$(echo "$PWD" | md5sum | cut -c1-8)"
28
+ HASH=$(echo "$COMMAND" | md5sum | cut -c1-16)
29
+
30
+ # Check if this exact command already failed
31
+ if grep -q "^$HASH:" "$STATE" 2>/dev/null; then
32
+ PREV_COUNT=$(grep "^$HASH:" "$STATE" | cut -d: -f2)
33
+ NEW_COUNT=$((PREV_COUNT + 1))
34
+ sed -i "s/^$HASH:.*/$HASH:$NEW_COUNT/" "$STATE"
35
+
36
+ if [ "$NEW_COUNT" -ge 3 ]; then
37
+ echo "BLOCKED: This command has failed $NEW_COUNT times with the same error." >&2
38
+ echo "Try a different approach instead of retrying." >&2
39
+ echo "Command: $(echo "$COMMAND" | head -c 80)" >&2
40
+ echo "Reset: rm $STATE" >&2
41
+ exit 2
42
+ elif [ "$NEW_COUNT" -ge 2 ]; then
43
+ echo "WARNING: Command failed $NEW_COUNT times. Consider a different approach." >&2
44
+ fi
45
+ else
46
+ echo "$HASH:1" >> "$STATE"
47
+ fi
48
+
49
+ exit 0
@@ -0,0 +1,44 @@
1
+ #!/bin/bash
2
+ # ================================================================
3
+ # large-read-guard.sh — Warn before reading large files
4
+ # ================================================================
5
+ # PURPOSE:
6
+ # Claude sometimes cats entire log files, database dumps, or
7
+ # minified bundles into context, wasting tokens and accelerating
8
+ # context exhaustion. This hook warns before reading files larger
9
+ # than a threshold.
10
+ #
11
+ # TRIGGER: PreToolUse MATCHER: "Bash"
12
+ #
13
+ # CONFIG:
14
+ # CC_MAX_READ_KB=100 (warn above 100KB)
15
+ # ================================================================
16
+
17
+ COMMAND=$(cat | jq -r '.tool_input.command // empty' 2>/dev/null)
18
+ [ -z "$COMMAND" ] && exit 0
19
+
20
+ MAX_KB="${CC_MAX_READ_KB:-100}"
21
+
22
+ # Detect file-reading commands
23
+ FILE=""
24
+ if echo "$COMMAND" | grep -qE '^\s*cat\s+'; then
25
+ FILE=$(echo "$COMMAND" | grep -oE 'cat\s+([^ |>]+)' | awk '{print $2}')
26
+ elif echo "$COMMAND" | grep -qE '^\s*less\s+|^\s*more\s+'; then
27
+ FILE=$(echo "$COMMAND" | awk '{print $2}')
28
+ fi
29
+
30
+ [ -z "$FILE" ] && exit 0
31
+ [ ! -f "$FILE" ] && exit 0
32
+
33
+ # Check file size
34
+ SIZE_KB=$(du -k "$FILE" 2>/dev/null | cut -f1)
35
+ [ -z "$SIZE_KB" ] && exit 0
36
+
37
+ if [ "$SIZE_KB" -gt "$MAX_KB" ]; then
38
+ LINES=$(wc -l < "$FILE" 2>/dev/null || echo "?")
39
+ echo "WARNING: $FILE is ${SIZE_KB}KB ($LINES lines)." >&2
40
+ echo "Reading large files wastes context tokens." >&2
41
+ echo "Consider: head -100 $FILE, grep pattern $FILE, or tail -50 $FILE" >&2
42
+ fi
43
+
44
+ exit 0
@@ -0,0 +1,44 @@
1
+ #!/bin/bash
2
+ # ================================================================
3
+ # parallel-edit-guard.sh — Detect concurrent edits to same file
4
+ # ================================================================
5
+ # PURPOSE:
6
+ # When Claude uses subagents (Agent tool), multiple agents can
7
+ # try to edit the same file simultaneously, causing conflicts
8
+ # and lost changes. This hook uses lock files to detect and
9
+ # warn about concurrent edits.
10
+ #
11
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
12
+ # ================================================================
13
+
14
+ INPUT=$(cat)
15
+ FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
16
+ [ -z "$FILE" ] && exit 0
17
+
18
+ # Create a lock directory for tracking
19
+ LOCK_DIR="/tmp/cc-edit-locks"
20
+ mkdir -p "$LOCK_DIR"
21
+
22
+ # Normalize file path for lock name
23
+ LOCK_FILE="$LOCK_DIR/$(echo "$FILE" | md5sum | cut -c1-16).lock"
24
+
25
+ # Check if another process has a lock
26
+ if [ -f "$LOCK_FILE" ]; then
27
+ LOCK_AGE=$(($(date +%s) - $(stat -c %Y "$LOCK_FILE" 2>/dev/null || echo 0)))
28
+ LOCK_PID=$(cat "$LOCK_FILE" 2>/dev/null)
29
+
30
+ # Lock is stale if older than 30 seconds
31
+ if [ "$LOCK_AGE" -lt 30 ] && [ "$LOCK_PID" != "$$" ]; then
32
+ echo "WARNING: File $FILE may be edited by another agent." >&2
33
+ echo "Lock age: ${LOCK_AGE}s, PID: $LOCK_PID" >&2
34
+ echo "Wait for the other edit to complete." >&2
35
+ fi
36
+ fi
37
+
38
+ # Set our lock
39
+ echo "$$" > "$LOCK_FILE"
40
+
41
+ # Clean up lock after 30s in background
42
+ (sleep 30 && rm -f "$LOCK_FILE") &>/dev/null &
43
+
44
+ exit 0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cc-safe-setup",
3
- "version": "7.6.0",
3
+ "version": "7.7.0",
4
4
  "description": "One command to make Claude Code safe. 59 hooks (8 built-in + 51 examples). 26 CLI commands: dashboard, create, audit, lint, diff, migrate, compare, generate-ci. 284 tests.",
5
5
  "main": "index.mjs",
6
6
  "bin": {