@eltonssouza/development-utility-kit 1.0.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.
Files changed (137) hide show
  1. package/.claude/agents/analyst.md +198 -0
  2. package/.claude/agents/backend-developer.md +126 -0
  3. package/.claude/agents/brain-keeper.md +229 -0
  4. package/.claude/agents/code-reviewer.md +181 -0
  5. package/.claude/agents/database-engineer.md +94 -0
  6. package/.claude/agents/devops-engineer.md +141 -0
  7. package/.claude/agents/frontend-developer.md +97 -0
  8. package/.claude/agents/gate-keeper.md +118 -0
  9. package/.claude/agents/migrator.md +291 -0
  10. package/.claude/agents/mobile-developer.md +80 -0
  11. package/.claude/agents/n8n-specialist.md +94 -0
  12. package/.claude/agents/product-owner.md +115 -0
  13. package/.claude/agents/qa-engineer.md +232 -0
  14. package/.claude/agents/release-engineer.md +204 -0
  15. package/.claude/agents/scaffold.md +87 -0
  16. package/.claude/agents/security-engineer.md +199 -0
  17. package/.claude/agents/sprint-runner.md +44 -0
  18. package/.claude/agents/stack-resolver.md +84 -0
  19. package/.claude/agents/tech-lead.md +182 -0
  20. package/.claude/agents/update-template.md +54 -0
  21. package/.claude/agents/ux-designer.md +118 -0
  22. package/.claude/settings.json +44 -0
  23. package/.claude/skills/README.md +332 -0
  24. package/.claude/skills/active-project/SKILL.md +129 -0
  25. package/.claude/skills/api-integration-test/SKILL.md +64 -0
  26. package/.claude/skills/auto-test-guard/SKILL.md +237 -0
  27. package/.claude/skills/auto-test-guard/resources/backend-tests.md +20 -0
  28. package/.claude/skills/auto-test-guard/resources/e2e-tests.md +24 -0
  29. package/.claude/skills/auto-test-guard/resources/execution-report.md +49 -0
  30. package/.claude/skills/auto-test-guard/resources/frontend-tests.md +18 -0
  31. package/.claude/skills/auto-test-guard/resources/initial-setup.md +108 -0
  32. package/.claude/skills/auto-test-guard/resources/run-suite.md +48 -0
  33. package/.claude/skills/auto-test-guard/resources/senior-gate.md +19 -0
  34. package/.claude/skills/brain-keeper/SKILL.md +60 -0
  35. package/.claude/skills/brain-keeper/obsidian/app.json +9 -0
  36. package/.claude/skills/brain-keeper/obsidian/appearance.json +4 -0
  37. package/.claude/skills/brain-keeper/obsidian/core-plugins.json +20 -0
  38. package/.claude/skills/brain-keeper/obsidian/daily-notes.json +5 -0
  39. package/.claude/skills/brain-keeper/obsidian/graph.json +32 -0
  40. package/.claude/skills/brain-keeper/obsidian/snippets/folder-colors.css +90 -0
  41. package/.claude/skills/brain-keeper/obsidian/templates.json +5 -0
  42. package/.claude/skills/brain-keeper/templates/README.md +51 -0
  43. package/.claude/skills/brain-keeper/templates/adr.md +40 -0
  44. package/.claude/skills/brain-keeper/templates/bug.md +35 -0
  45. package/.claude/skills/brain-keeper/templates/daily.md +38 -0
  46. package/.claude/skills/brain-keeper/templates/feature.md +62 -0
  47. package/.claude/skills/brain-keeper/templates/meeting.md +34 -0
  48. package/.claude/skills/brain-keeper/templates/tech-debt.md +21 -0
  49. package/.claude/skills/caveman/SKILL.md +187 -0
  50. package/.claude/skills/create-stack-pack/SKILL.md +281 -0
  51. package/.claude/skills/grill-me/SKILL.md +79 -0
  52. package/.claude/skills/honcho-memory/SKILL.md +207 -0
  53. package/.claude/skills/honcho-memory/docs/api-endpoints-verified.md +75 -0
  54. package/.claude/skills/honcho-memory/hooks/on-prompt-submit.js +221 -0
  55. package/.claude/skills/honcho-memory/hooks/on-stop.js +193 -0
  56. package/.claude/skills/honcho-memory/lib/honcho-client.js +363 -0
  57. package/.claude/skills/honcho-memory/lib/memory-injector.js +93 -0
  58. package/.claude/skills/honcho-memory/package.json +32 -0
  59. package/.claude/skills/honcho-memory/scripts/cli.js +370 -0
  60. package/.claude/skills/honcho-memory/scripts/setup.js +109 -0
  61. package/.claude/skills/honcho-memory/tests/t001-api-endpoints-verified.test.js +89 -0
  62. package/.claude/skills/honcho-memory/tests/t002-structure.test.js +97 -0
  63. package/.claude/skills/honcho-memory/tests/t003-honcho-client.test.js +162 -0
  64. package/.claude/skills/honcho-memory/tests/t004-soft-delete.test.js +259 -0
  65. package/.claude/skills/honcho-memory/tests/t005-memory-injector.test.js +175 -0
  66. package/.claude/skills/honcho-memory/tests/t006-on-prompt-submit.test.js +215 -0
  67. package/.claude/skills/honcho-memory/tests/t007-on-stop.test.js +165 -0
  68. package/.claude/skills/honcho-memory/tests/t008-cli.test.js +214 -0
  69. package/.claude/skills/honcho-memory/tests/t009-setup.test.js +232 -0
  70. package/.claude/skills/honcho-memory/tests/t010-skill-md.test.js +114 -0
  71. package/.claude/skills/honcho-memory/tests/t011-settings-hooks.test.js +105 -0
  72. package/.claude/skills/honcho-memory/tests/t012-docs-update.test.js +106 -0
  73. package/.claude/skills/honcho-memory/tests/t013-smoke-e2e.test.js +90 -0
  74. package/.claude/skills/pair-debug/SKILL.md +288 -0
  75. package/.claude/skills/prd-ready-check/SKILL.md +58 -0
  76. package/.claude/skills/project-manager/SKILL.md +167 -0
  77. package/.claude/skills/quality-standards/SKILL.md +201 -0
  78. package/.claude/skills/quick-feature/SKILL.md +264 -0
  79. package/.claude/skills/run-sprint/SKILL.md +342 -0
  80. package/.claude/skills/scaffold/SKILL.md +58 -0
  81. package/.claude/skills/stack-discovery/SKILL.md +159 -0
  82. package/.claude/skills/test-coverage-auditor/SKILL.md +59 -0
  83. package/.claude/skills/to-issues/SKILL.md +163 -0
  84. package/.claude/skills/to-prd/SKILL.md +130 -0
  85. package/.claude/skills/update-template/SKILL.md +254 -0
  86. package/.claude/stacks/CODEOWNERS +30 -0
  87. package/.claude/stacks/README.md +88 -0
  88. package/.claude/stacks/_template.md +116 -0
  89. package/.claude/stacks/java/spring-boot-3.md +376 -0
  90. package/.claude/stacks/java/spring-boot-4.md +438 -0
  91. package/.claude/stacks/typescript/angular-18.md +420 -0
  92. package/.claude/stacks/typescript/angular-19.md +397 -0
  93. package/.claude/stacks/typescript/angular-21.md +494 -0
  94. package/CLAUDE.md +453 -0
  95. package/README.md +391 -0
  96. package/bin/cli.js +773 -0
  97. package/bin/lib/backup.js +62 -0
  98. package/bin/lib/detect-stack.js +476 -0
  99. package/bin/lib/help.js +233 -0
  100. package/bin/lib/identity.js +108 -0
  101. package/bin/lib/local-dir.js +69 -0
  102. package/bin/lib/manifest.js +236 -0
  103. package/bin/lib/sync-all.js +394 -0
  104. package/bin/lib/version-check.js +398 -0
  105. package/dashboard/db.js +199 -0
  106. package/dashboard/package.json +22 -0
  107. package/dashboard/public/app.js +709 -0
  108. package/dashboard/public/content/docs/agents-reference.en.md +911 -0
  109. package/dashboard/public/content/docs/architecture-overview.en.md +260 -0
  110. package/dashboard/public/content/docs/autonomy-matrix.en.md +186 -0
  111. package/dashboard/public/content/docs/git-flow.en.md +525 -0
  112. package/dashboard/public/content/docs/honcho-memory.en.md +394 -0
  113. package/dashboard/public/content/docs/hooks-reference.en.md +420 -0
  114. package/dashboard/public/content/docs/pipeline.en.md +400 -0
  115. package/dashboard/public/content/docs/quality-gate.en.md +315 -0
  116. package/dashboard/public/content/docs/skills-reference.en.md +500 -0
  117. package/dashboard/public/content/docs/stack-rules.en.md +362 -0
  118. package/dashboard/public/content/docs/troubleshooting.en.md +637 -0
  119. package/dashboard/public/content/manifest.json +102 -0
  120. package/dashboard/public/content/manual/backend.en.md +1138 -0
  121. package/dashboard/public/content/manual/existing-project.en.md +831 -0
  122. package/dashboard/public/content/manual/frontend.en.md +1065 -0
  123. package/dashboard/public/content/manual/fullstack.en.md +1508 -0
  124. package/dashboard/public/content/manual/mobile.en.md +866 -0
  125. package/dashboard/public/index.html +108 -0
  126. package/dashboard/public/style.css +610 -0
  127. package/dashboard/public/vendor/marked.min.js +69 -0
  128. package/dashboard/rtk.js +143 -0
  129. package/dashboard/server-app.js +403 -0
  130. package/dashboard/server.js +104 -0
  131. package/dashboard/test/sprint1.test.js +406 -0
  132. package/dashboard/test/sprint2.test.js +571 -0
  133. package/dashboard/test/sprint3.test.js +560 -0
  134. package/package.json +33 -0
  135. package/scripts/hooks/subagent-telemetry.sh +14 -0
  136. package/scripts/hooks/telemetry-writer.js +250 -0
  137. package/scripts/latest-versions.json +56 -0
@@ -0,0 +1,420 @@
1
+ # Hooks Reference
2
+
3
+ This document describes every Claude Code hook active in the `development-utility-kit` harness. Hooks are extension points executed by the Claude Code runtime on specific lifecycle events — do not confuse them with Git hooks (`pre-commit`, `pre-push`), which live under `.git/hooks/` and are managed by Git.
4
+
5
+ Claude Code hooks are registered in `.claude/settings.json` (project scope) or in `~/.claude/settings.json` (user global scope). Each hook is an `event + shell command` pair, optionally filtered by a `matcher` that restricts which tool or prompt pattern fires the hook.
6
+
7
+ Audience: Java/Angular developers working inside the local harness dashboard or in projects that adopted the template.
8
+
9
+ ---
10
+
11
+ ## Overview — Claude Code events
12
+
13
+ | Event | Fires when | Can block? |
14
+ |---|---|---|
15
+ | `PreToolUse` | Before a tool (Bash, Edit, Write, etc.) runs | Yes — exit != 0 cancels the tool |
16
+ | `PostToolUse` | After a tool completes successfully | No — exit code is informational |
17
+ | `UserPromptSubmit` | Before the user prompt is sent to the model | Stdin/stdout can alter the prompt; exit != 0 cancels |
18
+ | `Stop` | When the session / turn ends | Does not block |
19
+ | `Notification` | When Claude Code needs user attention | Does not block |
20
+ | `SubagentStop` | When a sub-agent (Task tool) finishes | Does not block |
21
+
22
+ The `matcher` is matched against the tool name (`Bash`, `Edit`, `MultiEdit`, `Write`, `Read`, ...) or uses `*` as wildcard for events that have no tool (`UserPromptSubmit`, `Stop`, `Notification`).
23
+
24
+ ---
25
+
26
+ ## Master table — Active hooks in the harness
27
+
28
+ The table summarizes every hook registered in `.claude/settings.json`. Per-hook details follow in the next sections.
29
+
30
+ | Event | Matcher | Script / Command | Purpose | Failure mode |
31
+ |---|---|---|---|---|
32
+ | `PreToolUse` | `Bash` | `scripts/hooks/pre-push-guard.sh` | Block unsafe `git push` (protected branch, no approval) | Exit != 0 blocks the Bash command |
33
+ | `PreToolUse` | `Bash` | `scripts/hooks/block-test-deletion.sh` | Forbid `rm` / destructive edits on test files without justification | Exit != 0 blocks the Bash command |
34
+ | `PostToolUse` | `Edit\|MultiEdit\|Write` | `npx prettier --write` (inline) | Auto-format `.ts/.tsx/.html/.scss/.css` after editing | Silent — prettier failures never break the edit |
35
+ | `PostToolUse` | `Edit\|MultiEdit\|Write` | `scripts/hooks/post-edit-test-reminder.sh` | Remind to run tests / coverage after editing source | Always exit 0 — warning only |
36
+ | `UserPromptSubmit` | `*` | `scripts/hooks/prompt-gate-reminder.sh` | Remind senior+ gate before critical tasks | Always exit 0 — informational |
37
+ | `Stop` | `*` | `scripts/hooks/stop-brain-reminder.sh` | Remind to invoke `brain-keeper` at end of PLAN | Always exit 0 |
38
+ | `Notification` | `*` | inline `notify-send` / `osascript` | Desktop notification when Claude needs attention | Silent |
39
+ | `SubagentStop` (global) | `*` | `scripts/hooks/subagent-telemetry.sh` -> `telemetry-writer.js` | Persist sub-agent execution telemetry to `~/.claude/telemetry.db` | Silent — `exit 0` even on failure |
40
+ | `UserPromptSubmit` (global) | `*` | `.claude/skills/honcho-memory/hooks/on-prompt-submit.js` | Detect memory triggers + inject `[HONCHO MEMORY]` block | Silent — always `exit 0` |
41
+ | `Stop` (global) | `*` | `.claude/skills/honcho-memory/hooks/on-stop.js` | Save current session `project-context` | Silent — always `exit 0` |
42
+
43
+ ---
44
+
45
+ ## Harness hooks (`scripts/hooks/`)
46
+
47
+ ### PreToolUse — `pre-push-guard.sh`
48
+
49
+ **Trigger**: before any execution of the `Bash` tool.
50
+
51
+ **Command registered in `.claude/settings.json`**:
52
+
53
+ ```json
54
+ {
55
+ "matcher": "Bash",
56
+ "hooks": [
57
+ {
58
+ "type": "command",
59
+ "command": "bash \"$CLAUDE_PROJECT_DIR\"/scripts/hooks/pre-push-guard.sh"
60
+ }
61
+ ]
62
+ }
63
+ ```
64
+
65
+ **What the script does**: inspects the Bash command about to run. If it contains a `git push` targeting a protected branch (`main`, `develop`, `master`) without expected override flags, it fails with exit code 1 and prints the reason to stderr.
66
+
67
+ **When it blocks**:
68
+ - `git push origin main` directly, without an approved PR
69
+ - `git push --force` on a shared branch
70
+ - Push to a remote considered "protected" by the harness
71
+
72
+ **How to debug**:
73
+
74
+ ```bash
75
+ echo '{"command":"git push origin main"}' | bash scripts/hooks/pre-push-guard.sh
76
+ echo $? # expected: != 0
77
+ ```
78
+
79
+ ---
80
+
81
+ ### PreToolUse — `block-test-deletion.sh`
82
+
83
+ **Trigger**: before any execution of the `Bash` tool.
84
+
85
+ **Command**:
86
+
87
+ ```json
88
+ {
89
+ "matcher": "Bash",
90
+ "hooks": [
91
+ {
92
+ "type": "command",
93
+ "command": "bash \"$CLAUDE_PROJECT_DIR\"/scripts/hooks/block-test-deletion.sh"
94
+ }
95
+ ]
96
+ }
97
+ ```
98
+
99
+ **What the script does**: parses the Bash command looking for destructive operations on test files (`rm -rf src/**/*.test.ts`, `git rm src/**/*Test.java`, etc.). Sub-agents must not delete tests — only `tech-lead` approves removal, and it must come with a justification recorded in the PLAN.
100
+
101
+ **When it blocks**:
102
+ - Direct `rm` on `*.test.ts`, `*.spec.ts`, `*Test.java`, `*IT.java` files
103
+ - `git rm` inside `tests/` or `src/test/` directories
104
+ - `> /dev/null` redirect that wipes test content
105
+
106
+ **How to debug**:
107
+
108
+ ```bash
109
+ echo '{"command":"rm src/app/foo.spec.ts"}' | bash scripts/hooks/block-test-deletion.sh
110
+ ```
111
+
112
+ ---
113
+
114
+ ### PostToolUse — Inline auto-formatting (prettier)
115
+
116
+ **Trigger**: after `Edit`, `MultiEdit` or `Write` completes successfully.
117
+
118
+ **Inline command in `.claude/settings.json`**:
119
+
120
+ ```bash
121
+ json=$(cat); file_path=$(echo "$json" | jq -r '.file_path // empty'); \
122
+ if [[ "$file_path" =~ \.(ts|tsx|html|scss|css)$ ]] \
123
+ && command -v npx &>/dev/null \
124
+ && [ -f node_modules/.bin/prettier ]; then \
125
+ npx prettier --write "$file_path" 2>/dev/null; \
126
+ fi
127
+ ```
128
+
129
+ **What it does**: reads the hook JSON payload (which contains `file_path`), checks the extension and fires `npx prettier --write` if prettier is installed locally. Keeps formatting consistent with no manual intervention.
130
+
131
+ **When it blocks**: never. Everything is silenced by `2>/dev/null` and the exit code is ignored.
132
+
133
+ **How to debug**:
134
+
135
+ ```bash
136
+ echo '{"file_path":"src/app/foo.component.ts"}' | bash -c '<command above>'
137
+ ```
138
+
139
+ **Prerequisite**: `prettier` must exist at `node_modules/.bin/prettier` (install with `npm i -D prettier`).
140
+
141
+ ---
142
+
143
+ ### PostToolUse — `post-edit-test-reminder.sh`
144
+
145
+ **Trigger**: after `Edit`, `MultiEdit` or `Write`.
146
+
147
+ **Command**:
148
+
149
+ ```json
150
+ {
151
+ "matcher": "Edit|MultiEdit|Write",
152
+ "hooks": [
153
+ {
154
+ "type": "command",
155
+ "command": "bash \"$CLAUDE_PROJECT_DIR\"/scripts/hooks/post-edit-test-reminder.sh"
156
+ }
157
+ ]
158
+ }
159
+ ```
160
+
161
+ **What it does**: reminds the running agent to execute the relevant suite (`mvn test` on backend, `npm test` on frontend) if the edited file belongs to `domain/`, `application/` or `src/app/`. Prints the message to stderr; never blocks.
162
+
163
+ ---
164
+
165
+ ### UserPromptSubmit — `prompt-gate-reminder.sh`
166
+
167
+ **Trigger**: before each user prompt is sent to the model.
168
+
169
+ **Command**:
170
+
171
+ ```json
172
+ {
173
+ "matcher": "*",
174
+ "hooks": [
175
+ {
176
+ "type": "command",
177
+ "command": "bash \"$CLAUDE_PROJECT_DIR\"/scripts/hooks/prompt-gate-reminder.sh"
178
+ }
179
+ ]
180
+ }
181
+ ```
182
+
183
+ **What it does**: detects critical keywords in the prompt ("merge", "deploy", "release", "production") and appends a stderr reminder to invoke `gate-keeper` before proceeding. Useful in long sessions where the senior+ gate might have been forgotten.
184
+
185
+ ---
186
+
187
+ ### Stop — `stop-brain-reminder.sh`
188
+
189
+ **Trigger**: when the session turn ends.
190
+
191
+ **Command**:
192
+
193
+ ```json
194
+ {
195
+ "matcher": "*",
196
+ "hooks": [
197
+ {
198
+ "type": "command",
199
+ "command": "bash \"$CLAUDE_PROJECT_DIR\"/scripts/hooks/stop-brain-reminder.sh"
200
+ }
201
+ ]
202
+ }
203
+ ```
204
+
205
+ **What it does**: at the end of a `PLAN_*.md` or a relevant feature, reminds the user to invoke `brain-keeper` to record daily / feature / ADR / bug / tech-debt entries under `docs/brain/`. Does not block.
206
+
207
+ ---
208
+
209
+ ### Notification — Desktop notify
210
+
211
+ **Trigger**: when Claude Code requires user attention (e.g., waiting for tool approval).
212
+
213
+ **Inline command**:
214
+
215
+ ```bash
216
+ if command -v notify-send &>/dev/null; then
217
+ notify-send 'Claude Code' 'Needs your attention'
218
+ elif command -v osascript &>/dev/null; then
219
+ osascript -e 'display notification "Needs your attention" with title "Claude Code"'
220
+ fi
221
+ ```
222
+
223
+ **What it does**: fires a native notification (Linux via `notify-send`, macOS via `osascript`). On Windows with WSL, you need `notify-send` available in the WSL PATH for it to work.
224
+
225
+ ---
226
+
227
+ ## honcho-memory hooks
228
+
229
+ The `honcho-memory` skill registers two hooks at **global** scope (`~/.claude/settings.json`), not at the project level. Full details in [Honcho memory](honcho-memory); here only a quick summary for cross-reference.
230
+
231
+ | Event | Script | Function |
232
+ |---|---|---|
233
+ | `UserPromptSubmit` | `.claude/skills/honcho-memory/hooks/on-prompt-submit.js` | Detect triggers ("lembra que", "remember that", "never ...", "always ..."), save explicit memory, run hybrid peer + session search, inject `[HONCHO MEMORY]` block into the prompt |
234
+ | `Stop` | `.claude/skills/honcho-memory/hooks/on-stop.js` | Extract active feature/sprint from `CLAUDE.md` + `git log -3`, save as `project-context` |
235
+
236
+ Both run via `bun run` and always return exit 0 — Honcho being offline degrades silently without blocking the flow.
237
+
238
+ ---
239
+
240
+ ## Telemetry hook — `subagent-telemetry.sh`
241
+
242
+ **Trigger**: global `SubagentStop`. Fires every time a `Task` call (sub-agent) ends, in any project.
243
+
244
+ **Script** (`scripts/hooks/subagent-telemetry.sh`):
245
+
246
+ ```bash
247
+ #!/usr/bin/env bash
248
+ set -uo pipefail
249
+
250
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
251
+ WRITER="${SCRIPT_DIR}/telemetry-writer.js"
252
+
253
+ if [ ! -f "$WRITER" ]; then
254
+ exit 0
255
+ fi
256
+
257
+ node "$WRITER" || exit 0
258
+ ```
259
+
260
+ **Writer** (`scripts/hooks/telemetry-writer.js`): reads the `SubagentStop` JSON payload from stdin, normalises the model name (opus / sonnet / haiku / other) and persists the event in `~/.claude/telemetry.db` via `better-sqlite3` (fallback `sql.js`, final fallback NDJSON queue at `~/.claude/telemetry-queue.ndjson`).
261
+
262
+ **Schema** (created idempotently):
263
+
264
+ ```sql
265
+ CREATE TABLE IF NOT EXISTS events (
266
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
267
+ project_path TEXT NOT NULL,
268
+ project_name TEXT NOT NULL,
269
+ model TEXT NOT NULL,
270
+ input_tokens INTEGER NOT NULL DEFAULT 0,
271
+ output_tokens INTEGER NOT NULL DEFAULT 0,
272
+ subagent_type TEXT,
273
+ session_id TEXT,
274
+ agent_id TEXT,
275
+ agent_type TEXT,
276
+ ts INTEGER NOT NULL
277
+ );
278
+ ```
279
+
280
+ **Failure behavior**: everything is silent. If `node` is not on PATH, if the writer is missing, if SQLite fails — the hook returns exit 0 and the session proceeds normally. Errors are recorded in `~/.claude/telemetry-errors.log` when possible.
281
+
282
+ **Historical bug**: see `docs/brain/bugs/bash-source-hook-path.md`. The original script used `$CLAUDE_PROJECT_DIR` to locate the writer, which fails when the hook is registered globally — `$CLAUDE_PROJECT_DIR` resolves to whatever project is active at the moment, not to the harness repo. Fixed by switching to `$(dirname "${BASH_SOURCE[0]}")` in commit `b7397e2`.
283
+
284
+ ---
285
+
286
+ ## Current state — Pending scripts
287
+
288
+ The following scripts are **referenced** in `.claude/settings.json` but do **not yet exist** under `scripts/hooks/`. They are "configured but not implemented" hooks — create them as the feature demands:
289
+
290
+ - `scripts/hooks/pre-push-guard.sh`
291
+ - `scripts/hooks/block-test-deletion.sh`
292
+ - `scripts/hooks/post-edit-test-reminder.sh`
293
+ - `scripts/hooks/prompt-gate-reminder.sh`
294
+ - `scripts/hooks/stop-brain-reminder.sh`
295
+
296
+ While missing, Claude Code merely logs an execution error per hook and moves on — a `PreToolUse` with a missing script does **not** block (the runtime treats the missing-bash error as a config issue, not a gate failure).
297
+
298
+ To author any of them, follow the next section.
299
+
300
+ ---
301
+
302
+ ## How to add a new hook
303
+
304
+ 1. Edit `.claude/settings.json` and append a block to the desired event array:
305
+
306
+ ```json
307
+ "PreToolUse": [
308
+ {
309
+ "matcher": "Bash",
310
+ "hooks": [
311
+ {
312
+ "type": "command",
313
+ "command": "bash \"$CLAUDE_PROJECT_DIR\"/scripts/hooks/my-hook.sh"
314
+ }
315
+ ]
316
+ }
317
+ ]
318
+ ```
319
+
320
+ 2. Create the script at `scripts/hooks/my-hook.sh`:
321
+
322
+ ```bash
323
+ #!/usr/bin/env bash
324
+ set -uo pipefail
325
+
326
+ # Read JSON payload from stdin
327
+ payload=$(cat)
328
+
329
+ # Extract relevant field (depends on event)
330
+ command=$(echo "$payload" | jq -r '.command // empty')
331
+
332
+ # Gate logic
333
+ if [[ "$command" =~ rm.*-rf ]]; then
334
+ echo "ERROR: rm -rf blocked by hook" >&2
335
+ exit 1
336
+ fi
337
+
338
+ exit 0
339
+ ```
340
+
341
+ 3. Make the script executable (POSIX):
342
+
343
+ ```bash
344
+ chmod +x scripts/hooks/my-hook.sh
345
+ ```
346
+
347
+ 4. Test by invoking manually with a sample payload:
348
+
349
+ ```bash
350
+ echo '{"command":"rm -rf /"}' | bash scripts/hooks/my-hook.sh
351
+ echo "exit code: $?"
352
+ ```
353
+
354
+ 5. Start a new Claude Code session (hooks are loaded at startup). Trigger the target tool and observe behavior.
355
+
356
+ ---
357
+
358
+ ## Common pitfalls
359
+
360
+ ### 1. Always start with shebang + `set -uo pipefail`
361
+
362
+ ```bash
363
+ #!/usr/bin/env bash
364
+ set -uo pipefail
365
+ ```
366
+
367
+ Without `-u` the script silently tolerates undefined variables; without `pipefail` pipe failures stay invisible. **Do not use `set -e`** in hooks — exit code is your gate and you want explicit control.
368
+
369
+ ### 2. Exit 0 vs exit != 0
370
+
371
+ - `exit 0` on any event = does not block.
372
+ - `exit != 0` on **PreToolUse** = cancels the tool execution (gate).
373
+ - `exit != 0` on **PostToolUse**, **Stop**, **Notification** = informational only; the tool already ran.
374
+ - `exit != 0` on **UserPromptSubmit** = cancels sending the prompt to the model (hard gate).
375
+
376
+ ### 3. Path resolution — global vs project
377
+
378
+ **Global hooks** (`~/.claude/settings.json`): NEVER use `$CLAUDE_PROJECT_DIR` to point to the hook's own artifacts. That variable resolves to the **currently active project**, which may not contain the script. Use `$(dirname "${BASH_SOURCE[0]}")` (the running Bash script's own directory) or a hardcoded absolute path.
379
+
380
+ **Project hooks** (`.claude/settings.json`): `$CLAUDE_PROJECT_DIR` correctly resolves to the repo root, so it is safe.
381
+
382
+ History: the `bash-source-hook-path.md` bug (P1, fixed in `b7397e2`) was precisely this — the global `subagent-telemetry.sh` used `$CLAUDE_PROJECT_DIR` and the writer was never found.
383
+
384
+ ### 4. Windows-friendly
385
+
386
+ Claude Code on Windows runs hooks via Git Bash or WSL. To stay portable:
387
+
388
+ - Use forward slashes in paths whenever possible
389
+ - Do not call CMD/PowerShell utilities — POSIX only (`bash`, `jq`, `node`, `git`)
390
+ - Test in Git Bash before committing
391
+ - Windows absolute paths work if prefixed with `/c/...` (Git Bash) or `C:\\...` escaped
392
+
393
+ ### 5. JSON payload via stdin
394
+
395
+ Most events deliver a JSON payload on stdin. Parse with `jq`:
396
+
397
+ ```bash
398
+ payload=$(cat)
399
+ file_path=$(echo "$payload" | jq -r '.file_path // empty')
400
+ command=$(echo "$payload" | jq -r '.command // empty')
401
+ ```
402
+
403
+ Always use `// empty` in `jq` to avoid the literal `"null"` string when the field is missing.
404
+
405
+ ### 6. Debug logs do not reach the user
406
+
407
+ Stderr is silenced in Claude Code for non-blocking events. For persistent debugging, write to a file:
408
+
409
+ ```bash
410
+ echo "DEBUG: $(date) - hook fired with $file_path" >> /tmp/my-hook.log
411
+ ```
412
+
413
+ ---
414
+
415
+ ## Cross-references
416
+
417
+ - [Honcho memory](honcho-memory) — `UserPromptSubmit` and `Stop` hooks of the honcho-memory skill
418
+ - [Architecture overview](architecture-overview) — how hooks fit into the broader pipeline
419
+ - `docs/brain/bugs/bash-source-hook-path.md` — historical path resolution bug
420
+ - `scripts/hooks/telemetry-writer.js` — SQLite writer that feeds the telemetry dashboard