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 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 27 example hooks (5 categories)
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.2.0",
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.",
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"