cc-safe-setup 7.6.0 → 7.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
@@ -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 + 75 examples = **83 hooks**. 28 CLI commands. 420 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
@@ -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 71 examples |
90
+ | `--install-example <name>` | Install from 75 examples |
91
91
  | `--examples [filter]` | Browse examples by keyword |
92
92
  | `--full` | All-in-one setup |
93
93
  | `--status` | Check installed hooks |
@@ -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
@@ -0,0 +1,33 @@
1
+ #!/bin/bash
2
+ # ================================================================
3
+ # revert-helper.sh — Show revert command when session ends badly
4
+ # ================================================================
5
+ # PURPOSE:
6
+ # When a Claude Code session ends (Stop event), check if there
7
+ # are uncommitted changes and show a one-line revert command.
8
+ # Makes it easy to undo everything Claude did if it went wrong.
9
+ #
10
+ # TRIGGER: Stop MATCHER: ""
11
+ # ================================================================
12
+
13
+ # Check if we're in a git repo
14
+ git rev-parse --git-dir &>/dev/null || exit 0
15
+
16
+ # Check for uncommitted changes
17
+ DIRTY=$(git status --porcelain 2>/dev/null)
18
+ [ -z "$DIRTY" ] && exit 0
19
+
20
+ COUNT=$(echo "$DIRTY" | wc -l)
21
+ LAST_COMMIT=$(git log --oneline -1 2>/dev/null | head -c 50)
22
+
23
+ echo "" >&2
24
+ echo "Session ended with $COUNT uncommitted change(s)." >&2
25
+ echo "Last commit: $LAST_COMMIT" >&2
26
+ echo "" >&2
27
+ echo "To undo all changes:" >&2
28
+ echo " git checkout -- . && git clean -fd" >&2
29
+ echo "" >&2
30
+ echo "To review changes:" >&2
31
+ echo " git diff --stat" >&2
32
+
33
+ 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.8.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": {