cc-safe-setup 8.9.0 → 9.1.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 +1 -1
- package/examples/env-drift-guard.sh +40 -0
- package/examples/package-script-guard.sh +41 -0
- package/index.mjs +48 -17
- package/package.json +1 -1
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 +
|
|
9
|
+
8 built-in + 104 examples = **112 hooks**. 34 CLI commands. 457 tests. 4 languages. [Web Tool](https://yurukusa.github.io/cc-safe-setup/) · [Cheat Sheet](https://yurukusa.github.io/cc-safe-setup/hooks-cheatsheet.html) · [Builder](https://yurukusa.github.io/cc-safe-setup/builder.html) · [FAQ](https://yurukusa.github.io/cc-safe-setup/faq.html) · [Examples](https://yurukusa.github.io/cc-safe-setup/by-example.html) · [Migration](https://yurukusa.github.io/cc-safe-setup/migration-guide.html) · [Playground](https://yurukusa.github.io/cc-hook-registry/playground.html)
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
12
|
npx cc-safe-setup
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ================================================================
|
|
3
|
+
# env-drift-guard.sh — Detect .env vs .env.example drift
|
|
4
|
+
# ================================================================
|
|
5
|
+
# PURPOSE:
|
|
6
|
+
# When Claude edits .env.example (adding new required vars),
|
|
7
|
+
# warn if .env is missing those variables. Prevents deploy
|
|
8
|
+
# failures from missing environment configuration.
|
|
9
|
+
#
|
|
10
|
+
# TRIGGER: PostToolUse MATCHER: "Edit|Write"
|
|
11
|
+
# ================================================================
|
|
12
|
+
|
|
13
|
+
FILE=$(cat | jq -r '.tool_input.file_path // empty' 2>/dev/null)
|
|
14
|
+
[ -z "$FILE" ] && exit 0
|
|
15
|
+
|
|
16
|
+
# Only trigger when .env.example or .env is edited
|
|
17
|
+
case "$FILE" in
|
|
18
|
+
*.env.example|*.env.sample|*.env.template) ;;
|
|
19
|
+
*) exit 0 ;;
|
|
20
|
+
esac
|
|
21
|
+
|
|
22
|
+
# Compare keys in .env.example vs .env
|
|
23
|
+
EXAMPLE="$FILE"
|
|
24
|
+
ENV_FILE="$(dirname "$FILE")/.env"
|
|
25
|
+
[ -f "$EXAMPLE" ] || exit 0
|
|
26
|
+
[ -f "$ENV_FILE" ] || { echo "WARNING: $ENV_FILE does not exist but $EXAMPLE was updated." >&2; exit 0; }
|
|
27
|
+
|
|
28
|
+
# Extract variable names (KEY=... lines, skip comments)
|
|
29
|
+
EXAMPLE_KEYS=$(grep -E '^[A-Z_]+=' "$EXAMPLE" 2>/dev/null | cut -d= -f1 | sort)
|
|
30
|
+
ENV_KEYS=$(grep -E '^[A-Z_]+=' "$ENV_FILE" 2>/dev/null | cut -d= -f1 | sort)
|
|
31
|
+
|
|
32
|
+
MISSING=$(comm -23 <(echo "$EXAMPLE_KEYS") <(echo "$ENV_KEYS"))
|
|
33
|
+
if [ -n "$MISSING" ]; then
|
|
34
|
+
COUNT=$(echo "$MISSING" | wc -l)
|
|
35
|
+
echo "WARNING: $COUNT variable(s) in $EXAMPLE missing from .env:" >&2
|
|
36
|
+
echo "$MISSING" | head -5 | sed 's/^/ /' >&2
|
|
37
|
+
echo "Update .env to match $EXAMPLE." >&2
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
exit 0
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ================================================================
|
|
3
|
+
# package-script-guard.sh — Warn when package.json scripts change
|
|
4
|
+
# ================================================================
|
|
5
|
+
# PURPOSE:
|
|
6
|
+
# package.json scripts are critical infrastructure — they're
|
|
7
|
+
# often wired into CI/CD. Claude sometimes modifies them without
|
|
8
|
+
# understanding the downstream impact. This hook warns on changes.
|
|
9
|
+
#
|
|
10
|
+
# TRIGGER: PreToolUse MATCHER: "Edit"
|
|
11
|
+
# ================================================================
|
|
12
|
+
|
|
13
|
+
INPUT=$(cat)
|
|
14
|
+
FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
|
|
15
|
+
[ -z "$FILE" ] && exit 0
|
|
16
|
+
|
|
17
|
+
# Only check package.json
|
|
18
|
+
case "$FILE" in
|
|
19
|
+
*/package.json|package.json) ;;
|
|
20
|
+
*) exit 0 ;;
|
|
21
|
+
esac
|
|
22
|
+
|
|
23
|
+
OLD=$(echo "$INPUT" | jq -r '.tool_input.old_string // empty' 2>/dev/null)
|
|
24
|
+
NEW=$(echo "$INPUT" | jq -r '.tool_input.new_string // empty' 2>/dev/null)
|
|
25
|
+
[ -z "$OLD" ] && exit 0
|
|
26
|
+
|
|
27
|
+
# Check if scripts section is being modified
|
|
28
|
+
if echo "$OLD" | grep -q '"scripts"' || echo "$NEW" | grep -q '"scripts"'; then
|
|
29
|
+
echo "NOTE: Modifying package.json scripts section." >&2
|
|
30
|
+
echo "These are often wired into CI/CD pipelines." >&2
|
|
31
|
+
echo "Verify: npm test, npm run build still work after this change." >&2
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
# Check if dependencies are being modified
|
|
35
|
+
if echo "$OLD" | grep -qE '"(dependencies|devDependencies|peerDependencies)"' || \
|
|
36
|
+
echo "$NEW" | grep -qE '"(dependencies|devDependencies|peerDependencies)"'; then
|
|
37
|
+
echo "NOTE: Modifying package.json dependencies." >&2
|
|
38
|
+
echo "Run npm install after this change." >&2
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
exit 0
|
package/index.mjs
CHANGED
|
@@ -1866,7 +1866,7 @@ function generateCI() {
|
|
|
1866
1866
|
|
|
1867
1867
|
const workflow = `# Claude Code Safety Audit
|
|
1868
1868
|
# Generated by: npx cc-safe-setup --generate-ci
|
|
1869
|
-
#
|
|
1869
|
+
# Runs safety checks on every PR and push to main
|
|
1870
1870
|
|
|
1871
1871
|
name: Claude Code Safety
|
|
1872
1872
|
on:
|
|
@@ -1880,24 +1880,55 @@ jobs:
|
|
|
1880
1880
|
steps:
|
|
1881
1881
|
- uses: actions/checkout@v4
|
|
1882
1882
|
|
|
1883
|
-
- name:
|
|
1884
|
-
uses:
|
|
1883
|
+
- name: Setup Node.js
|
|
1884
|
+
uses: actions/setup-node@v4
|
|
1885
1885
|
with:
|
|
1886
|
-
|
|
1886
|
+
node-version: 20
|
|
1887
1887
|
|
|
1888
|
-
- name:
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1888
|
+
- name: Install jq
|
|
1889
|
+
run: sudo apt-get install -y jq
|
|
1890
|
+
|
|
1891
|
+
- name: Run safety audit
|
|
1892
|
+
id: audit
|
|
1893
|
+
run: |
|
|
1894
|
+
npx cc-safe-setup --audit --json > /tmp/audit.json 2>&1 || true
|
|
1895
|
+
SCORE=\$(cat /tmp/audit.json | jq -r '.score // 0' 2>/dev/null || echo 0)
|
|
1896
|
+
echo "score=\$SCORE" >> \$GITHUB_OUTPUT
|
|
1897
|
+
echo "Safety score: \$SCORE/100"
|
|
1898
|
+
if [ "\$SCORE" -lt 70 ]; then
|
|
1899
|
+
echo "::error::Safety score \$SCORE is below threshold (70)"
|
|
1900
|
+
exit 1
|
|
1901
|
+
fi
|
|
1902
|
+
|
|
1903
|
+
- name: Verify hooks syntax
|
|
1904
|
+
run: |
|
|
1905
|
+
ERRORS=0
|
|
1906
|
+
for f in .claude/hooks/*.sh 2>/dev/null; do
|
|
1907
|
+
[ -f "\$f" ] || continue
|
|
1908
|
+
if ! bash -n "\$f" 2>/dev/null; then
|
|
1909
|
+
echo "::error file=\$f::Syntax error in hook"
|
|
1910
|
+
ERRORS=\$((ERRORS+1))
|
|
1911
|
+
fi
|
|
1912
|
+
done
|
|
1913
|
+
echo "Checked hooks: \$ERRORS error(s)"
|
|
1914
|
+
[ "\$ERRORS" -gt 0 ] && exit 1 || true
|
|
1915
|
+
|
|
1916
|
+
- name: Check settings.json validity
|
|
1917
|
+
run: |
|
|
1918
|
+
if [ -f ".claude/settings.json" ]; then
|
|
1919
|
+
python3 -c "import json; json.load(open('.claude/settings.json'))" || {
|
|
1920
|
+
echo "::error::.claude/settings.json has invalid JSON"
|
|
1921
|
+
exit 1
|
|
1922
|
+
}
|
|
1923
|
+
echo "settings.json: valid"
|
|
1924
|
+
fi
|
|
1925
|
+
if [ -f ".claude/settings.local.json" ]; then
|
|
1926
|
+
python3 -c "import json; json.load(open('.claude/settings.local.json'))" || {
|
|
1927
|
+
echo "::error::.claude/settings.local.json has invalid JSON"
|
|
1928
|
+
exit 1
|
|
1929
|
+
}
|
|
1930
|
+
echo "settings.local.json: valid"
|
|
1931
|
+
fi
|
|
1901
1932
|
`;
|
|
1902
1933
|
|
|
1903
1934
|
console.log();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cc-safe-setup",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "9.1.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": {
|