cc-safe-setup 3.2.0 → 3.3.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 +4 -0
- package/docs/cheatsheet.html +187 -0
- package/examples/tmp-cleanup.sh +36 -0
- package/index.mjs +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -215,6 +215,9 @@ 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))
|
|
219
|
+
- **session-checkpoint.sh** — Save session state to mission file before context compaction ([#37866](https://github.com/anthropics/claude-code/issues/37866))
|
|
220
|
+
- **verify-before-commit.sh** — Block git commit when lint/test commands haven't been run ([#37818](https://github.com/anthropics/claude-code/issues/37818))
|
|
218
221
|
|
|
219
222
|
## Safety Checklist
|
|
220
223
|
|
|
@@ -234,6 +237,7 @@ Or browse all available examples in [`examples/`](examples/):
|
|
|
234
237
|
- [Hooks Cookbook](https://github.com/yurukusa/claude-code-hooks/blob/main/COOKBOOK.md) — 19 ready-to-use recipes from real GitHub Issues
|
|
235
238
|
- [Japanese guide (Qiita)](https://qiita.com/yurukusa/items/a9714b33f5d974e8f1e8) — この記事の日本語解説
|
|
236
239
|
- [Hook Test Runner](https://github.com/yurukusa/cc-hook-test) — `npx cc-hook-test <hook.sh>` to auto-test any hook
|
|
240
|
+
- [Hooks Cheat Sheet](https://yurukusa.github.io/cc-safe-setup/cheatsheet.html) — printable A4 quick reference
|
|
237
241
|
- [Ecosystem Comparison](https://yurukusa.github.io/cc-safe-setup/ecosystem.html) — all Claude Code hook projects compared
|
|
238
242
|
- [The incident that inspired this tool](https://github.com/anthropics/claude-code/issues/36339) — NTFS junction rm -rf
|
|
239
243
|
|
|
@@ -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 30 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,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cc-safe-setup",
|
|
3
|
-
"version": "3.
|
|
4
|
-
"description": "One command to make Claude Code safe for autonomous operation. 8 built-in hooks +
|
|
3
|
+
"version": "3.3.0",
|
|
4
|
+
"description": "One command to make Claude Code safe for autonomous operation. 8 built-in hooks + 30 installable examples. Destructive blocker, branch guard, compound command approver, database wipe protection, tmp cleanup, and more.",
|
|
5
5
|
"main": "index.mjs",
|
|
6
6
|
"bin": {
|
|
7
7
|
"cc-safe-setup": "index.mjs"
|