cc-safe-setup 8.8.0 → 8.9.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 + 100 examples = **108 hooks**. 33 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)
9
+ 8 built-in + 102 examples = **110 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,317 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Claude Code settings.json Complete Reference</title>
7
+ <meta name="description" content="Every settings.json field explained with examples. Hooks, permissions, env vars — the definitive reference.">
8
+ <style>
9
+ *{box-sizing:border-box;margin:0;padding:0}
10
+ body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;background:#0d1117;color:#c9d1d9;padding:1.5rem;line-height:1.6}
11
+ .c{max-width:820px;margin:0 auto}
12
+ h1{color:#f0f6fc;font-size:1.4rem;margin-bottom:.3rem}
13
+ h2{color:#f0f6fc;font-size:1.05rem;margin:1.3rem 0 .4rem;padding-bottom:.3rem;border-bottom:1px solid #21262d}
14
+ h3{color:#c9d1d9;font-size:.88rem;margin:.7rem 0 .2rem}
15
+ .sub{color:#8b949e;font-size:.83rem;margin-bottom:1rem}
16
+ a{color:#58a6ff;text-decoration:none}
17
+ code{background:#161b22;padding:.12rem .25rem;border-radius:3px;font-size:.82rem}
18
+ pre{background:#161b22;border:1px solid #30363d;border-radius:6px;padding:.6rem;font-size:.78rem;color:#e6edf3;overflow-x:auto;margin:.3rem 0;position:relative}
19
+ .copy{position:absolute;top:.3rem;right:.3rem;background:#21262d;border:1px solid #30363d;color:#8b949e;padding:.15rem .4rem;border-radius:3px;cursor:pointer;font-size:.65rem}
20
+ .copy:hover{color:#f0f6fc}
21
+ table{width:100%;border-collapse:collapse;margin:.4rem 0;font-size:.8rem}
22
+ th,td{padding:.35rem .5rem;border:1px solid #21262d;text-align:left}
23
+ th{background:#161b22;color:#f0f6fc}
24
+ .note{background:#161b22;border-left:3px solid #58a6ff;padding:.4rem .7rem;margin:.4rem 0;font-size:.8rem;color:#8b949e}
25
+ .warn{border-left-color:#d29922}
26
+ .field{background:#161b22;border:1px solid #30363d;border-radius:6px;padding:.6rem;margin:.4rem 0}
27
+ .field-name{font-weight:700;color:#f0f6fc;font-family:monospace;font-size:.85rem}
28
+ .field-type{color:#d29922;font-size:.7rem;margin-left:.4rem}
29
+ .field-desc{color:#8b949e;font-size:.8rem;margin:.2rem 0}
30
+ .footer{text-align:center;color:#484f58;font-size:.7rem;margin-top:2rem;padding-top:1rem;border-top:1px solid #21262d}
31
+ .toc{columns:2;font-size:.8rem;margin:.5rem 0}
32
+ .toc a{display:block;padding:.15rem 0}
33
+ </style>
34
+ </head>
35
+ <body>
36
+ <div class="c">
37
+
38
+ <h1>settings.json Reference</h1>
39
+ <p class="sub">Every field, every option, with practical examples. <a href="https://docs.anthropic.com/en/docs/claude-code/settings">Official docs</a></p>
40
+
41
+ <div class="toc">
42
+ <a href="#locations">File Locations</a>
43
+ <a href="#hooks">hooks</a>
44
+ <a href="#permissions">permissions</a>
45
+ <a href="#env">env</a>
46
+ <a href="#model">model</a>
47
+ <a href="#projects">projects</a>
48
+ <a href="#examples">Full Examples</a>
49
+ </div>
50
+
51
+ <h2 id="locations">File Locations</h2>
52
+
53
+ <table>
54
+ <tr><th>File</th><th>Scope</th><th>Priority</th></tr>
55
+ <tr><td><code>~/.claude/settings.json</code></td><td>Global (all projects)</td><td>Lowest</td></tr>
56
+ <tr><td><code>.claude/settings.json</code></td><td>Project (in repo)</td><td>Medium</td></tr>
57
+ <tr><td><code>.claude/settings.local.json</code></td><td>Project local (gitignored)</td><td>Highest</td></tr>
58
+ </table>
59
+
60
+ <div class="note">
61
+ Project settings merge with global. Higher priority files override lower ones for the same key. For hooks, they are <strong>combined</strong>, not replaced.
62
+ </div>
63
+
64
+ <h2 id="hooks">hooks</h2>
65
+
66
+ <div class="field">
67
+ <span class="field-name">hooks</span> <span class="field-type">object</span>
68
+ <div class="field-desc">Shell scripts that run at lifecycle points. The core of safety configuration.</div>
69
+ </div>
70
+
71
+ <h3>Structure</h3>
72
+ <pre><code>{
73
+ "hooks": {
74
+ "EVENT": [
75
+ {
76
+ "matcher": "REGEX",
77
+ "hooks": [
78
+ {
79
+ "type": "command",
80
+ "command": "bash path/to/hook.sh"
81
+ }
82
+ ]
83
+ }
84
+ ]
85
+ }
86
+ }</code><button class="copy" onclick="cp(this)">Copy</button></pre>
87
+
88
+ <h3>Events</h3>
89
+ <table>
90
+ <tr><th>Event</th><th>When</th><th>stdin JSON</th></tr>
91
+ <tr><td><code>PreToolUse</code></td><td>Before tool executes</td><td><code>tool_name</code>, <code>tool_input</code></td></tr>
92
+ <tr><td><code>PostToolUse</code></td><td>After tool completes</td><td><code>tool_name</code>, <code>tool_input</code>, <code>tool_result</code></td></tr>
93
+ <tr><td><code>Stop</code></td><td>Claude finishes responding</td><td><code>stop_reason</code></td></tr>
94
+ <tr><td><code>SubagentStop</code></td><td>Subagent finishes</td><td>Subagent context</td></tr>
95
+ <tr><td><code>UserPromptSubmit</code></td><td>User sends a message</td><td>Prompt content</td></tr>
96
+ </table>
97
+
98
+ <h3>Matcher</h3>
99
+ <table>
100
+ <tr><th>Value</th><th>Matches</th></tr>
101
+ <tr><td><code>""</code></td><td>All tools</td></tr>
102
+ <tr><td><code>"Bash"</code></td><td>Shell commands only</td></tr>
103
+ <tr><td><code>"Edit"</code></td><td>File edits only</td></tr>
104
+ <tr><td><code>"Write"</code></td><td>File writes only</td></tr>
105
+ <tr><td><code>"Read"</code></td><td>File reads only</td></tr>
106
+ <tr><td><code>"Edit|Write"</code></td><td>Any file modification</td></tr>
107
+ <tr><td><code>"Bash|Edit|Write"</code></td><td>Multiple tools (regex OR)</td></tr>
108
+ </table>
109
+
110
+ <h3>Exit Codes</h3>
111
+ <table>
112
+ <tr><th>Code</th><th>Effect</th></tr>
113
+ <tr><td><code>0</code></td><td>Allow (default)</td></tr>
114
+ <tr><td><code>2</code></td><td>Block the action</td></tr>
115
+ <tr><td><code>1</code></td><td>Hook error (ignored, action proceeds)</td></tr>
116
+ </table>
117
+
118
+ <h3>stdout Override</h3>
119
+ <pre><code>// Auto-approve
120
+ echo '{"decision":"approve","reason":"Safe command"}'
121
+
122
+ // Block with reason
123
+ echo '{"decision":"block","reason":"Too dangerous"}'</code></pre>
124
+
125
+ <h3>Practical Example</h3>
126
+ <pre><code>{
127
+ "hooks": {
128
+ "PreToolUse": [
129
+ {
130
+ "matcher": "Bash",
131
+ "hooks": [
132
+ {"type": "command", "command": "bash ~/.claude/hooks/destructive-guard.sh"},
133
+ {"type": "command", "command": "bash ~/.claude/hooks/branch-guard.sh"},
134
+ {"type": "command", "command": "bash ~/.claude/hooks/secret-guard.sh"}
135
+ ]
136
+ },
137
+ {
138
+ "matcher": "Edit|Write",
139
+ "hooks": [
140
+ {"type": "command", "command": "bash ~/.claude/hooks/scope-guard.sh"}
141
+ ]
142
+ }
143
+ ],
144
+ "PostToolUse": [
145
+ {
146
+ "matcher": "Edit|Write",
147
+ "hooks": [
148
+ {"type": "command", "command": "bash ~/.claude/hooks/syntax-check.sh"}
149
+ ]
150
+ },
151
+ {
152
+ "matcher": "",
153
+ "hooks": [
154
+ {"type": "command", "command": "bash ~/.claude/hooks/context-monitor.sh"}
155
+ ]
156
+ }
157
+ ],
158
+ "Stop": [
159
+ {
160
+ "matcher": "",
161
+ "hooks": [
162
+ {"type": "command", "command": "bash ~/.claude/hooks/api-error-alert.sh"}
163
+ ]
164
+ }
165
+ ]
166
+ }
167
+ }</code><button class="copy" onclick="cp(this)">Copy</button></pre>
168
+
169
+ <h2 id="permissions">permissions</h2>
170
+
171
+ <div class="field">
172
+ <span class="field-name">permissions</span> <span class="field-type">object</span>
173
+ <div class="field-desc">Allow/deny rules for tool usage without prompting.</div>
174
+ </div>
175
+
176
+ <pre><code>{
177
+ "permissions": {
178
+ "allow": [
179
+ "Bash(npm test)",
180
+ "Bash(git status)",
181
+ "Bash(git log *)",
182
+ "Read(*)",
183
+ "Bash(ls *)"
184
+ ],
185
+ "deny": [
186
+ "Bash(rm -rf *)",
187
+ "Bash(sudo *)",
188
+ "Bash(git push * --force)"
189
+ ]
190
+ }
191
+ }</code><button class="copy" onclick="cp(this)">Copy</button></pre>
192
+
193
+ <div class="note warn">
194
+ <strong>Gotcha:</strong> Permissions use glob patterns, not regex. <code>*</code> matches anything. Claude adds flags like <code>-C /path</code> that can break exact matches — use hooks for reliable blocking.
195
+ </div>
196
+
197
+ <h2 id="env">env</h2>
198
+
199
+ <div class="field">
200
+ <span class="field-name">env</span> <span class="field-type">object</span>
201
+ <div class="field-desc">Environment variables passed to Claude Code and hooks.</div>
202
+ </div>
203
+
204
+ <pre><code>{
205
+ "env": {
206
+ "CC_TOKEN_BUDGET": "20",
207
+ "CC_MAX_LINE_LENGTH": "120",
208
+ "CC_DISK_WARN_PCT": "90",
209
+ "CC_ALLOWLIST_FILE": "~/.claude/allowlist.txt"
210
+ }
211
+ }</code><button class="copy" onclick="cp(this)">Copy</button></pre>
212
+
213
+ <h2 id="model">model</h2>
214
+
215
+ <div class="field">
216
+ <span class="field-name">model</span> <span class="field-type">string</span>
217
+ <div class="field-desc">Default model for Claude Code sessions.</div>
218
+ </div>
219
+
220
+ <pre><code>{
221
+ "model": "claude-sonnet-4-6"
222
+ }</code></pre>
223
+
224
+ <table>
225
+ <tr><th>Model</th><th>Best for</th></tr>
226
+ <tr><td><code>claude-opus-4-6</code></td><td>Complex reasoning, architecture</td></tr>
227
+ <tr><td><code>claude-sonnet-4-6</code></td><td>Fast daily coding (default)</td></tr>
228
+ <tr><td><code>claude-haiku-4-5</code></td><td>Quick tasks, high volume</td></tr>
229
+ </table>
230
+
231
+ <h2 id="projects">Project-Level Settings</h2>
232
+
233
+ <pre><code>// .claude/settings.json (commit to repo)
234
+ {
235
+ "hooks": {
236
+ "PreToolUse": [{
237
+ "matcher": "Bash",
238
+ "hooks": [{
239
+ "type": "command",
240
+ "command": "bash .claude/hooks/guard.sh"
241
+ }]
242
+ }]
243
+ }
244
+ }
245
+
246
+ // .claude/settings.local.json (gitignored, personal)
247
+ {
248
+ "permissions": {
249
+ "allow": ["Bash(npm test)"]
250
+ }
251
+ }</code><button class="copy" onclick="cp(this)">Copy</button></pre>
252
+
253
+ <div class="note">
254
+ Use relative paths in project settings (<code>.claude/hooks/guard.sh</code>) so they work for all team members. Use <code>npx cc-safe-setup --team</code> to set this up automatically.
255
+ </div>
256
+
257
+ <h2 id="examples">Full Working Examples</h2>
258
+
259
+ <h3>Minimal Safe Setup</h3>
260
+ <pre><code>{
261
+ "hooks": {
262
+ "PreToolUse": [{
263
+ "matcher": "Bash",
264
+ "hooks": [
265
+ {"type": "command", "command": "bash ~/.claude/hooks/destructive-guard.sh"},
266
+ {"type": "command", "command": "bash ~/.claude/hooks/branch-guard.sh"},
267
+ {"type": "command", "command": "bash ~/.claude/hooks/secret-guard.sh"}
268
+ ]
269
+ }]
270
+ }
271
+ }</code><button class="copy" onclick="cp(this)">Copy</button></pre>
272
+
273
+ <h3>Node.js Project</h3>
274
+ <pre><code>{
275
+ "hooks": {
276
+ "PreToolUse": [
277
+ {"matcher": "Bash", "hooks": [
278
+ {"type": "command", "command": "bash ~/.claude/hooks/destructive-guard.sh"},
279
+ {"type": "command", "command": "bash ~/.claude/hooks/branch-guard.sh"},
280
+ {"type": "command", "command": "bash ~/.claude/hooks/secret-guard.sh"},
281
+ {"type": "command", "command": "bash ~/.claude/hooks/auto-approve-build.sh"}
282
+ ]},
283
+ {"matcher": "Edit|Write", "hooks": [
284
+ {"type": "command", "command": "bash ~/.claude/hooks/syntax-check.sh"}
285
+ ]}
286
+ ]
287
+ },
288
+ "permissions": {
289
+ "allow": ["Bash(npm test)", "Bash(npm run lint)", "Read(*)"]
290
+ }
291
+ }</code><button class="copy" onclick="cp(this)">Copy</button></pre>
292
+
293
+ <h3>Maximum Safety (Autonomous)</h3>
294
+ <pre><code>// Generated by: npx cc-safe-setup --profile strict
295
+ // 33 hooks for autonomous/production use
296
+ // Run: npx cc-safe-setup --shield</code></pre>
297
+
298
+ <div class="footer">
299
+ <a href="hooks-cheatsheet.html">Cheat Sheet</a> ·
300
+ <a href="builder.html">Builder</a> ·
301
+ <a href="faq.html">FAQ</a> ·
302
+ <a href="by-example.html">Examples</a> ·
303
+ <a href="migration-guide.html">Migration</a> ·
304
+ <a href="https://github.com/yurukusa/cc-safe-setup">GitHub</a>
305
+ </div>
306
+ </div>
307
+
308
+ <script>
309
+ function cp(btn) {
310
+ const code = btn.parentElement.querySelector('code').textContent;
311
+ navigator.clipboard.writeText(code);
312
+ btn.textContent = 'Copied!';
313
+ setTimeout(() => btn.textContent = 'Copy', 1500);
314
+ }
315
+ </script>
316
+ </body>
317
+ </html>
@@ -0,0 +1,35 @@
1
+ #!/bin/bash
2
+ # ================================================================
3
+ # git-blame-context.sh — Show file ownership before major edits
4
+ # ================================================================
5
+ # PURPOSE:
6
+ # Before Claude rewrites a file, show who wrote most of it.
7
+ # Helps prevent accidentally breaking code you don't understand
8
+ # the history of. Especially useful in team repositories.
9
+ #
10
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
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
+ [ ! -f "$FILE" ] && exit 0
17
+
18
+ # Only warn on substantial edits (old_string > 10 lines)
19
+ OLD=$(echo "$INPUT" | jq -r '.tool_input.old_string // empty' 2>/dev/null)
20
+ [ -z "$OLD" ] && exit 0
21
+ OLD_LINES=$(echo "$OLD" | wc -l)
22
+ [ "$OLD_LINES" -lt 10 ] && exit 0
23
+
24
+ # Get top contributors for this file
25
+ CONTRIBUTORS=$(git log --format='%an' -- "$FILE" 2>/dev/null | sort | uniq -c | sort -rn | head -3)
26
+ if [ -n "$CONTRIBUTORS" ]; then
27
+ TOTAL_COMMITS=$(git log --oneline -- "$FILE" 2>/dev/null | wc -l)
28
+ LAST_AUTHOR=$(git log -1 --format='%an' -- "$FILE" 2>/dev/null)
29
+ echo "NOTE: Editing $OLD_LINES+ lines in $FILE" >&2
30
+ echo " Last edited by: $LAST_AUTHOR" >&2
31
+ echo " Top contributors ($TOTAL_COMMITS commits):" >&2
32
+ echo "$CONTRIBUTORS" | head -3 | sed 's/^/ /' >&2
33
+ fi
34
+
35
+ exit 0
@@ -0,0 +1,48 @@
1
+ #!/bin/bash
2
+ # ================================================================
3
+ # import-cycle-warn.sh — Detect potential circular imports
4
+ # ================================================================
5
+ # PURPOSE:
6
+ # Claude adds imports without considering dependency cycles.
7
+ # After an edit that adds an import/require, check if the
8
+ # target file imports back from the edited file.
9
+ #
10
+ # TRIGGER: PostToolUse 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
+ NEW=$(echo "$INPUT" | jq -r '.tool_input.new_string // empty' 2>/dev/null)
18
+ [ -z "$NEW" ] && exit 0
19
+
20
+ # Extract newly added imports
21
+ BASENAME=$(basename "$FILE" | sed 's/\.[^.]*$//')
22
+
23
+ # JS/TS: import ... from './target' or require('./target')
24
+ IMPORTS=$(echo "$NEW" | grep -oE "(from\s+['\"]\.\/[^'\"]+|require\(['\"]\.\/[^'\"]+)" | grep -oE '\./[^"'"'"']+' | sed 's/^\.\///')
25
+
26
+ # Python: from .target import or import target
27
+ if [ -z "$IMPORTS" ]; then
28
+ IMPORTS=$(echo "$NEW" | grep -oE "from\s+\.\w+" | awk '{print $2}' | sed 's/^\.//')
29
+ fi
30
+
31
+ [ -z "$IMPORTS" ] && exit 0
32
+
33
+ DIR=$(dirname "$FILE")
34
+ for imp in $IMPORTS; do
35
+ # Check if target imports back
36
+ for ext in .js .ts .jsx .tsx .py .mjs; do
37
+ TARGET="$DIR/$imp$ext"
38
+ [ -f "$TARGET" ] || continue
39
+ if grep -qE "(from\s+['\"].*${BASENAME}|import\s+.*${BASENAME}|require.*${BASENAME})" "$TARGET" 2>/dev/null; then
40
+ echo "WARNING: Potential circular import detected." >&2
41
+ echo " $FILE imports $imp" >&2
42
+ echo " $TARGET imports back from $BASENAME" >&2
43
+ break
44
+ fi
45
+ done
46
+ done
47
+
48
+ exit 0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cc-safe-setup",
3
- "version": "8.8.0",
3
+ "version": "8.9.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": {