cc-safe-setup 11.7.0 → 11.8.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.
@@ -1,317 +0,0 @@
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>
@@ -1,189 +0,0 @@
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 Troubleshooting — Fix Any Problem in 2 Minutes</title>
7
- <meta name="description" content="Hook not firing? Claude ignoring rules? Permission prompt spam? Fix every common Claude Code problem.">
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:800px;margin:0 auto}
12
- h1{color:#f0f6fc;font-size:1.4rem;margin-bottom:.3rem}
13
- h2{color:#f0f6fc;font-size:1rem;margin:1.2rem 0 .4rem}
14
- .sub{color:#8b949e;font-size:.83rem;margin-bottom:1rem}
15
- a{color:#58a6ff;text-decoration:none}
16
- code{background:#161b22;padding:.12rem .25rem;border-radius:3px;font-size:.82rem}
17
- pre{background:#161b22;border:1px solid #30363d;border-radius:6px;padding:.5rem;font-size:.78rem;color:#e6edf3;overflow-x:auto;margin:.3rem 0}
18
- .problem{background:#161b22;border:1px solid #30363d;border-radius:8px;margin:.6rem 0;overflow:hidden}
19
- .problem-header{padding:.6rem .8rem;cursor:pointer;font-weight:600;color:#f0f6fc;font-size:.88rem;display:flex;align-items:center;gap:.5rem}
20
- .problem-header:hover{background:#21262d}
21
- .problem-icon{font-size:1rem}
22
- .problem-body{padding:0 .8rem .6rem;font-size:.82rem;display:none}
23
- .problem.open .problem-body{display:block}
24
- .step{background:#0d1117;border-radius:4px;padding:.4rem .6rem;margin:.3rem 0;border-left:3px solid #30363d}
25
- .step-yes{border-left-color:#238636}
26
- .step-no{border-left-color:#da3633}
27
- .step-fix{border-left-color:#58a6ff}
28
- .footer{text-align:center;color:#484f58;font-size:.7rem;margin-top:2rem;padding-top:1rem;border-top:1px solid #21262d}
29
- .quick{background:#161b22;border:1px solid #30363d;border-radius:6px;padding:.6rem;margin:.5rem 0;font-size:.82rem}
30
- </style>
31
- </head>
32
- <body>
33
- <div class="c">
34
-
35
- <h1>Troubleshooting</h1>
36
- <p class="sub">Click your problem. Follow the steps. Fixed in 2 minutes.</p>
37
-
38
- <div class="quick">
39
- <strong>Quick fix for most problems:</strong> <code>npx cc-safe-setup --quickfix</code>
40
- </div>
41
-
42
- <div class="problem" onclick="this.classList.toggle('open')">
43
- <div class="problem-header"><span class="problem-icon">🔇</span> My hook doesn't fire</div>
44
- <div class="problem-body">
45
- <div class="step">1. Is the hook file executable? <code>ls -la ~/.claude/hooks/your-hook.sh</code></div>
46
- <div class="step-fix">Fix: <code>chmod +x ~/.claude/hooks/your-hook.sh</code></div>
47
-
48
- <div class="step">2. Does it have a shebang? First line must be <code>#!/bin/bash</code></div>
49
- <div class="step-fix">Fix: Add <code>#!/bin/bash</code> as the very first line</div>
50
-
51
- <div class="step">3. Is it registered in settings.json?</div>
52
- <pre>cat ~/.claude/settings.json | python3 -m json.tool | grep your-hook</pre>
53
- <div class="step-fix">Fix: <code>npx cc-safe-setup --shield</code> (auto-registers all hooks)</div>
54
-
55
- <div class="step">4. Is the matcher correct? <code>"Bash"</code> won't fire for Edit/Write</div>
56
- <div class="step-fix">Use <code>""</code> (empty) to match all tools, or <code>"Edit|Write"</code> for file ops</div>
57
-
58
- <div class="step">5. Is jq installed? <code>which jq</code></div>
59
- <div class="step-fix">Install: <code>brew install jq</code> (macOS) or <code>sudo apt install jq</code> (Linux)</div>
60
-
61
- <div class="step">6. Test it manually:</div>
62
- <pre>echo '{"tool_input":{"command":"rm -rf /"}}' | bash ~/.claude/hooks/your-hook.sh; echo "Exit: $?"</pre>
63
- </div>
64
- </div>
65
-
66
- <div class="problem" onclick="this.classList.toggle('open')">
67
- <div class="problem-header"><span class="problem-icon">🚫</span> My hook blocks everything</div>
68
- <div class="problem-body">
69
- <div class="step">Your regex pattern is too broad. Test with a safe command:</div>
70
- <pre>echo '{"tool_input":{"command":"ls -la"}}' | bash ~/.claude/hooks/your-hook.sh; echo "Exit: $?"</pre>
71
- <div class="step">If it exits 2 for <code>ls</code>, your grep pattern matches too much.</div>
72
- <div class="step-fix">Check the <code>grep -qE</code> pattern in your hook. Add <code>\b</code> word boundaries.</div>
73
- <div class="step-fix">Example: <code>grep -qE '\brm\s+.*-rf\s+/'</code> instead of <code>grep -q 'rm'</code></div>
74
- </div>
75
- </div>
76
-
77
- <div class="problem" onclick="this.classList.toggle('open')">
78
- <div class="problem-header"><span class="problem-icon">📋</span> Claude ignores CLAUDE.md rules</div>
79
- <div class="problem-body">
80
- <div class="step">This is normal — CLAUDE.md rules degrade as context fills up.</div>
81
- <div class="step-fix"><strong>Solution: Convert critical rules to hooks.</strong></div>
82
- <pre># Example: "Don't push to main" as a hook instead of a rule
83
- npx cc-safe-setup # Installs branch-guard</pre>
84
- <div class="step">For any rule that must be enforced 100%, create a hook:</div>
85
- <pre>npx cc-safe-setup --create "your rule in plain English"</pre>
86
- <div class="step-fix">CLAUDE.md is for guidelines. Hooks are for hard constraints. Use both.</div>
87
- </div>
88
- </div>
89
-
90
- <div class="problem" onclick="this.classList.toggle('open')">
91
- <div class="problem-header"><span class="problem-icon">🔔</span> Too many permission prompts</div>
92
- <div class="problem-body">
93
- <div class="step">Install auto-approve hooks for safe commands:</div>
94
- <pre>npx cc-safe-setup --install-example auto-approve-build # npm test, cargo build
95
- npx cc-safe-setup --install-example auto-approve-python # pytest, mypy
96
- npx cc-safe-setup --install-example auto-approve-git-read # git status, git log
97
- npx cc-safe-setup --install-example compound-command-approver # cd && git log</pre>
98
- <div class="step">Or add permissions in settings.json:</div>
99
- <pre>"permissions": {"allow": ["Bash(npm test)", "Bash(git status)", "Read(*)"]}</pre>
100
- <div class="step-fix">The <code>--profile standard</code> includes auto-approve hooks for common commands.</div>
101
- </div>
102
- </div>
103
-
104
- <div class="problem" onclick="this.classList.toggle('open')">
105
- <div class="problem-header"><span class="problem-icon">💾</span> settings.json won't parse</div>
106
- <div class="problem-body">
107
- <div class="step">Validate:</div>
108
- <pre>python3 -c "import json; json.load(open('$HOME/.claude/settings.json'))"</pre>
109
- <div class="step-fix">Common causes: trailing commas, comments (JSON doesn't allow them), unescaped quotes</div>
110
- <div class="step">Auto-fix:</div>
111
- <pre>npx cc-safe-setup --quickfix</pre>
112
- <div class="step-fix">If totally broken: <code>echo '{}' > ~/.claude/settings.json</code> then re-run setup</div>
113
- </div>
114
- </div>
115
-
116
- <div class="problem" onclick="this.classList.toggle('open')">
117
- <div class="problem-header"><span class="problem-icon">🔄</span> Claude keeps retrying the same failed command</div>
118
- <div class="problem-body">
119
- <div class="step">Install the error memory guard:</div>
120
- <pre>npx cc-safe-setup --install-example error-memory-guard</pre>
121
- <div class="step-fix">After 3 failures of the same command, it blocks and says "try a different approach".</div>
122
- <div class="step">Also useful: loop detector</div>
123
- <pre>npx cc-safe-setup --install-example loop-detector</pre>
124
- </div>
125
- </div>
126
-
127
- <div class="problem" onclick="this.classList.toggle('open')">
128
- <div class="problem-header"><span class="problem-icon">💸</span> Session costs too much</div>
129
- <div class="problem-body">
130
- <div class="step">Install token budget guard:</div>
131
- <pre>npx cc-safe-setup --install-example token-budget-guard</pre>
132
- <div class="step-fix">Warns at $10, blocks at $50 (configurable via <code>CC_TOKEN_BUDGET</code> and <code>CC_TOKEN_BLOCK</code>)</div>
133
- <div class="step">Monitor with:</div>
134
- <pre>npx cc-safe-setup --analyze</pre>
135
- </div>
136
- </div>
137
-
138
- <div class="problem" onclick="this.classList.toggle('open')">
139
- <div class="problem-header"><span class="problem-icon">🧠</span> Context fills up too fast</div>
140
- <div class="problem-body">
141
- <div class="step">Three hooks help:</div>
142
- <pre>npx cc-safe-setup --install-example output-length-guard # Warn on large outputs
143
- npx cc-safe-setup --install-example large-read-guard # Warn before cat on large files
144
- npx cc-safe-setup --install-example compact-reminder # Suggest /compact after N calls</pre>
145
- <div class="step-fix">The context-monitor hook (installed by default) warns at 40%, 25%, 20%, 15%.</div>
146
- </div>
147
- </div>
148
-
149
- <div class="problem" onclick="this.classList.toggle('open')">
150
- <div class="problem-header"><span class="problem-icon">👥</span> Team members have different hook setups</div>
151
- <div class="problem-body">
152
- <div class="step">Use project-level hooks:</div>
153
- <pre>npx cc-safe-setup --team
154
- git add .claude/
155
- git commit -m "chore: add team safety hooks"</pre>
156
- <div class="step-fix">Hooks are copied to <code>.claude/hooks/</code> with relative paths. Works on any machine.</div>
157
- <div class="step">Generate CI to enforce:</div>
158
- <pre>npx cc-safe-setup --generate-ci</pre>
159
- </div>
160
- </div>
161
-
162
- <div class="problem" onclick="this.classList.toggle('open')">
163
- <div class="problem-header"><span class="problem-icon">🔀</span> Hooks from different tools conflict</div>
164
- <div class="problem-body">
165
- <div class="step">Analyze what you have:</div>
166
- <pre>npx cc-safe-setup --migrate-from manual # See all existing hooks
167
- npx cc-safe-setup --health # Check hook health</pre>
168
- <div class="step-fix">Hooks in the same group run sequentially. If one consumes stdin, the next gets nothing.</div>
169
- <div class="step">Fix: Put each hook in a separate matcher group in settings.json.</div>
170
- </div>
171
- </div>
172
-
173
- <div class="quick" style="margin-top:1rem">
174
- <strong>Still stuck?</strong>
175
- <code>npx cc-safe-setup --doctor</code> — full diagnosis<br>
176
- <code>npx cc-safe-setup --quickfix</code> — auto-fix common issues<br>
177
- <a href="faq.html">FAQ</a> — 15 questions answered
178
- </div>
179
-
180
- <div class="footer">
181
- <a href="hooks-cheatsheet.html">Cheat Sheet</a> ·
182
- <a href="builder.html">Builder</a> ·
183
- <a href="faq.html">FAQ</a> ·
184
- <a href="settings-reference.html">Settings Ref</a> ·
185
- <a href="https://github.com/yurukusa/cc-safe-setup">GitHub</a>
186
- </div>
187
- </div>
188
- </body>
189
- </html>
@@ -1,69 +0,0 @@
1
- // destructive_guard.go — Claude Code PreToolUse hook in Go
2
- //
3
- // Blocks rm -rf /, git reset --hard, git clean -fd, and similar
4
- // destructive commands. Exit code 2 = block, 0 = allow.
5
- //
6
- // Build: go build -o destructive-guard destructive_guard.go
7
- // Usage in settings.json:
8
- // {"type": "command", "command": "/path/to/destructive-guard"}
9
- package main
10
-
11
- import (
12
- "encoding/json"
13
- "fmt"
14
- "io"
15
- "os"
16
- "regexp"
17
- "strings"
18
- )
19
-
20
- type HookInput struct {
21
- ToolInput struct {
22
- Command string `json:"command"`
23
- } `json:"tool_input"`
24
- }
25
-
26
- var dangerousPatterns = []*regexp.Regexp{
27
- regexp.MustCompile(`\brm\s+.*-rf\s+(/|~/?\s*$|\.\./)`),
28
- regexp.MustCompile(`\bgit\s+reset\s+--hard`),
29
- regexp.MustCompile(`\bgit\s+clean\s+-[a-zA-Z]*f`),
30
- regexp.MustCompile(`\bgit\s+checkout\s+--force`),
31
- regexp.MustCompile(`\bchmod\s+(-R\s+)?777\s+/`),
32
- regexp.MustCompile(`\bfind\s+/\s+-delete`),
33
- regexp.MustCompile(`Remove-Item.*-Recurse.*-Force`),
34
- regexp.MustCompile(`--no-preserve-root`),
35
- regexp.MustCompile(`\bsudo\s+mkfs\b`),
36
- }
37
-
38
- func main() {
39
- data, err := io.ReadAll(os.Stdin)
40
- if err != nil {
41
- os.Exit(0) // Don't block on read error
42
- }
43
-
44
- var input HookInput
45
- if err := json.Unmarshal(data, &input); err != nil {
46
- os.Exit(0) // Don't block on parse error
47
- }
48
-
49
- cmd := input.ToolInput.Command
50
- if cmd == "" {
51
- os.Exit(0)
52
- }
53
-
54
- // Skip if command is in an echo/printf context
55
- lower := strings.ToLower(cmd)
56
- if strings.HasPrefix(strings.TrimSpace(lower), "echo ") ||
57
- strings.HasPrefix(strings.TrimSpace(lower), "printf ") {
58
- os.Exit(0)
59
- }
60
-
61
- for _, pattern := range dangerousPatterns {
62
- if pattern.MatchString(cmd) {
63
- fmt.Fprintf(os.Stderr, "BLOCKED: Dangerous command detected\nCommand: %s\n", cmd)
64
- os.Exit(2)
65
- }
66
- }
67
-
68
- os.Exit(0)
69
- }
@@ -1,72 +0,0 @@
1
- // destructive_guard.rs — Claude Code PreToolUse hook in Rust
2
- //
3
- // Blocks rm -rf /, git reset --hard, git clean -fd, and similar
4
- // destructive commands. Exit code 2 = block, 0 = allow.
5
- //
6
- // Build: rustc destructive_guard.rs -o destructive-guard
7
- // Usage: {"type": "command", "command": "/path/to/destructive-guard"}
8
-
9
- use std::io::{self, Read};
10
- use std::process;
11
-
12
- fn main() {
13
- let mut input = String::new();
14
- if io::stdin().read_to_string(&mut input).is_err() {
15
- process::exit(0);
16
- }
17
-
18
- // Simple JSON parsing without serde (zero dependencies)
19
- let cmd = extract_command(&input);
20
- if cmd.is_empty() {
21
- process::exit(0);
22
- }
23
-
24
- // Skip echo/printf context
25
- let trimmed = cmd.trim_start().to_lowercase();
26
- if trimmed.starts_with("echo ") || trimmed.starts_with("printf ") {
27
- process::exit(0);
28
- }
29
-
30
- let patterns: &[&str] = &[
31
- "rm -rf /",
32
- "rm -rf ~/",
33
- "rm -rf ../",
34
- "rm -rf .",
35
- "git reset --hard",
36
- "git clean -f",
37
- "git checkout --force",
38
- "chmod 777 /",
39
- "find / -delete",
40
- "--no-preserve-root",
41
- "sudo mkfs",
42
- ];
43
-
44
- for pattern in patterns {
45
- if cmd.to_lowercase().contains(&pattern.to_lowercase()) {
46
- eprintln!("BLOCKED: Dangerous command detected");
47
- eprintln!("Command: {}", cmd);
48
- process::exit(2);
49
- }
50
- }
51
-
52
- process::exit(0);
53
- }
54
-
55
- fn extract_command(json: &str) -> String {
56
- // Extract .tool_input.command from JSON without a parser
57
- if let Some(pos) = json.find("\"command\"") {
58
- let rest = &json[pos + 9..];
59
- if let Some(start) = rest.find('"') {
60
- let value_start = start + 1;
61
- let mut end = value_start;
62
- let bytes = rest.as_bytes();
63
- while end < bytes.len() {
64
- if bytes[end] == b'"' && (end == 0 || bytes[end - 1] != b'\\') {
65
- return rest[value_start..end].replace("\\\"", "\"").replace("\\\\", "\\");
66
- }
67
- end += 1;
68
- }
69
- }
70
- }
71
- String::new()
72
- }