cc-safe-setup 3.2.0 → 3.2.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 +2 -0
- package/docs/cheatsheet.html +187 -0
- package/examples/tmp-cleanup.sh +36 -0
- package/index.mjs +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -215,6 +215,7 @@ Or browse all available examples in [`examples/`](examples/):
|
|
|
215
215
|
- **path-traversal-guard.sh** — Block Edit/Write with `../../` path traversal and system directories
|
|
216
216
|
- **case-sensitive-guard.sh** — Detect case-insensitive filesystems (exFAT, NTFS, HFS+) and block rm/mkdir that would collide due to case folding ([#37875](https://github.com/anthropics/claude-code/issues/37875))
|
|
217
217
|
- **compound-command-approver.sh** — Auto-approve safe compound commands (`cd && git log`, `cd && npm test`) that the permission system can't match ([#30519](https://github.com/anthropics/claude-code/issues/30519) [#16561](https://github.com/anthropics/claude-code/issues/16561))
|
|
218
|
+
- **tmp-cleanup.sh** — Clean up accumulated `/tmp/claude-*-cwd` files on session end ([#8856](https://github.com/anthropics/claude-code/issues/8856))
|
|
218
219
|
|
|
219
220
|
## Safety Checklist
|
|
220
221
|
|
|
@@ -234,6 +235,7 @@ Or browse all available examples in [`examples/`](examples/):
|
|
|
234
235
|
- [Hooks Cookbook](https://github.com/yurukusa/claude-code-hooks/blob/main/COOKBOOK.md) — 19 ready-to-use recipes from real GitHub Issues
|
|
235
236
|
- [Japanese guide (Qiita)](https://qiita.com/yurukusa/items/a9714b33f5d974e8f1e8) — この記事の日本語解説
|
|
236
237
|
- [Hook Test Runner](https://github.com/yurukusa/cc-hook-test) — `npx cc-hook-test <hook.sh>` to auto-test any hook
|
|
238
|
+
- [Hooks Cheat Sheet](https://yurukusa.github.io/cc-safe-setup/cheatsheet.html) — printable A4 quick reference
|
|
237
239
|
- [Ecosystem Comparison](https://yurukusa.github.io/cc-safe-setup/ecosystem.html) — all Claude Code hook projects compared
|
|
238
240
|
- [The incident that inspired this tool](https://github.com/anthropics/claude-code/issues/36339) — NTFS junction rm -rf
|
|
239
241
|
|
|
@@ -0,0 +1,187 @@
|
|
|
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 Hooks Cheat Sheet</title>
|
|
7
|
+
<style>
|
|
8
|
+
@media print { body { padding: 0; background: #fff; color: #000; font-size: 9px; } .no-print { display: none; } h1 { font-size: 14px; } h2 { font-size: 11px; } pre { font-size: 8px; border: 1px solid #ccc; } .col { break-inside: avoid; } }
|
|
9
|
+
@media screen { body { background: #0d1117; color: #c9d1d9; padding: 1rem; } pre { background: #161b22; border: 1px solid #30363d; } h1 { color: #f0f6fc; } h2 { color: #f0f6fc; } a { color: #58a6ff; } }
|
|
10
|
+
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
11
|
+
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', monospace; font-size: 11px; line-height: 1.4; }
|
|
12
|
+
.container { max-width: 900px; margin: 0 auto; columns: 2; column-gap: 1.5rem; }
|
|
13
|
+
h1 { font-size: 16px; margin-bottom: 0.3rem; text-align: center; column-span: all; }
|
|
14
|
+
.subtitle { text-align: center; margin-bottom: 0.8rem; font-size: 10px; opacity: 0.7; column-span: all; }
|
|
15
|
+
h2 { font-size: 12px; margin: 0.6rem 0 0.3rem; border-bottom: 1px solid #30363d; padding-bottom: 0.15rem; }
|
|
16
|
+
pre { padding: 0.4rem; border-radius: 4px; overflow-x: auto; font-size: 9.5px; margin: 0.2rem 0 0.4rem; white-space: pre-wrap; word-break: break-all; }
|
|
17
|
+
.col { break-inside: avoid; margin-bottom: 0.3rem; }
|
|
18
|
+
table { width: 100%; border-collapse: collapse; font-size: 9.5px; margin: 0.2rem 0; }
|
|
19
|
+
th, td { text-align: left; padding: 0.15rem 0.3rem; border-bottom: 1px solid #21262d; }
|
|
20
|
+
th { font-weight: 600; }
|
|
21
|
+
code { font-size: 9px; padding: 0.1rem 0.2rem; border-radius: 2px; }
|
|
22
|
+
@media screen { code { background: #161b22; } }
|
|
23
|
+
.footer { text-align: center; font-size: 8px; opacity: 0.5; margin-top: 0.5rem; column-span: all; }
|
|
24
|
+
</style>
|
|
25
|
+
</head>
|
|
26
|
+
<body>
|
|
27
|
+
<h1>Claude Code Hooks Cheat Sheet</h1>
|
|
28
|
+
<p class="subtitle">Quick reference · Print this page (Ctrl+P) · <a href="https://github.com/yurukusa/cc-safe-setup" class="no-print">github.com/yurukusa/cc-safe-setup</a></p>
|
|
29
|
+
|
|
30
|
+
<div class="container">
|
|
31
|
+
|
|
32
|
+
<div class="col">
|
|
33
|
+
<h2>Hook Lifecycle</h2>
|
|
34
|
+
<pre>Prompt → PreToolUse → Tool Executes → PostToolUse → Stop
|
|
35
|
+
↑ block here ↑ check here ↑ log here</pre>
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
<div class="col">
|
|
39
|
+
<h2>Exit Codes</h2>
|
|
40
|
+
<table>
|
|
41
|
+
<tr><th>Code</th><th>Meaning</th></tr>
|
|
42
|
+
<tr><td><code>0</code></td><td>Allow (or no opinion)</td></tr>
|
|
43
|
+
<tr><td><code>2</code></td><td><strong>Block</strong> — tool call cancelled</td></tr>
|
|
44
|
+
<tr><td>other</td><td>Error (treated as allow)</td></tr>
|
|
45
|
+
</table>
|
|
46
|
+
</div>
|
|
47
|
+
|
|
48
|
+
<div class="col">
|
|
49
|
+
<h2>Hook Events</h2>
|
|
50
|
+
<table>
|
|
51
|
+
<tr><th>Event</th><th>Matcher</th><th>Use</th></tr>
|
|
52
|
+
<tr><td>PreToolUse</td><td>Bash</td><td>Block commands</td></tr>
|
|
53
|
+
<tr><td>PostToolUse</td><td>Edit|Write</td><td>Syntax check</td></tr>
|
|
54
|
+
<tr><td>PostToolUse</td><td>(empty)</td><td>All tools</td></tr>
|
|
55
|
+
<tr><td>Stop</td><td>(empty)</td><td>Session end</td></tr>
|
|
56
|
+
<tr><td>UserPromptSubmit</td><td>—</td><td>Validate input</td></tr>
|
|
57
|
+
</table>
|
|
58
|
+
</div>
|
|
59
|
+
|
|
60
|
+
<div class="col">
|
|
61
|
+
<h2>settings.json Structure</h2>
|
|
62
|
+
<pre>{
|
|
63
|
+
"hooks": {
|
|
64
|
+
"PreToolUse": [{
|
|
65
|
+
"matcher": "Bash",
|
|
66
|
+
"hooks": [{
|
|
67
|
+
"type": "command",
|
|
68
|
+
"command": "~/.claude/hooks/guard.sh"
|
|
69
|
+
}]
|
|
70
|
+
}]
|
|
71
|
+
}
|
|
72
|
+
}</pre>
|
|
73
|
+
</div>
|
|
74
|
+
|
|
75
|
+
<div class="col">
|
|
76
|
+
<h2>Minimal Block Hook</h2>
|
|
77
|
+
<pre>#!/bin/bash
|
|
78
|
+
COMMAND=$(cat | jq -r '.tool_input.command // empty')
|
|
79
|
+
[ -z "$COMMAND" ] && exit 0
|
|
80
|
+
if echo "$COMMAND" | grep -qE 'PATTERN'; then
|
|
81
|
+
echo "BLOCKED: reason" >&2
|
|
82
|
+
exit 2
|
|
83
|
+
fi
|
|
84
|
+
exit 0</pre>
|
|
85
|
+
</div>
|
|
86
|
+
|
|
87
|
+
<div class="col">
|
|
88
|
+
<h2>Auto-Approve Hook</h2>
|
|
89
|
+
<pre>#!/bin/bash
|
|
90
|
+
COMMAND=$(cat | jq -r '.tool_input.command // empty')
|
|
91
|
+
[ -z "$COMMAND" ] && exit 0
|
|
92
|
+
if echo "$COMMAND" | grep -qE '^\s*git\s+(status|log|diff)'; then
|
|
93
|
+
jq -n '{
|
|
94
|
+
"hookSpecificOutput": {
|
|
95
|
+
"hookEventName": "PreToolUse",
|
|
96
|
+
"permissionDecision": "allow"
|
|
97
|
+
}
|
|
98
|
+
}'
|
|
99
|
+
fi
|
|
100
|
+
exit 0</pre>
|
|
101
|
+
</div>
|
|
102
|
+
|
|
103
|
+
<div class="col">
|
|
104
|
+
<h2>PostToolUse Syntax Check</h2>
|
|
105
|
+
<pre>#!/bin/bash
|
|
106
|
+
FILE=$(cat | jq -r '.tool_input.file_path // empty')
|
|
107
|
+
[ -z "$FILE" ] || [ ! -f "$FILE" ] && exit 0
|
|
108
|
+
case "${FILE##*.}" in
|
|
109
|
+
py) python3 -m py_compile "$FILE" 2>&1 ;;
|
|
110
|
+
sh) bash -n "$FILE" 2>&1 ;;
|
|
111
|
+
json) jq empty "$FILE" 2>&1 ;;
|
|
112
|
+
js) node --check "$FILE" 2>&1 ;;
|
|
113
|
+
esac
|
|
114
|
+
exit 0</pre>
|
|
115
|
+
</div>
|
|
116
|
+
|
|
117
|
+
<div class="col">
|
|
118
|
+
<h2>Modify Input</h2>
|
|
119
|
+
<pre>#!/bin/bash
|
|
120
|
+
# Strip comments from bash commands
|
|
121
|
+
COMMAND=$(cat | jq -r '.tool_input.command // empty')
|
|
122
|
+
CLEAN=$(echo "$COMMAND" | sed '/^#/d; /^$/d')
|
|
123
|
+
[ "$CLEAN" = "$COMMAND" ] && exit 0
|
|
124
|
+
jq -n --arg cmd "$CLEAN" '{
|
|
125
|
+
"hookSpecificOutput": {
|
|
126
|
+
"hookEventName": "PreToolUse",
|
|
127
|
+
"updatedInput": {"command": $cmd}
|
|
128
|
+
}
|
|
129
|
+
}'</pre>
|
|
130
|
+
</div>
|
|
131
|
+
|
|
132
|
+
<div class="col">
|
|
133
|
+
<h2>stdin JSON Reference</h2>
|
|
134
|
+
<table>
|
|
135
|
+
<tr><th>Event</th><th>Key Fields</th></tr>
|
|
136
|
+
<tr><td>PreToolUse (Bash)</td><td><code>.tool_input.command</code></td></tr>
|
|
137
|
+
<tr><td>PreToolUse (Edit)</td><td><code>.tool_input.file_path</code></td></tr>
|
|
138
|
+
<tr><td>PostToolUse</td><td><code>.tool_input.file_path</code></td></tr>
|
|
139
|
+
<tr><td>Stop</td><td><code>.stop_reason</code></td></tr>
|
|
140
|
+
<tr><td>UserPromptSubmit</td><td><code>.prompt</code></td></tr>
|
|
141
|
+
</table>
|
|
142
|
+
</div>
|
|
143
|
+
|
|
144
|
+
<div class="col">
|
|
145
|
+
<h2>Test a Hook</h2>
|
|
146
|
+
<pre># Manual test
|
|
147
|
+
echo '{"tool_input":{"command":"rm -rf /"}}' \
|
|
148
|
+
| bash ~/.claude/hooks/guard.sh
|
|
149
|
+
echo $? # 2 = blocked
|
|
150
|
+
|
|
151
|
+
# Auto-test
|
|
152
|
+
npx cc-hook-test ~/.claude/hooks/guard.sh</pre>
|
|
153
|
+
</div>
|
|
154
|
+
|
|
155
|
+
<div class="col">
|
|
156
|
+
<h2>Quick Setup Commands</h2>
|
|
157
|
+
<table>
|
|
158
|
+
<tr><td><code>npx cc-safe-setup</code></td><td>Install 8 hooks</td></tr>
|
|
159
|
+
<tr><td><code>--create "desc"</code></td><td>Generate hook</td></tr>
|
|
160
|
+
<tr><td><code>--audit</code></td><td>Safety score</td></tr>
|
|
161
|
+
<tr><td><code>--lint</code></td><td>Config analysis</td></tr>
|
|
162
|
+
<tr><td><code>--doctor</code></td><td>Diagnose issues</td></tr>
|
|
163
|
+
<tr><td><code>--watch</code></td><td>Live dashboard</td></tr>
|
|
164
|
+
<tr><td><code>--stats</code></td><td>Block statistics</td></tr>
|
|
165
|
+
<tr><td><code>--verify</code></td><td>Test all hooks</td></tr>
|
|
166
|
+
<tr><td><code>--export</code></td><td>Share with team</td></tr>
|
|
167
|
+
</table>
|
|
168
|
+
</div>
|
|
169
|
+
|
|
170
|
+
<div class="col">
|
|
171
|
+
<h2>Common Patterns</h2>
|
|
172
|
+
<table>
|
|
173
|
+
<tr><th>Block</th><th>Pattern</th></tr>
|
|
174
|
+
<tr><td>rm -rf /</td><td><code>rm\s+(-[rf]+\s+)*/</code></td></tr>
|
|
175
|
+
<tr><td>force push</td><td><code>git\s+push.*--force</code></td></tr>
|
|
176
|
+
<tr><td>push main</td><td><code>git\s+push.*main</code></td></tr>
|
|
177
|
+
<tr><td>.env commit</td><td><code>git\s+add.*\.env</code></td></tr>
|
|
178
|
+
<tr><td>git reset</td><td><code>git\s+reset\s+--hard</code></td></tr>
|
|
179
|
+
<tr><td>DB wipe</td><td><code>migrate:fresh|DROP\s+DB</code></td></tr>
|
|
180
|
+
</table>
|
|
181
|
+
</div>
|
|
182
|
+
|
|
183
|
+
</div>
|
|
184
|
+
|
|
185
|
+
<p class="footer">cc-safe-setup v3.2.0 · 20 recipes: <a href="https://github.com/yurukusa/claude-code-hooks/blob/main/COOKBOOK.md" class="no-print">COOKBOOK.md</a> · Full ref: <a href="https://github.com/yurukusa/cc-safe-setup/blob/main/SETTINGS_REFERENCE.md" class="no-print">SETTINGS_REFERENCE.md</a></p>
|
|
186
|
+
</body>
|
|
187
|
+
</html>
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ================================================================
|
|
3
|
+
# tmp-cleanup.sh — Clean up /tmp/claude-*-cwd temp files
|
|
4
|
+
# ================================================================
|
|
5
|
+
# PURPOSE:
|
|
6
|
+
# Claude Code creates /tmp/claude-{hex}-cwd files to track working
|
|
7
|
+
# directory changes but never deletes them. Over time, thousands
|
|
8
|
+
# accumulate.
|
|
9
|
+
#
|
|
10
|
+
# This hook runs on session end and cleans up stale files.
|
|
11
|
+
#
|
|
12
|
+
# GitHub #8856 (67 reactions, 102 comments) — the most reported
|
|
13
|
+
# resource leak in Claude Code.
|
|
14
|
+
#
|
|
15
|
+
# TRIGGER: Stop
|
|
16
|
+
# MATCHER: ""
|
|
17
|
+
#
|
|
18
|
+
# WHAT IT CLEANS:
|
|
19
|
+
# - /tmp/claude-*-cwd (working directory tracking files, ~22 bytes each)
|
|
20
|
+
# - Only files older than 1 hour (to avoid cleaning active sessions)
|
|
21
|
+
#
|
|
22
|
+
# WHAT IT DOES NOT CLEAN:
|
|
23
|
+
# - /tmp/claude-* directories (may be in use by other sessions)
|
|
24
|
+
# - Any non-claude temp files
|
|
25
|
+
# ================================================================
|
|
26
|
+
|
|
27
|
+
# Clean up stale cwd tracking files (older than 60 minutes)
|
|
28
|
+
find /tmp -maxdepth 1 -name 'claude-*-cwd' -type f -mmin +60 -delete 2>/dev/null
|
|
29
|
+
|
|
30
|
+
# Count remaining (for logging)
|
|
31
|
+
REMAINING=$(find /tmp -maxdepth 1 -name 'claude-*-cwd' -type f 2>/dev/null | wc -l)
|
|
32
|
+
if [ "$REMAINING" -gt 100 ]; then
|
|
33
|
+
echo "NOTE: $REMAINING claude-*-cwd files remain in /tmp (active sessions)" >&2
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
exit 0
|
package/index.mjs
CHANGED
|
@@ -93,7 +93,7 @@ if (HELP) {
|
|
|
93
93
|
npx cc-safe-setup --verify Test each hook with sample inputs
|
|
94
94
|
npx cc-safe-setup --dry-run Preview without installing
|
|
95
95
|
npx cc-safe-setup --uninstall Remove all installed hooks
|
|
96
|
-
npx cc-safe-setup --examples List
|
|
96
|
+
npx cc-safe-setup --examples List 28 example hooks (5 categories)
|
|
97
97
|
npx cc-safe-setup --install-example <name> Install a specific example
|
|
98
98
|
npx cc-safe-setup --full Complete setup: hooks + scan + audit + badge
|
|
99
99
|
npx cc-safe-setup --audit Safety score (0-100) with fixes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cc-safe-setup",
|
|
3
|
-
"version": "3.2.
|
|
3
|
+
"version": "3.2.1",
|
|
4
4
|
"description": "One command to make Claude Code safe for autonomous operation. 8 built-in hooks + 27 installable examples. Destructive blocker, branch guard, compound command approver, database wipe protection, and more.",
|
|
5
5
|
"main": "index.mjs",
|
|
6
6
|
"bin": {
|