cc-safe-setup 29.6.38 → 29.6.39
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 +2 -2
- package/examples/dotenv-watch.sh +5 -5
- package/examples/file-change-undo-tracker.sh +2 -2
- package/index.mjs +12 -8
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
[](https://www.npmjs.com/package/cc-safe-setup)
|
|
5
5
|
[](https://github.com/yurukusa/cc-safe-setup/actions/workflows/test.yml)
|
|
6
6
|
|
|
7
|
-
**One command to make Claude Code safe for autonomous operation.**
|
|
7
|
+
**One command to make Claude Code safe for autonomous operation.** 650 example hooks · 14,078 tests · 1,000+ installs/day · [日本語](docs/README.ja.md)
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
10
|
npx cc-safe-setup
|
|
@@ -146,7 +146,7 @@ Guards against issues that corrupt sessions or waste tokens silently.
|
|
|
146
146
|
| `--scan [--apply]` | Tech stack detection |
|
|
147
147
|
| `--export / --import` | Team config sharing |
|
|
148
148
|
| `--verify` | Test each hook |
|
|
149
|
-
| `--install-example <name>` | Install from
|
|
149
|
+
| `--install-example <name>` | Install from 650 examples |
|
|
150
150
|
| `--examples [filter]` | Browse examples by keyword |
|
|
151
151
|
| `--full` | All-in-one setup |
|
|
152
152
|
| `--status` | Check installed hooks |
|
package/examples/dotenv-watch.sh
CHANGED
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
# API keys, wrong database URLs, or missing config values.
|
|
11
11
|
#
|
|
12
12
|
# TRIGGER: FileChanged
|
|
13
|
-
# MATCHER: ".env" (watches .env
|
|
13
|
+
# MATCHER: ".env" (watches the .env file in cwd — use ".env|.env.local" for multiple files)
|
|
14
14
|
#
|
|
15
|
-
# INPUT: {"file_path": "/path/to/.env", "event": "
|
|
15
|
+
# INPUT: {"file_path": "/path/to/.env", "event": "change|add|unlink"}
|
|
16
16
|
#
|
|
17
17
|
# DECISION CONTROL: None (notification only — shows stderr to user)
|
|
18
18
|
|
|
@@ -24,17 +24,17 @@ EVENT=$(echo "$INPUT" | jq -r '.event // empty' 2>/dev/null)
|
|
|
24
24
|
FILENAME=$(basename "$FILE_PATH")
|
|
25
25
|
|
|
26
26
|
case "$EVENT" in
|
|
27
|
-
|
|
27
|
+
change)
|
|
28
28
|
echo "⚠ Environment file changed: ${FILENAME}" >&2
|
|
29
29
|
echo " Path: ${FILE_PATH}" >&2
|
|
30
30
|
echo " Action: Verify environment variables are still correct" >&2
|
|
31
31
|
;;
|
|
32
|
-
|
|
32
|
+
add)
|
|
33
33
|
echo "📝 New environment file: ${FILENAME}" >&2
|
|
34
34
|
echo " Path: ${FILE_PATH}" >&2
|
|
35
35
|
echo " Action: Review contents before use" >&2
|
|
36
36
|
;;
|
|
37
|
-
|
|
37
|
+
unlink)
|
|
38
38
|
echo "🗑 Environment file deleted: ${FILENAME}" >&2
|
|
39
39
|
echo " Path: ${FILE_PATH}" >&2
|
|
40
40
|
echo " Action: Check if environment variables are still available" >&2
|
|
@@ -27,13 +27,13 @@ UNDO_FILE="/tmp/claude-undo-session-${PPID:-0}.sh"
|
|
|
27
27
|
TIMESTAMP=$(date +"%H:%M:%S")
|
|
28
28
|
|
|
29
29
|
# Log the change
|
|
30
|
-
echo "${TIMESTAMP} ${EVENT:-
|
|
30
|
+
echo "${TIMESTAMP} ${EVENT:-change} ${FILE}" >> "$LOG_FILE"
|
|
31
31
|
|
|
32
32
|
# Track for undo (git-tracked files only)
|
|
33
33
|
if git ls-files --error-unmatch "$FILE" &>/dev/null 2>&1; then
|
|
34
34
|
# File is git-tracked — can be reverted with git checkout
|
|
35
35
|
if ! grep -qF "git checkout -- \"$FILE\"" "$UNDO_FILE" 2>/dev/null; then
|
|
36
|
-
echo "git checkout -- \"$FILE\" # ${EVENT:-
|
|
36
|
+
echo "git checkout -- \"$FILE\" # ${EVENT:-change} at ${TIMESTAMP}" >> "$UNDO_FILE"
|
|
37
37
|
fi
|
|
38
38
|
fi
|
|
39
39
|
|
package/index.mjs
CHANGED
|
@@ -1112,10 +1112,10 @@ async function installExample(name) {
|
|
|
1112
1112
|
let matcher = 'Bash';
|
|
1113
1113
|
|
|
1114
1114
|
// Detect trigger from header comments (case-insensitive for "Trigger:" prefix)
|
|
1115
|
-
const triggerMatch = content.match(/^#\s*[Tt]
|
|
1115
|
+
const triggerMatch = content.match(/^#\s*[Tt][Rr][Ii][Gg][Gg][Ee][Rr]:\s*(\S+)/m);
|
|
1116
1116
|
if (triggerMatch) {
|
|
1117
1117
|
const t = triggerMatch[1];
|
|
1118
|
-
if (['PermissionRequest','PostToolUse','Notification','Stop','SessionStart','PreCompact','SessionEnd','UserPromptSubmit'].includes(t)) {
|
|
1118
|
+
if (['PermissionRequest','PostToolUse','Notification','Stop','SessionStart','PreCompact','SessionEnd','UserPromptSubmit','CwdChanged','FileChanged'].includes(t)) {
|
|
1119
1119
|
trigger = t;
|
|
1120
1120
|
}
|
|
1121
1121
|
} else if (content.match(/^#.*PermissionRequest hook/m)) {
|
|
@@ -1127,8 +1127,12 @@ async function installExample(name) {
|
|
|
1127
1127
|
// Detect matcher from header (JSON format or comment format)
|
|
1128
1128
|
const matcherMatch = content.match(/"matcher":\s*"([^"]*)"/);
|
|
1129
1129
|
if (matcherMatch) matcher = matcherMatch[1];
|
|
1130
|
-
const commentMatcher = content.match(/^#\s*
|
|
1131
|
-
if (commentMatcher)
|
|
1130
|
+
const commentMatcher = content.match(/^#\s*[Mm][Aa][Tt][Cc][Hh][Ee][Rr]:\s*(.+)$/m);
|
|
1131
|
+
if (commentMatcher) {
|
|
1132
|
+
// Extract quoted value if present (e.g., ".env" or ".env|.env.local"), otherwise use raw
|
|
1133
|
+
const quoted = commentMatcher[1].match(/^"([^"]*)"/);
|
|
1134
|
+
matcher = quoted ? quoted[1] : commentMatcher[1].trim();
|
|
1135
|
+
}
|
|
1132
1136
|
|
|
1133
1137
|
// Update settings.json
|
|
1134
1138
|
let settings = {};
|
|
@@ -1138,10 +1142,10 @@ async function installExample(name) {
|
|
|
1138
1142
|
if (!settings.hooks) settings.hooks = {};
|
|
1139
1143
|
if (!settings.hooks[trigger]) settings.hooks[trigger] = [];
|
|
1140
1144
|
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
hooks: [{ type: 'command', command: toBashPath(destPath) }]
|
|
1144
|
-
|
|
1145
|
+
// CwdChanged does not support matchers; FileChanged uses matcher from header
|
|
1146
|
+
const hookEntry = trigger === 'CwdChanged'
|
|
1147
|
+
? { hooks: [{ type: 'command', command: toBashPath(destPath) }] }
|
|
1148
|
+
: { matcher: matcher, hooks: [{ type: 'command', command: toBashPath(destPath) }] };
|
|
1145
1149
|
|
|
1146
1150
|
// Check if already installed
|
|
1147
1151
|
const existing = settings.hooks[trigger].find(h =>
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cc-safe-setup",
|
|
3
|
-
"version": "29.6.
|
|
4
|
-
"description": "One command to make Claude Code safe.
|
|
3
|
+
"version": "29.6.39",
|
|
4
|
+
"description": "One command to make Claude Code safe. 650 example hooks + 8 built-in. 56 CLI commands. Token consumption diagnosis. Works with Auto Mode.",
|
|
5
5
|
"main": "index.mjs",
|
|
6
6
|
"bin": {
|
|
7
7
|
"cc-safe-setup": "index.mjs"
|