@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.
- package/.claude/agents/analyst.md +198 -0
- package/.claude/agents/backend-developer.md +126 -0
- package/.claude/agents/brain-keeper.md +229 -0
- package/.claude/agents/code-reviewer.md +181 -0
- package/.claude/agents/database-engineer.md +94 -0
- package/.claude/agents/devops-engineer.md +141 -0
- package/.claude/agents/frontend-developer.md +97 -0
- package/.claude/agents/gate-keeper.md +118 -0
- package/.claude/agents/migrator.md +291 -0
- package/.claude/agents/mobile-developer.md +80 -0
- package/.claude/agents/n8n-specialist.md +94 -0
- package/.claude/agents/product-owner.md +115 -0
- package/.claude/agents/qa-engineer.md +232 -0
- package/.claude/agents/release-engineer.md +204 -0
- package/.claude/agents/scaffold.md +87 -0
- package/.claude/agents/security-engineer.md +199 -0
- package/.claude/agents/sprint-runner.md +44 -0
- package/.claude/agents/stack-resolver.md +84 -0
- package/.claude/agents/tech-lead.md +182 -0
- package/.claude/agents/update-template.md +54 -0
- package/.claude/agents/ux-designer.md +118 -0
- package/.claude/settings.json +44 -0
- package/.claude/skills/README.md +332 -0
- package/.claude/skills/active-project/SKILL.md +129 -0
- package/.claude/skills/api-integration-test/SKILL.md +64 -0
- package/.claude/skills/auto-test-guard/SKILL.md +237 -0
- package/.claude/skills/auto-test-guard/resources/backend-tests.md +20 -0
- package/.claude/skills/auto-test-guard/resources/e2e-tests.md +24 -0
- package/.claude/skills/auto-test-guard/resources/execution-report.md +49 -0
- package/.claude/skills/auto-test-guard/resources/frontend-tests.md +18 -0
- package/.claude/skills/auto-test-guard/resources/initial-setup.md +108 -0
- package/.claude/skills/auto-test-guard/resources/run-suite.md +48 -0
- package/.claude/skills/auto-test-guard/resources/senior-gate.md +19 -0
- package/.claude/skills/brain-keeper/SKILL.md +60 -0
- package/.claude/skills/brain-keeper/obsidian/app.json +9 -0
- package/.claude/skills/brain-keeper/obsidian/appearance.json +4 -0
- package/.claude/skills/brain-keeper/obsidian/core-plugins.json +20 -0
- package/.claude/skills/brain-keeper/obsidian/daily-notes.json +5 -0
- package/.claude/skills/brain-keeper/obsidian/graph.json +32 -0
- package/.claude/skills/brain-keeper/obsidian/snippets/folder-colors.css +90 -0
- package/.claude/skills/brain-keeper/obsidian/templates.json +5 -0
- package/.claude/skills/brain-keeper/templates/README.md +51 -0
- package/.claude/skills/brain-keeper/templates/adr.md +40 -0
- package/.claude/skills/brain-keeper/templates/bug.md +35 -0
- package/.claude/skills/brain-keeper/templates/daily.md +38 -0
- package/.claude/skills/brain-keeper/templates/feature.md +62 -0
- package/.claude/skills/brain-keeper/templates/meeting.md +34 -0
- package/.claude/skills/brain-keeper/templates/tech-debt.md +21 -0
- package/.claude/skills/caveman/SKILL.md +187 -0
- package/.claude/skills/create-stack-pack/SKILL.md +281 -0
- package/.claude/skills/grill-me/SKILL.md +79 -0
- package/.claude/skills/honcho-memory/SKILL.md +207 -0
- package/.claude/skills/honcho-memory/docs/api-endpoints-verified.md +75 -0
- package/.claude/skills/honcho-memory/hooks/on-prompt-submit.js +221 -0
- package/.claude/skills/honcho-memory/hooks/on-stop.js +193 -0
- package/.claude/skills/honcho-memory/lib/honcho-client.js +363 -0
- package/.claude/skills/honcho-memory/lib/memory-injector.js +93 -0
- package/.claude/skills/honcho-memory/package.json +32 -0
- package/.claude/skills/honcho-memory/scripts/cli.js +370 -0
- package/.claude/skills/honcho-memory/scripts/setup.js +109 -0
- package/.claude/skills/honcho-memory/tests/t001-api-endpoints-verified.test.js +89 -0
- package/.claude/skills/honcho-memory/tests/t002-structure.test.js +97 -0
- package/.claude/skills/honcho-memory/tests/t003-honcho-client.test.js +162 -0
- package/.claude/skills/honcho-memory/tests/t004-soft-delete.test.js +259 -0
- package/.claude/skills/honcho-memory/tests/t005-memory-injector.test.js +175 -0
- package/.claude/skills/honcho-memory/tests/t006-on-prompt-submit.test.js +215 -0
- package/.claude/skills/honcho-memory/tests/t007-on-stop.test.js +165 -0
- package/.claude/skills/honcho-memory/tests/t008-cli.test.js +214 -0
- package/.claude/skills/honcho-memory/tests/t009-setup.test.js +232 -0
- package/.claude/skills/honcho-memory/tests/t010-skill-md.test.js +114 -0
- package/.claude/skills/honcho-memory/tests/t011-settings-hooks.test.js +105 -0
- package/.claude/skills/honcho-memory/tests/t012-docs-update.test.js +106 -0
- package/.claude/skills/honcho-memory/tests/t013-smoke-e2e.test.js +90 -0
- package/.claude/skills/pair-debug/SKILL.md +288 -0
- package/.claude/skills/prd-ready-check/SKILL.md +58 -0
- package/.claude/skills/project-manager/SKILL.md +167 -0
- package/.claude/skills/quality-standards/SKILL.md +201 -0
- package/.claude/skills/quick-feature/SKILL.md +264 -0
- package/.claude/skills/run-sprint/SKILL.md +342 -0
- package/.claude/skills/scaffold/SKILL.md +58 -0
- package/.claude/skills/stack-discovery/SKILL.md +159 -0
- package/.claude/skills/test-coverage-auditor/SKILL.md +59 -0
- package/.claude/skills/to-issues/SKILL.md +163 -0
- package/.claude/skills/to-prd/SKILL.md +130 -0
- package/.claude/skills/update-template/SKILL.md +254 -0
- package/.claude/stacks/CODEOWNERS +30 -0
- package/.claude/stacks/README.md +88 -0
- package/.claude/stacks/_template.md +116 -0
- package/.claude/stacks/java/spring-boot-3.md +376 -0
- package/.claude/stacks/java/spring-boot-4.md +438 -0
- package/.claude/stacks/typescript/angular-18.md +420 -0
- package/.claude/stacks/typescript/angular-19.md +397 -0
- package/.claude/stacks/typescript/angular-21.md +494 -0
- package/CLAUDE.md +453 -0
- package/README.md +391 -0
- package/bin/cli.js +773 -0
- package/bin/lib/backup.js +62 -0
- package/bin/lib/detect-stack.js +476 -0
- package/bin/lib/help.js +233 -0
- package/bin/lib/identity.js +108 -0
- package/bin/lib/local-dir.js +69 -0
- package/bin/lib/manifest.js +236 -0
- package/bin/lib/sync-all.js +394 -0
- package/bin/lib/version-check.js +398 -0
- package/dashboard/db.js +199 -0
- package/dashboard/package.json +22 -0
- package/dashboard/public/app.js +709 -0
- package/dashboard/public/content/docs/agents-reference.en.md +911 -0
- package/dashboard/public/content/docs/architecture-overview.en.md +260 -0
- package/dashboard/public/content/docs/autonomy-matrix.en.md +186 -0
- package/dashboard/public/content/docs/git-flow.en.md +525 -0
- package/dashboard/public/content/docs/honcho-memory.en.md +394 -0
- package/dashboard/public/content/docs/hooks-reference.en.md +420 -0
- package/dashboard/public/content/docs/pipeline.en.md +400 -0
- package/dashboard/public/content/docs/quality-gate.en.md +315 -0
- package/dashboard/public/content/docs/skills-reference.en.md +500 -0
- package/dashboard/public/content/docs/stack-rules.en.md +362 -0
- package/dashboard/public/content/docs/troubleshooting.en.md +637 -0
- package/dashboard/public/content/manifest.json +102 -0
- package/dashboard/public/content/manual/backend.en.md +1138 -0
- package/dashboard/public/content/manual/existing-project.en.md +831 -0
- package/dashboard/public/content/manual/frontend.en.md +1065 -0
- package/dashboard/public/content/manual/fullstack.en.md +1508 -0
- package/dashboard/public/content/manual/mobile.en.md +866 -0
- package/dashboard/public/index.html +108 -0
- package/dashboard/public/style.css +610 -0
- package/dashboard/public/vendor/marked.min.js +69 -0
- package/dashboard/rtk.js +143 -0
- package/dashboard/server-app.js +403 -0
- package/dashboard/server.js +104 -0
- package/dashboard/test/sprint1.test.js +406 -0
- package/dashboard/test/sprint2.test.js +571 -0
- package/dashboard/test/sprint3.test.js +560 -0
- package/package.json +33 -0
- package/scripts/hooks/subagent-telemetry.sh +14 -0
- package/scripts/hooks/telemetry-writer.js +250 -0
- 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
|