cc-safe-setup 3.5.0 → 3.6.1

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
@@ -220,6 +220,9 @@ Or browse all available examples in [`examples/`](examples/):
220
220
  - **verify-before-commit.sh** — Block git commit when lint/test commands haven't been run ([#37818](https://github.com/anthropics/claude-code/issues/37818))
221
221
  - **hook-debug-wrapper.sh** — Wrap any hook to log input/output/exit code/timing to `~/.claude/hook-debug.log`
222
222
  - **loop-detector.sh** — Detect and break command repetition loops (warn at 3, block at 5 repeats)
223
+ - **commit-quality-gate.sh** — Warn on vague commit messages ("update code"), long subjects, mega-commits
224
+ - **session-handoff.sh** — Auto-save git state and session info to `~/.claude/session-handoff.md` on session end
225
+ - **diff-size-guard.sh** — Warn/block when committing too many files at once (default: warn at 10, block at 50)
223
226
 
224
227
  ## Safety Checklist
225
228
 
@@ -0,0 +1,61 @@
1
+ #!/bin/bash
2
+ # ================================================================
3
+ # diff-size-guard.sh — Warn on large uncommitted changes
4
+ # ================================================================
5
+ # PURPOSE:
6
+ # Claude Code can modify dozens of files in a single session
7
+ # without committing. By the time you notice, the diff is
8
+ # unmanageable. This hook warns when the working tree has
9
+ # too many changed files.
10
+ #
11
+ # TRIGGER: PreToolUse
12
+ # MATCHER: "Bash"
13
+ #
14
+ # WHEN IT FIRES:
15
+ # On git commit — checks if the commit is too large
16
+ # Configurable thresholds via environment variables
17
+ #
18
+ # CONFIGURATION:
19
+ # CC_DIFF_WARN=10 — warn when staging 10+ files (default)
20
+ # CC_DIFF_BLOCK=50 — block when staging 50+ files (default)
21
+ # ================================================================
22
+
23
+ INPUT=$(cat)
24
+ COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
25
+
26
+ if [[ -z "$COMMAND" ]]; then
27
+ exit 0
28
+ fi
29
+
30
+ # Only check git commit and git add
31
+ if ! echo "$COMMAND" | grep -qE '^\s*git\s+(commit|add\s+(-A|--all|\.))'; then
32
+ exit 0
33
+ fi
34
+
35
+ # Check number of changed files
36
+ if ! command -v git &>/dev/null || ! [ -d .git ]; then
37
+ exit 0
38
+ fi
39
+
40
+ WARN="${CC_DIFF_WARN:-10}"
41
+ BLOCK="${CC_DIFF_BLOCK:-50}"
42
+
43
+ # Count staged + unstaged changed files
44
+ CHANGED=$(git diff --name-only HEAD 2>/dev/null | wc -l)
45
+ STAGED=$(git diff --cached --name-only 2>/dev/null | wc -l)
46
+ TOTAL=$((CHANGED + STAGED))
47
+
48
+ if [ "$TOTAL" -ge "$BLOCK" ]; then
49
+ echo "BLOCKED: $TOTAL files changed — too large for one commit." >&2
50
+ echo "" >&2
51
+ echo "Break this into smaller, reviewable commits:" >&2
52
+ echo " git add src/feature/ && git commit -m 'feat: add feature'" >&2
53
+ echo " git add tests/ && git commit -m 'test: add feature tests'" >&2
54
+ echo "" >&2
55
+ echo "Set CC_DIFF_BLOCK to adjust the limit (current: $BLOCK)." >&2
56
+ exit 2
57
+ elif [ "$TOTAL" -ge "$WARN" ]; then
58
+ echo "WARNING: $TOTAL files changed. Consider splitting into smaller commits." >&2
59
+ fi
60
+
61
+ exit 0
@@ -0,0 +1,106 @@
1
+ #!/bin/bash
2
+ # ================================================================
3
+ # session-handoff.sh — Auto-save session state for next session
4
+ # ================================================================
5
+ # PURPOSE:
6
+ # When a Claude Code session ends (Stop event), automatically
7
+ # captures the current state and writes a handoff file that the
8
+ # next session can read to resume work.
9
+ #
10
+ # Solves the "I forgot what I was doing" problem after /compact
11
+ # or session restart.
12
+ #
13
+ # TRIGGER: Stop
14
+ # MATCHER: ""
15
+ #
16
+ # WHAT IT CAPTURES:
17
+ # - Current git branch and uncommitted changes
18
+ # - Last 5 commands from shell history
19
+ # - Modified files (git diff --stat)
20
+ # - Current working directory
21
+ # - Timestamp
22
+ #
23
+ # OUTPUT: ~/.claude/session-handoff.md
24
+ # Next session can read this to understand where the last one left off.
25
+ #
26
+ # CONFIGURATION:
27
+ # CC_HANDOFF_FILE — path to handoff file
28
+ # default: ~/.claude/session-handoff.md
29
+ # ================================================================
30
+
31
+ HANDOFF="${CC_HANDOFF_FILE:-$HOME/.claude/session-handoff.md}"
32
+
33
+ # Detect project directory from recent tool calls
34
+ PROJECT_DIR=""
35
+ if [ -d ".git" ]; then
36
+ PROJECT_DIR="$(pwd)"
37
+ elif [ -f "$HOME/.claude/projects" ]; then
38
+ PROJECT_DIR=$(ls -td "$HOME/.claude/projects/"*/ 2>/dev/null | head -1)
39
+ fi
40
+
41
+ {
42
+ echo "# Session Handoff"
43
+ echo ""
44
+ echo "**Last session ended:** $(date -Iseconds)"
45
+ echo ""
46
+
47
+ # Git state
48
+ if command -v git &>/dev/null && [ -d ".git" ]; then
49
+ BRANCH=$(git branch --show-current 2>/dev/null || echo "unknown")
50
+ echo "## Git State"
51
+ echo "- Branch: \`$BRANCH\`"
52
+
53
+ MODIFIED=$(git diff --stat 2>/dev/null | tail -1)
54
+ if [ -n "$MODIFIED" ]; then
55
+ echo "- Changes: $MODIFIED"
56
+ echo ""
57
+ echo "### Modified files"
58
+ echo '```'
59
+ git diff --name-only 2>/dev/null | head -10
60
+ echo '```'
61
+ else
62
+ echo "- Changes: clean working tree"
63
+ fi
64
+
65
+ STAGED=$(git diff --cached --stat 2>/dev/null | tail -1)
66
+ if [ -n "$STAGED" ]; then
67
+ echo "- Staged: $STAGED"
68
+ fi
69
+
70
+ LAST_COMMIT=$(git log --oneline -1 2>/dev/null)
71
+ echo "- Last commit: $LAST_COMMIT"
72
+ echo ""
73
+ fi
74
+
75
+ # Recent blocked commands (if any)
76
+ BLOCK_LOG="$HOME/.claude/blocked-commands.log"
77
+ if [ -f "$BLOCK_LOG" ]; then
78
+ RECENT_BLOCKS=$(tail -3 "$BLOCK_LOG" 2>/dev/null)
79
+ if [ -n "$RECENT_BLOCKS" ]; then
80
+ echo "## Recent Blocks"
81
+ echo '```'
82
+ echo "$RECENT_BLOCKS"
83
+ echo '```'
84
+ echo ""
85
+ fi
86
+ fi
87
+
88
+ # Session errors
89
+ ERROR_LOG="$HOME/.claude/session-errors.log"
90
+ if [ -f "$ERROR_LOG" ]; then
91
+ RECENT_ERRORS=$(tail -3 "$ERROR_LOG" 2>/dev/null)
92
+ if [ -n "$RECENT_ERRORS" ]; then
93
+ echo "## Recent Errors"
94
+ echo '```'
95
+ echo "$RECENT_ERRORS"
96
+ echo '```'
97
+ echo ""
98
+ fi
99
+ fi
100
+
101
+ echo "---"
102
+ echo "*Auto-generated by session-handoff hook. Read this at session start to resume.*"
103
+
104
+ } > "$HANDOFF"
105
+
106
+ exit 0
package/index.mjs CHANGED
@@ -350,6 +350,9 @@ function examples() {
350
350
  'tmp-cleanup.sh': 'Clean up /tmp/claude-*-cwd files on session end',
351
351
  'hook-debug-wrapper.sh': 'Wrap any hook to log input/output/exit/timing',
352
352
  'loop-detector.sh': 'Detect and break command repetition loops',
353
+ 'session-handoff.sh': 'Auto-save session state for next session resume',
354
+ 'commit-quality-gate.sh': 'Warn on vague or too-long commit messages',
355
+ 'diff-size-guard.sh': 'Warn/block on large diffs (10+ files warn, 50+ block)',
353
356
  },
354
357
  };
355
358
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "cc-safe-setup",
3
- "version": "3.5.0",
4
- "description": "One command to make Claude Code safe for autonomous operation. 8 built-in hooks + 33 examples. Create, audit, lint, diff, share, watch, learn. 2,500+ daily npm downloads.",
3
+ "version": "3.6.1",
4
+ "description": "One command to make Claude Code safe for autonomous operation. 8 built-in hooks + 34 examples. Create, audit, lint, diff, share, watch, learn. Session handoff, loop detection, commit quality gate.",
5
5
  "main": "index.mjs",
6
6
  "bin": {
7
7
  "cc-safe-setup": "index.mjs"