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 +3 -0
- package/examples/diff-size-guard.sh +61 -0
- package/examples/session-handoff.sh +106 -0
- package/index.mjs +3 -0
- package/package.json +2 -2
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.
|
|
4
|
-
"description": "One command to make Claude Code safe for autonomous operation. 8 built-in hooks +
|
|
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"
|