@goodfoot/agent-hooks 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/README.md +137 -0
- package/dist/agents/antigravity/events.js +42 -0
- package/dist/agents/antigravity/hooks.js +59 -0
- package/dist/agents/antigravity/index.js +28 -0
- package/dist/agents/antigravity/outputs.js +81 -0
- package/dist/agents/antigravity/transport.js +84 -0
- package/dist/agents/antigravity/types.js +11 -0
- package/dist/agents/claude-code/env.js +27 -0
- package/dist/agents/claude-code/events.js +87 -0
- package/dist/agents/claude-code/hooks.js +1000 -0
- package/dist/agents/claude-code/index.js +57 -0
- package/dist/agents/claude-code/outputs.js +579 -0
- package/dist/agents/claude-code/tool-helpers.js +840 -0
- package/dist/agents/claude-code/transport.js +254 -0
- package/dist/agents/claude-code/types.js +11 -0
- package/dist/agents/codex/cli-support.js +318 -0
- package/dist/agents/codex/constants.js +29 -0
- package/dist/agents/codex/events.js +68 -0
- package/dist/agents/codex/hooks.js +93 -0
- package/dist/agents/codex/index.js +21 -0
- package/dist/agents/codex/outputs.js +189 -0
- package/dist/agents/codex/scaffold.js +273 -0
- package/dist/agents/codex/transport.js +139 -0
- package/dist/agents/codex/types.js +1 -0
- package/dist/cli.js +1357 -0
- package/dist/constants.js +39 -0
- package/dist/core/define-hook.js +61 -0
- package/dist/core/env.js +186 -0
- package/dist/core/logger.js +508 -0
- package/dist/core/stdin.js +38 -0
- package/dist/core/transport.js +231 -0
- package/dist/core/types.js +10 -0
- package/dist/index.js +17 -0
- package/dist/scaffold.js +512 -0
- package/package.json +61 -0
- package/types/agents/antigravity/events.d.ts +50 -0
- package/types/agents/antigravity/hooks.d.ts +76 -0
- package/types/agents/antigravity/index.d.ts +27 -0
- package/types/agents/antigravity/outputs.d.ts +107 -0
- package/types/agents/antigravity/transport.d.ts +47 -0
- package/types/agents/antigravity/types.d.ts +58 -0
- package/types/agents/claude-code/env.d.ts +27 -0
- package/types/agents/claude-code/events.d.ts +69 -0
- package/types/agents/claude-code/hooks.d.ts +1182 -0
- package/types/agents/claude-code/index.d.ts +23 -0
- package/types/agents/claude-code/outputs.d.ts +1160 -0
- package/types/agents/claude-code/tool-helpers.d.ts +807 -0
- package/types/agents/claude-code/transport.d.ts +119 -0
- package/types/agents/claude-code/types.d.ts +557 -0
- package/types/agents/codex/cli-support.d.ts +105 -0
- package/types/agents/codex/constants.d.ts +10 -0
- package/types/agents/codex/events.d.ts +63 -0
- package/types/agents/codex/hooks.d.ts +135 -0
- package/types/agents/codex/index.d.ts +19 -0
- package/types/agents/codex/outputs.d.ts +190 -0
- package/types/agents/codex/scaffold.d.ts +14 -0
- package/types/agents/codex/transport.d.ts +74 -0
- package/types/agents/codex/types.d.ts +131 -0
- package/types/cli.d.ts +315 -0
- package/types/constants.d.ts +9 -0
- package/types/core/define-hook.d.ts +39 -0
- package/types/core/env.d.ts +150 -0
- package/types/core/logger.d.ts +476 -0
- package/types/core/stdin.d.ts +21 -0
- package/types/core/transport.d.ts +131 -0
- package/types/core/types.d.ts +137 -0
- package/types/index.d.ts +18 -0
- package/types/scaffold.d.ts +46 -0
|
@@ -0,0 +1,1000 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook factory functions for Claude Code hooks.
|
|
3
|
+
*
|
|
4
|
+
* Provides typed factory functions for all 30 hook types that handle:
|
|
5
|
+
* - Input type narrowing based on hook event type
|
|
6
|
+
* - Output type enforcement via return types
|
|
7
|
+
* - Error wrapping with automatic logging
|
|
8
|
+
* - Logger context injection
|
|
9
|
+
*
|
|
10
|
+
* Each factory accepts a HookConfig with optional matcher and timeout settings,
|
|
11
|
+
* and returns a function that the runtime invokes when the hook file executes.
|
|
12
|
+
* @module
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* import { preToolUseHook, preToolUseOutput } from '@goodfoot/agent-hooks/claude-code';
|
|
16
|
+
*
|
|
17
|
+
* export default preToolUseHook({ matcher: 'Bash' }, async (input, { logger }) => {
|
|
18
|
+
* logger.info('Processing Bash command');
|
|
19
|
+
* return preToolUseOutput({ allow: true });
|
|
20
|
+
* });
|
|
21
|
+
* ```
|
|
22
|
+
* @see https://code.claude.com/docs/en/hooks
|
|
23
|
+
*/
|
|
24
|
+
import { defineHook } from "../../core/define-hook.js";
|
|
25
|
+
import { persistEnvVar, persistEnvVars } from "../../core/env.js";
|
|
26
|
+
import { logger } from "../../core/logger.js";
|
|
27
|
+
import { ADVISORY_EVENTS } from "./events.js";
|
|
28
|
+
// ============================================================================
|
|
29
|
+
// Generic Factory
|
|
30
|
+
// ============================================================================
|
|
31
|
+
/**
|
|
32
|
+
* The runtime policy gate injected into every Claude Code factory: rejects
|
|
33
|
+
* `unexpectedError: "continue"` at factory-call time for any event not on
|
|
34
|
+
* the advisory allow-list ({@link ADVISORY_EVENTS}). Every other policy
|
|
35
|
+
* value (including undefined, meaning the default `"error"`) is accepted
|
|
36
|
+
* for every event. {@link defineHook} fails closed — throws instead of
|
|
37
|
+
* creating the hook — when this gate returns false.
|
|
38
|
+
*/
|
|
39
|
+
const advisoryPolicyGate = (eventName, policy) => policy !== "continue" || ADVISORY_EVENTS.includes(eventName);
|
|
40
|
+
/**
|
|
41
|
+
* Builds the handler context for a SessionStart hook: the extended context
|
|
42
|
+
* carries the env-persistence utilities alongside the logger. Bound at
|
|
43
|
+
* factory time via {@link defineHook}'s `createContext` seam.
|
|
44
|
+
*/
|
|
45
|
+
function createSessionStartContext() {
|
|
46
|
+
return { logger, persistEnvVar, persistEnvVars };
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Creates a hook function for a specific hook type on the shared core.
|
|
50
|
+
*
|
|
51
|
+
* This is the internal implementation used by all typed factories. It binds
|
|
52
|
+
* the event name, injects the advisory allow-list policy gate, and attaches
|
|
53
|
+
* the SessionStart-specific context factory where applicable.
|
|
54
|
+
* @param hookEventName - The hook event name
|
|
55
|
+
* @param config - Hook configuration
|
|
56
|
+
* @param handler - The handler function to wrap
|
|
57
|
+
* @returns A wrapped hook function carrying its metadata for the driver
|
|
58
|
+
* @internal
|
|
59
|
+
*/
|
|
60
|
+
function createHookFunction(hookEventName, config, handler) {
|
|
61
|
+
const isSessionStart = hookEventName === "SessionStart";
|
|
62
|
+
return defineHook(hookEventName, isSessionStart ? { ...config, createContext: createSessionStartContext } : config, handler, advisoryPolicyGate);
|
|
63
|
+
}
|
|
64
|
+
/** @inheritdoc */
|
|
65
|
+
export function preToolUseHook(config, handler) {
|
|
66
|
+
return createHookFunction("PreToolUse", config, handler);
|
|
67
|
+
}
|
|
68
|
+
/** @inheritdoc */
|
|
69
|
+
export function postToolUseHook(config, handler) {
|
|
70
|
+
return createHookFunction("PostToolUse", config, handler);
|
|
71
|
+
}
|
|
72
|
+
/** @inheritdoc */
|
|
73
|
+
export function postToolUseFailureHook(config, handler) {
|
|
74
|
+
return createHookFunction("PostToolUseFailure", config, handler);
|
|
75
|
+
}
|
|
76
|
+
// ============================================================================
|
|
77
|
+
// PostToolBatch Hook Factory
|
|
78
|
+
// ============================================================================
|
|
79
|
+
/**
|
|
80
|
+
* Creates a PostToolBatch hook handler.
|
|
81
|
+
*
|
|
82
|
+
* PostToolBatch hooks fire exactly once after every tool call in a batch has
|
|
83
|
+
* resolved, before the next model request. Unlike PostToolUse — which fires per
|
|
84
|
+
* tool and may run concurrently for parallel tool calls — PostToolBatch receives
|
|
85
|
+
* the full batch via `input.tool_calls`, allowing you to:
|
|
86
|
+
* - Inspect or summarize all tool calls in a single turn together
|
|
87
|
+
* - Inject additional context once per batch instead of once per tool
|
|
88
|
+
*
|
|
89
|
+
* **Matcher**: No matcher support - fires once per batch
|
|
90
|
+
* @param config - Hook configuration with optional timeout (matcher is ignored)
|
|
91
|
+
* @param handler - The handler function to execute
|
|
92
|
+
* @returns A hook function that can be exported as the default export
|
|
93
|
+
* @example
|
|
94
|
+
* ```typescript
|
|
95
|
+
* import { postToolBatchHook, postToolBatchOutput } from '@goodfoot/agent-hooks/claude-code';
|
|
96
|
+
*
|
|
97
|
+
* export default postToolBatchHook({}, async (input, { logger }) => {
|
|
98
|
+
* logger.info('Tool batch completed', { count: input.tool_calls.length });
|
|
99
|
+
*
|
|
100
|
+
* return postToolBatchOutput({
|
|
101
|
+
* hookSpecificOutput: {
|
|
102
|
+
* additionalContext: `Reviewed ${input.tool_calls.length} tool calls`
|
|
103
|
+
* }
|
|
104
|
+
* });
|
|
105
|
+
* });
|
|
106
|
+
* ```
|
|
107
|
+
* @see https://code.claude.com/docs/en/hooks#posttoolbatch
|
|
108
|
+
*/
|
|
109
|
+
export function postToolBatchHook(config, handler) {
|
|
110
|
+
return createHookFunction("PostToolBatch", config, handler);
|
|
111
|
+
}
|
|
112
|
+
// ============================================================================
|
|
113
|
+
// Notification Hook Factory
|
|
114
|
+
// ============================================================================
|
|
115
|
+
/**
|
|
116
|
+
* Creates a Notification hook handler.
|
|
117
|
+
*
|
|
118
|
+
* Notification hooks fire when Claude Code sends a notification, allowing you to:
|
|
119
|
+
* - Forward notifications to external systems
|
|
120
|
+
* - Log important events
|
|
121
|
+
* - Trigger custom alerting
|
|
122
|
+
*
|
|
123
|
+
* **Matcher**: Matches against `notification_type`
|
|
124
|
+
* @param config - Hook configuration with optional matcher and timeout
|
|
125
|
+
* @param handler - The handler function to execute
|
|
126
|
+
* @returns A hook function that can be exported as the default export
|
|
127
|
+
* @example
|
|
128
|
+
* ```typescript
|
|
129
|
+
* import { notificationHook, notificationOutput } from '@goodfoot/agent-hooks/claude-code';
|
|
130
|
+
*
|
|
131
|
+
* // Forward notifications to Slack
|
|
132
|
+
* export default notificationHook({}, async (input, { logger }) => {
|
|
133
|
+
* logger.info('Notification received', {
|
|
134
|
+
* type: input.notification_type,
|
|
135
|
+
* title: input.title
|
|
136
|
+
* });
|
|
137
|
+
*
|
|
138
|
+
* await sendSlackMessage(input.title ?? 'Notification', input.message);
|
|
139
|
+
*
|
|
140
|
+
* return notificationOutput({});
|
|
141
|
+
* });
|
|
142
|
+
* ```
|
|
143
|
+
* @see https://code.claude.com/docs/en/hooks#notification
|
|
144
|
+
*/
|
|
145
|
+
export function notificationHook(config, handler) {
|
|
146
|
+
return createHookFunction("Notification", config, handler);
|
|
147
|
+
}
|
|
148
|
+
// ============================================================================
|
|
149
|
+
// UserPromptSubmit Hook Factory
|
|
150
|
+
// ============================================================================
|
|
151
|
+
/**
|
|
152
|
+
* Creates a UserPromptSubmit hook handler.
|
|
153
|
+
*
|
|
154
|
+
* UserPromptSubmit hooks fire when a user submits a prompt, allowing you to:
|
|
155
|
+
* - Add additional context or instructions
|
|
156
|
+
* - Log user interactions
|
|
157
|
+
* - Validate or transform prompts
|
|
158
|
+
*
|
|
159
|
+
* **Matcher**: No matcher support - fires on all prompt submissions
|
|
160
|
+
* @param config - Hook configuration with optional timeout (matcher is ignored)
|
|
161
|
+
* @param handler - The handler function to execute
|
|
162
|
+
* @returns A hook function that can be exported as the default export
|
|
163
|
+
* @example
|
|
164
|
+
* ```typescript
|
|
165
|
+
* import { userPromptSubmitHook, userPromptSubmitOutput } from '@goodfoot/agent-hooks/claude-code';
|
|
166
|
+
*
|
|
167
|
+
* // Add project context to every prompt
|
|
168
|
+
* export default userPromptSubmitHook({}, async (input, { logger }) => {
|
|
169
|
+
* logger.debug('User prompt submitted', { promptLength: input.prompt.length });
|
|
170
|
+
*
|
|
171
|
+
* const projectContext = await getProjectContext();
|
|
172
|
+
*
|
|
173
|
+
* return userPromptSubmitOutput({
|
|
174
|
+
* additionalContext: projectContext
|
|
175
|
+
* });
|
|
176
|
+
* });
|
|
177
|
+
* ```
|
|
178
|
+
* @see https://code.claude.com/docs/en/hooks#userpromptsubmit
|
|
179
|
+
*/
|
|
180
|
+
export function userPromptSubmitHook(config, handler) {
|
|
181
|
+
return createHookFunction("UserPromptSubmit", config, handler);
|
|
182
|
+
}
|
|
183
|
+
// ============================================================================
|
|
184
|
+
// UserPromptExpansion Hook Factory
|
|
185
|
+
// ============================================================================
|
|
186
|
+
/**
|
|
187
|
+
* Creates a UserPromptExpansion hook handler.
|
|
188
|
+
*
|
|
189
|
+
* UserPromptExpansion hooks fire when a user prompt is expanded from a slash
|
|
190
|
+
* command or MCP prompt, allowing you to:
|
|
191
|
+
* - Add context based on the command being invoked
|
|
192
|
+
* - Log slash command and MCP prompt usage
|
|
193
|
+
* - Observe prompt expansion events
|
|
194
|
+
*
|
|
195
|
+
* **Matcher**: No matcher support - fires on all prompt expansions
|
|
196
|
+
* @param config - Hook configuration with optional timeout (matcher is ignored)
|
|
197
|
+
* @param handler - The handler function to execute
|
|
198
|
+
* @returns A hook function that can be exported as the default export
|
|
199
|
+
* @example
|
|
200
|
+
* ```typescript
|
|
201
|
+
* import { userPromptExpansionHook, userPromptExpansionOutput } from '@goodfoot/agent-hooks/claude-code';
|
|
202
|
+
*
|
|
203
|
+
* // Add context when a slash command is invoked
|
|
204
|
+
* export default userPromptExpansionHook({}, async (input, { logger }) => {
|
|
205
|
+
* logger.debug('Prompt expanded', { type: input.expansion_type, command: input.command_name });
|
|
206
|
+
*
|
|
207
|
+
* return userPromptExpansionOutput({
|
|
208
|
+
* hookSpecificOutput: {
|
|
209
|
+
* additionalContext: `Command: ${input.command_name}`
|
|
210
|
+
* }
|
|
211
|
+
* });
|
|
212
|
+
* });
|
|
213
|
+
* ```
|
|
214
|
+
* @see https://code.claude.com/docs/en/hooks#userpromptexpansion
|
|
215
|
+
*/
|
|
216
|
+
export function userPromptExpansionHook(config, handler) {
|
|
217
|
+
return createHookFunction("UserPromptExpansion", config, handler);
|
|
218
|
+
}
|
|
219
|
+
// ============================================================================
|
|
220
|
+
// SessionStart Hook Factory
|
|
221
|
+
// ============================================================================
|
|
222
|
+
/**
|
|
223
|
+
* Creates a SessionStart hook handler.
|
|
224
|
+
*
|
|
225
|
+
* SessionStart hooks fire when a Claude Code session starts or restarts,
|
|
226
|
+
* allowing you to:
|
|
227
|
+
* - Initialize session state
|
|
228
|
+
* - Inject context or instructions
|
|
229
|
+
* - Persist environment variables for subsequent bash commands
|
|
230
|
+
* - Set up logging or monitoring
|
|
231
|
+
*
|
|
232
|
+
* **Matcher**: Matches against `source` ('startup', 'resume', 'clear', 'compact')
|
|
233
|
+
*
|
|
234
|
+
* **Context**: SessionStart hooks receive an extended context with `persistEnvVar`
|
|
235
|
+
* and `persistEnvVars` functions for setting environment variables.
|
|
236
|
+
* @param config - Hook configuration with optional matcher and timeout
|
|
237
|
+
* @param handler - The handler function to execute
|
|
238
|
+
* @returns A hook function that can be exported as the default export
|
|
239
|
+
* @example
|
|
240
|
+
* ```typescript
|
|
241
|
+
* import { sessionStartHook, sessionStartOutput } from '@goodfoot/agent-hooks/claude-code';
|
|
242
|
+
*
|
|
243
|
+
* // Persist environment variables for the session
|
|
244
|
+
* export default sessionStartHook({ matcher: 'startup' }, async (input, { logger, persistEnvVar }) => {
|
|
245
|
+
* logger.info('New session started', {
|
|
246
|
+
* sessionId: input.session_id,
|
|
247
|
+
* cwd: input.cwd
|
|
248
|
+
* });
|
|
249
|
+
*
|
|
250
|
+
* // Set environment variables for all subsequent bash commands
|
|
251
|
+
* persistEnvVar('NODE_ENV', 'development');
|
|
252
|
+
* persistEnvVar('DEBUG', 'true');
|
|
253
|
+
*
|
|
254
|
+
* return sessionStartOutput({});
|
|
255
|
+
* });
|
|
256
|
+
* ```
|
|
257
|
+
* @example
|
|
258
|
+
* ```typescript
|
|
259
|
+
* // Set multiple environment variables at once
|
|
260
|
+
* export default sessionStartHook({}, async (input, { persistEnvVars }) => {
|
|
261
|
+
* persistEnvVars({
|
|
262
|
+
* NODE_ENV: 'production',
|
|
263
|
+
* API_KEY: 'secret',
|
|
264
|
+
* DEBUG: 'false'
|
|
265
|
+
* });
|
|
266
|
+
*
|
|
267
|
+
* return sessionStartOutput({});
|
|
268
|
+
* });
|
|
269
|
+
* ```
|
|
270
|
+
* @see https://code.claude.com/docs/en/hooks#sessionstart
|
|
271
|
+
*/
|
|
272
|
+
export function sessionStartHook(config, handler) {
|
|
273
|
+
return createHookFunction("SessionStart", config, handler);
|
|
274
|
+
}
|
|
275
|
+
// ============================================================================
|
|
276
|
+
// SessionEnd Hook Factory
|
|
277
|
+
// ============================================================================
|
|
278
|
+
/**
|
|
279
|
+
* Creates a SessionEnd hook handler.
|
|
280
|
+
*
|
|
281
|
+
* SessionEnd hooks fire when a Claude Code session ends, allowing you to:
|
|
282
|
+
* - Clean up session resources
|
|
283
|
+
* - Log session metrics
|
|
284
|
+
* - Persist session state
|
|
285
|
+
*
|
|
286
|
+
* **Matcher**: Matches against `reason` (the exit reason string)
|
|
287
|
+
* @param config - Hook configuration with optional matcher and timeout
|
|
288
|
+
* @param handler - The handler function to execute
|
|
289
|
+
* @returns A hook function that can be exported as the default export
|
|
290
|
+
* @example
|
|
291
|
+
* ```typescript
|
|
292
|
+
* import { sessionEndHook, sessionEndOutput } from '@goodfoot/agent-hooks/claude-code';
|
|
293
|
+
*
|
|
294
|
+
* // Log session end and clean up
|
|
295
|
+
* export default sessionEndHook({}, async (input, { logger }) => {
|
|
296
|
+
* logger.info('Session ended', {
|
|
297
|
+
* sessionId: input.session_id,
|
|
298
|
+
* reason: input.reason
|
|
299
|
+
* });
|
|
300
|
+
*
|
|
301
|
+
* await cleanupSessionResources(input.session_id);
|
|
302
|
+
*
|
|
303
|
+
* return sessionEndOutput({});
|
|
304
|
+
* });
|
|
305
|
+
* ```
|
|
306
|
+
* @see https://code.claude.com/docs/en/hooks#sessionend
|
|
307
|
+
*/
|
|
308
|
+
export function sessionEndHook(config, handler) {
|
|
309
|
+
return createHookFunction("SessionEnd", config, handler);
|
|
310
|
+
}
|
|
311
|
+
// ============================================================================
|
|
312
|
+
// Stop Hook Factory
|
|
313
|
+
// ============================================================================
|
|
314
|
+
/**
|
|
315
|
+
* Creates a Stop hook handler.
|
|
316
|
+
*
|
|
317
|
+
* Stop hooks fire when Claude Code is about to stop, allowing you to:
|
|
318
|
+
* - Block the stop and require additional action
|
|
319
|
+
* - Confirm the user wants to stop
|
|
320
|
+
* - Clean up resources before stopping
|
|
321
|
+
*
|
|
322
|
+
* **Matcher**: No matcher support - fires on all stop events
|
|
323
|
+
* @param config - Hook configuration with optional timeout (matcher is ignored)
|
|
324
|
+
* @param handler - The handler function to execute
|
|
325
|
+
* @returns A hook function that can be exported as the default export
|
|
326
|
+
* @example
|
|
327
|
+
* ```typescript
|
|
328
|
+
* import { stopHook, stopOutput } from '@goodfoot/agent-hooks/claude-code';
|
|
329
|
+
*
|
|
330
|
+
* // Block stop if there are pending changes
|
|
331
|
+
* export default stopHook({}, async (input, { logger }) => {
|
|
332
|
+
* const pendingChanges = await checkPendingChanges();
|
|
333
|
+
*
|
|
334
|
+
* if (pendingChanges.length > 0) {
|
|
335
|
+
* logger.warn('Blocking stop due to pending changes', {
|
|
336
|
+
* count: pendingChanges.length
|
|
337
|
+
* });
|
|
338
|
+
*
|
|
339
|
+
* return stopOutput({
|
|
340
|
+
* decision: 'block',
|
|
341
|
+
* reason: `There are ${pendingChanges.length} uncommitted changes`,
|
|
342
|
+
* systemMessage: 'Please commit or discard changes before stopping'
|
|
343
|
+
* });
|
|
344
|
+
* }
|
|
345
|
+
*
|
|
346
|
+
* logger.info('Approving stop');
|
|
347
|
+
* return stopOutput({ decision: 'approve' });
|
|
348
|
+
* });
|
|
349
|
+
* ```
|
|
350
|
+
* @see https://code.claude.com/docs/en/hooks#stop
|
|
351
|
+
*/
|
|
352
|
+
export function stopHook(config, handler) {
|
|
353
|
+
return createHookFunction("Stop", config, handler);
|
|
354
|
+
}
|
|
355
|
+
// ============================================================================
|
|
356
|
+
// StopFailure Hook Factory
|
|
357
|
+
// ============================================================================
|
|
358
|
+
/**
|
|
359
|
+
* Creates a StopFailure hook handler.
|
|
360
|
+
*
|
|
361
|
+
* StopFailure hooks fire when Claude Code encounters an error while stopping
|
|
362
|
+
* (e.g., API errors, authentication failures, rate limits), allowing you to:
|
|
363
|
+
* - Log stop failure events and error details
|
|
364
|
+
* - Alert on unexpected session termination errors
|
|
365
|
+
* - Observe what error caused the failure
|
|
366
|
+
*
|
|
367
|
+
* **Matcher**: No matcher support - fires on all stop failure events
|
|
368
|
+
* @param config - Hook configuration with optional timeout (matcher is ignored)
|
|
369
|
+
* @param handler - The handler function to execute
|
|
370
|
+
* @returns A hook function that can be exported as the default export
|
|
371
|
+
* @example
|
|
372
|
+
* ```typescript
|
|
373
|
+
* import { stopFailureHook, stopFailureOutput } from '@goodfoot/agent-hooks/claude-code';
|
|
374
|
+
*
|
|
375
|
+
* export default stopFailureHook({}, async (input, { logger }) => {
|
|
376
|
+
* logger.error('Session stopped due to error', {
|
|
377
|
+
* error: input.error,
|
|
378
|
+
* details: input.error_details
|
|
379
|
+
* });
|
|
380
|
+
* return stopFailureOutput({});
|
|
381
|
+
* });
|
|
382
|
+
* ```
|
|
383
|
+
* @see https://code.claude.com/docs/en/hooks#stopfailure
|
|
384
|
+
*/
|
|
385
|
+
export function stopFailureHook(config, handler) {
|
|
386
|
+
return createHookFunction("StopFailure", config, handler);
|
|
387
|
+
}
|
|
388
|
+
// ============================================================================
|
|
389
|
+
// SubagentStart Hook Factory
|
|
390
|
+
// ============================================================================
|
|
391
|
+
/**
|
|
392
|
+
* Creates a SubagentStart hook handler.
|
|
393
|
+
*
|
|
394
|
+
* SubagentStart hooks fire when a subagent (Agent tool) starts, allowing you to:
|
|
395
|
+
* - Inject context for the subagent
|
|
396
|
+
* - Log subagent invocations
|
|
397
|
+
* - Configure subagent behavior
|
|
398
|
+
*
|
|
399
|
+
* **Matcher**: Matches against `agent_type` (e.g., 'explore', 'codebase-analysis')
|
|
400
|
+
* @param config - Hook configuration with optional matcher and timeout
|
|
401
|
+
* @param handler - The handler function to execute
|
|
402
|
+
* @returns A hook function that can be exported as the default export
|
|
403
|
+
* @example
|
|
404
|
+
* ```typescript
|
|
405
|
+
* import { subagentStartHook, subagentStartOutput } from '@goodfoot/agent-hooks/claude-code';
|
|
406
|
+
*
|
|
407
|
+
* // Add context for explore subagents
|
|
408
|
+
* export default subagentStartHook({ matcher: 'explore' }, async (input, { logger }) => {
|
|
409
|
+
* logger.info('Explore subagent starting', {
|
|
410
|
+
* agentId: input.agent_id,
|
|
411
|
+
* agentType: input.agent_type
|
|
412
|
+
* });
|
|
413
|
+
*
|
|
414
|
+
* return subagentStartOutput({
|
|
415
|
+
* additionalContext: 'Focus on finding patterns and conventions'
|
|
416
|
+
* });
|
|
417
|
+
* });
|
|
418
|
+
* ```
|
|
419
|
+
* @see https://code.claude.com/docs/en/hooks#subagentstart
|
|
420
|
+
*/
|
|
421
|
+
export function subagentStartHook(config, handler) {
|
|
422
|
+
return createHookFunction("SubagentStart", config, handler);
|
|
423
|
+
}
|
|
424
|
+
// ============================================================================
|
|
425
|
+
// SubagentStop Hook Factory
|
|
426
|
+
// ============================================================================
|
|
427
|
+
/**
|
|
428
|
+
* Creates a SubagentStop hook handler.
|
|
429
|
+
*
|
|
430
|
+
* SubagentStop hooks fire when a subagent completes or stops, allowing you to:
|
|
431
|
+
* - Block the subagent from stopping
|
|
432
|
+
* - Process subagent results
|
|
433
|
+
* - Clean up subagent resources
|
|
434
|
+
* - Log subagent completion
|
|
435
|
+
*
|
|
436
|
+
* **Matcher**: Matches against `agent_type` (e.g., 'explore', 'codebase-analysis')
|
|
437
|
+
* @param config - Hook configuration with optional matcher and timeout
|
|
438
|
+
* @param handler - The handler function to execute
|
|
439
|
+
* @returns A hook function that can be exported as the default export
|
|
440
|
+
* @example
|
|
441
|
+
* ```typescript
|
|
442
|
+
* import { subagentStopHook, subagentStopOutput } from '@goodfoot/agent-hooks/claude-code';
|
|
443
|
+
*
|
|
444
|
+
* // Block explore subagents if task incomplete
|
|
445
|
+
* export default subagentStopHook({ matcher: 'explore' }, async (input, { logger }) => {
|
|
446
|
+
* logger.info('Subagent stopping', {
|
|
447
|
+
* agentId: input.agent_id,
|
|
448
|
+
* agentType: input.agent_type
|
|
449
|
+
* });
|
|
450
|
+
*
|
|
451
|
+
* // Block if transcript shows incomplete work
|
|
452
|
+
* return subagentStopOutput({
|
|
453
|
+
* decision: 'block',
|
|
454
|
+
* reason: 'Please verify exploration is complete'
|
|
455
|
+
* });
|
|
456
|
+
* });
|
|
457
|
+
* ```
|
|
458
|
+
* @see https://code.claude.com/docs/en/hooks#subagentstop
|
|
459
|
+
*/
|
|
460
|
+
export function subagentStopHook(config, handler) {
|
|
461
|
+
return createHookFunction("SubagentStop", config, handler);
|
|
462
|
+
}
|
|
463
|
+
// ============================================================================
|
|
464
|
+
// PreCompact Hook Factory
|
|
465
|
+
// ============================================================================
|
|
466
|
+
/**
|
|
467
|
+
* Creates a PreCompact hook handler.
|
|
468
|
+
*
|
|
469
|
+
* PreCompact hooks fire before context compaction occurs, allowing you to:
|
|
470
|
+
* - Preserve important information before compaction
|
|
471
|
+
* - Log compaction events
|
|
472
|
+
* - Modify custom instructions for the compacted context
|
|
473
|
+
*
|
|
474
|
+
* **Matcher**: Matches against `trigger` ('manual', 'auto')
|
|
475
|
+
* @param config - Hook configuration with optional matcher and timeout
|
|
476
|
+
* @param handler - The handler function to execute
|
|
477
|
+
* @returns A hook function that can be exported as the default export
|
|
478
|
+
* @example
|
|
479
|
+
* ```typescript
|
|
480
|
+
* import { preCompactHook, preCompactOutput } from '@goodfoot/agent-hooks/claude-code';
|
|
481
|
+
*
|
|
482
|
+
* // Log compaction events and preserve context
|
|
483
|
+
* export default preCompactHook({}, async (input, { logger }) => {
|
|
484
|
+
* logger.info('Context compaction triggered', {
|
|
485
|
+
* trigger: input.trigger,
|
|
486
|
+
* hasCustomInstructions: input.custom_instructions !== null
|
|
487
|
+
* });
|
|
488
|
+
*
|
|
489
|
+
* return preCompactOutput({
|
|
490
|
+
* systemMessage: 'Remember: strict mode is enabled'
|
|
491
|
+
* });
|
|
492
|
+
* });
|
|
493
|
+
* ```
|
|
494
|
+
* @example
|
|
495
|
+
* ```typescript
|
|
496
|
+
* // Only handle manual compaction
|
|
497
|
+
* export default preCompactHook({ matcher: 'manual' }, async (input, { logger }) => {
|
|
498
|
+
* logger.info('Manual compaction requested');
|
|
499
|
+
* return preCompactOutput({});
|
|
500
|
+
* });
|
|
501
|
+
* ```
|
|
502
|
+
* @see https://code.claude.com/docs/en/hooks#precompact
|
|
503
|
+
*/
|
|
504
|
+
export function preCompactHook(config, handler) {
|
|
505
|
+
return createHookFunction("PreCompact", config, handler);
|
|
506
|
+
}
|
|
507
|
+
// ============================================================================
|
|
508
|
+
// PostCompact Hook Factory
|
|
509
|
+
// ============================================================================
|
|
510
|
+
/**
|
|
511
|
+
* Creates a PostCompact hook handler.
|
|
512
|
+
*
|
|
513
|
+
* PostCompact hooks fire after context compaction completes, allowing you to:
|
|
514
|
+
* - Observe the compaction summary and details
|
|
515
|
+
* - Log compaction events
|
|
516
|
+
* - React to the new compacted state
|
|
517
|
+
*
|
|
518
|
+
* **Matcher**: Matches against `trigger` ('manual', 'auto')
|
|
519
|
+
* @param config - Hook configuration with optional matcher and timeout
|
|
520
|
+
* @param handler - The handler function to execute
|
|
521
|
+
* @returns A hook function that can be exported as the default export
|
|
522
|
+
* @example
|
|
523
|
+
* ```typescript
|
|
524
|
+
* import { postCompactHook, postCompactOutput } from '@goodfoot/agent-hooks/claude-code';
|
|
525
|
+
*
|
|
526
|
+
* export default postCompactHook({}, async (input, { logger }) => {
|
|
527
|
+
* logger.info('Context compaction completed', {
|
|
528
|
+
* trigger: input.trigger,
|
|
529
|
+
* summary: input.compact_summary
|
|
530
|
+
* });
|
|
531
|
+
* return postCompactOutput({});
|
|
532
|
+
* });
|
|
533
|
+
* ```
|
|
534
|
+
* @see https://code.claude.com/docs/en/hooks#postcompact
|
|
535
|
+
*/
|
|
536
|
+
export function postCompactHook(config, handler) {
|
|
537
|
+
return createHookFunction("PostCompact", config, handler);
|
|
538
|
+
}
|
|
539
|
+
/** @inheritdoc */
|
|
540
|
+
export function permissionRequestHook(config, handler) {
|
|
541
|
+
return createHookFunction("PermissionRequest", config, handler);
|
|
542
|
+
}
|
|
543
|
+
// ============================================================================
|
|
544
|
+
// PermissionDenied Hook Factory
|
|
545
|
+
// ============================================================================
|
|
546
|
+
/**
|
|
547
|
+
* Creates a PermissionDenied hook handler.
|
|
548
|
+
*
|
|
549
|
+
* PermissionDenied hooks fire when a permission request is denied (either by the
|
|
550
|
+
* user or by a PermissionRequest hook), allowing you to:
|
|
551
|
+
* - Log permission denials for auditing
|
|
552
|
+
* - React to denied tool executions
|
|
553
|
+
* - Optionally request a retry via the output
|
|
554
|
+
*
|
|
555
|
+
* **Matcher**: Matches against `tool_name`
|
|
556
|
+
* @param config - Hook configuration with optional matcher and timeout
|
|
557
|
+
* @param handler - The handler function to execute
|
|
558
|
+
* @returns A hook function that can be exported as the default export
|
|
559
|
+
* @example
|
|
560
|
+
* ```typescript
|
|
561
|
+
* import { permissionDeniedHook, permissionDeniedOutput } from '@goodfoot/agent-hooks/claude-code';
|
|
562
|
+
*
|
|
563
|
+
* // Log all permission denials
|
|
564
|
+
* export default permissionDeniedHook({}, async (input, { logger }) => {
|
|
565
|
+
* logger.warn('Permission denied', {
|
|
566
|
+
* toolName: input.tool_name,
|
|
567
|
+
* reason: input.reason
|
|
568
|
+
* });
|
|
569
|
+
* return permissionDeniedOutput({});
|
|
570
|
+
* });
|
|
571
|
+
* ```
|
|
572
|
+
* @see https://code.claude.com/docs/en/hooks#permissiondenied
|
|
573
|
+
*/
|
|
574
|
+
export function permissionDeniedHook(config, handler) {
|
|
575
|
+
return createHookFunction("PermissionDenied", config, handler);
|
|
576
|
+
}
|
|
577
|
+
// ============================================================================
|
|
578
|
+
// Setup Hook Factory
|
|
579
|
+
// ============================================================================
|
|
580
|
+
/**
|
|
581
|
+
* Creates a Setup hook handler.
|
|
582
|
+
*
|
|
583
|
+
* Setup hooks fire during initialization or maintenance, allowing you to:
|
|
584
|
+
* - Configure initial session state
|
|
585
|
+
* - Perform setup tasks before the session starts
|
|
586
|
+
* - Add context for maintenance operations
|
|
587
|
+
*
|
|
588
|
+
* **Matcher**: Matches against `trigger` ('init' or 'maintenance')
|
|
589
|
+
* @param config - Hook configuration with optional matcher and timeout
|
|
590
|
+
* @param handler - The handler function to execute
|
|
591
|
+
* @returns A hook function that can be exported as the default export
|
|
592
|
+
* @example
|
|
593
|
+
* ```typescript
|
|
594
|
+
* import { setupHook, setupOutput } from '@goodfoot/agent-hooks/claude-code';
|
|
595
|
+
*
|
|
596
|
+
* // Handle all setup events
|
|
597
|
+
* export default setupHook({}, async (input, { logger }) => {
|
|
598
|
+
* logger.info('Setup triggered', { trigger: input.trigger });
|
|
599
|
+
* return setupOutput({});
|
|
600
|
+
* });
|
|
601
|
+
*
|
|
602
|
+
* // Only handle initialization
|
|
603
|
+
* export default setupHook({ matcher: 'init' }, async (input, { logger }) => {
|
|
604
|
+
* logger.info('Initializing session');
|
|
605
|
+
* return setupOutput({
|
|
606
|
+
* hookSpecificOutput: {
|
|
607
|
+
* additionalContext: 'Session initialized with custom configuration'
|
|
608
|
+
* }
|
|
609
|
+
* });
|
|
610
|
+
* });
|
|
611
|
+
* ```
|
|
612
|
+
* @see https://code.claude.com/docs/en/hooks#setup
|
|
613
|
+
*/
|
|
614
|
+
export function setupHook(config, handler) {
|
|
615
|
+
return createHookFunction("Setup", config, handler);
|
|
616
|
+
}
|
|
617
|
+
// ============================================================================
|
|
618
|
+
// TeammateIdle Hook Factory
|
|
619
|
+
// ============================================================================
|
|
620
|
+
/**
|
|
621
|
+
* Creates a TeammateIdle hook handler.
|
|
622
|
+
*
|
|
623
|
+
* TeammateIdle hooks fire when a teammate in a team is about to go idle,
|
|
624
|
+
* allowing you to:
|
|
625
|
+
* - Assign work to idle teammates
|
|
626
|
+
* - Log team activity
|
|
627
|
+
* - Coordinate multi-agent workflows
|
|
628
|
+
*
|
|
629
|
+
* **Matcher**: No matcher support - fires on all teammate idle events
|
|
630
|
+
* @param config - Hook configuration with optional timeout (matcher is ignored)
|
|
631
|
+
* @param handler - The handler function to execute
|
|
632
|
+
* @returns A hook function that can be exported as the default export
|
|
633
|
+
* @example
|
|
634
|
+
* ```typescript
|
|
635
|
+
* import { teammateIdleHook, teammateIdleOutput } from '@goodfoot/agent-hooks/claude-code';
|
|
636
|
+
*
|
|
637
|
+
* // Log when teammates go idle
|
|
638
|
+
* export default teammateIdleHook({}, async (input, { logger }) => {
|
|
639
|
+
* logger.info('Teammate going idle', {
|
|
640
|
+
* teammateName: input.teammate_name,
|
|
641
|
+
* teamName: input.team_name
|
|
642
|
+
* });
|
|
643
|
+
*
|
|
644
|
+
* return teammateIdleOutput({});
|
|
645
|
+
* });
|
|
646
|
+
* ```
|
|
647
|
+
* @see https://code.claude.com/docs/en/hooks#teammateidle
|
|
648
|
+
*/
|
|
649
|
+
export function teammateIdleHook(config, handler) {
|
|
650
|
+
return createHookFunction("TeammateIdle", config, handler);
|
|
651
|
+
}
|
|
652
|
+
// ============================================================================
|
|
653
|
+
// TaskCreated Hook Factory
|
|
654
|
+
// ============================================================================
|
|
655
|
+
/**
|
|
656
|
+
* Creates a TaskCreated hook handler.
|
|
657
|
+
*
|
|
658
|
+
* TaskCreated hooks fire when a new task is created and assigned to a teammate,
|
|
659
|
+
* allowing you to:
|
|
660
|
+
* - Observe task creation events
|
|
661
|
+
* - Log task assignments for auditing
|
|
662
|
+
* - React to new work being assigned
|
|
663
|
+
*
|
|
664
|
+
* **Matcher**: No matcher support - fires on all task creation events
|
|
665
|
+
* @param config - Hook configuration with optional timeout (matcher is ignored)
|
|
666
|
+
* @param handler - The handler function to execute
|
|
667
|
+
* @returns A hook function that can be exported as the default export
|
|
668
|
+
* @example
|
|
669
|
+
* ```typescript
|
|
670
|
+
* import { taskCreatedHook, taskCreatedOutput } from '@goodfoot/agent-hooks/claude-code';
|
|
671
|
+
*
|
|
672
|
+
* // Log task creation
|
|
673
|
+
* export default taskCreatedHook({}, async (input, { logger }) => {
|
|
674
|
+
* logger.info('Task created', {
|
|
675
|
+
* taskId: input.task_id,
|
|
676
|
+
* taskSubject: input.task_subject
|
|
677
|
+
* });
|
|
678
|
+
*
|
|
679
|
+
* return taskCreatedOutput({});
|
|
680
|
+
* });
|
|
681
|
+
* ```
|
|
682
|
+
* @see https://code.claude.com/docs/en/hooks#taskcreated
|
|
683
|
+
*/
|
|
684
|
+
export function taskCreatedHook(config, handler) {
|
|
685
|
+
return createHookFunction("TaskCreated", config, handler);
|
|
686
|
+
}
|
|
687
|
+
// ============================================================================
|
|
688
|
+
// TaskCompleted Hook Factory
|
|
689
|
+
// ============================================================================
|
|
690
|
+
/**
|
|
691
|
+
* Creates a TaskCompleted hook handler.
|
|
692
|
+
*
|
|
693
|
+
* TaskCompleted hooks fire when a task is being marked as completed,
|
|
694
|
+
* allowing you to:
|
|
695
|
+
* - Verify task completion
|
|
696
|
+
* - Log task metrics
|
|
697
|
+
* - Trigger follow-up actions
|
|
698
|
+
*
|
|
699
|
+
* **Matcher**: No matcher support - fires on all task completion events
|
|
700
|
+
* @param config - Hook configuration with optional timeout (matcher is ignored)
|
|
701
|
+
* @param handler - The handler function to execute
|
|
702
|
+
* @returns A hook function that can be exported as the default export
|
|
703
|
+
* @example
|
|
704
|
+
* ```typescript
|
|
705
|
+
* import { taskCompletedHook, taskCompletedOutput } from '@goodfoot/agent-hooks/claude-code';
|
|
706
|
+
*
|
|
707
|
+
* // Log task completion
|
|
708
|
+
* export default taskCompletedHook({}, async (input, { logger }) => {
|
|
709
|
+
* logger.info('Task completed', {
|
|
710
|
+
* taskId: input.task_id,
|
|
711
|
+
* taskSubject: input.task_subject
|
|
712
|
+
* });
|
|
713
|
+
*
|
|
714
|
+
* return taskCompletedOutput({});
|
|
715
|
+
* });
|
|
716
|
+
* ```
|
|
717
|
+
* @see https://code.claude.com/docs/en/hooks#taskcompleted
|
|
718
|
+
*/
|
|
719
|
+
export function taskCompletedHook(config, handler) {
|
|
720
|
+
return createHookFunction("TaskCompleted", config, handler);
|
|
721
|
+
}
|
|
722
|
+
// ============================================================================
|
|
723
|
+
// Elicitation Hook Factory
|
|
724
|
+
// ============================================================================
|
|
725
|
+
/**
|
|
726
|
+
* Creates an Elicitation hook handler.
|
|
727
|
+
*
|
|
728
|
+
* Elicitation hooks fire when an MCP server requests user input, allowing you to:
|
|
729
|
+
* - Accept, decline, or cancel elicitation requests programmatically
|
|
730
|
+
* - Provide structured form input or URL-based auth responses
|
|
731
|
+
* - Log or audit elicitation requests
|
|
732
|
+
*
|
|
733
|
+
* **Matcher**: No matcher support - fires on all elicitation events
|
|
734
|
+
* @param config - Hook configuration with optional timeout
|
|
735
|
+
* @param handler - The handler function to execute
|
|
736
|
+
* @returns A hook function that can be exported as the default export
|
|
737
|
+
* @example
|
|
738
|
+
* ```typescript
|
|
739
|
+
* import { elicitationHook, elicitationOutput } from '@goodfoot/agent-hooks/claude-code';
|
|
740
|
+
*
|
|
741
|
+
* export default elicitationHook({}, async (input, { logger }) => {
|
|
742
|
+
* logger.info('Elicitation request', { server: input.mcp_server_name });
|
|
743
|
+
* return elicitationOutput({
|
|
744
|
+
* hookSpecificOutput: { action: 'accept', content: { approved: true } }
|
|
745
|
+
* });
|
|
746
|
+
* });
|
|
747
|
+
* ```
|
|
748
|
+
* @see https://code.claude.com/docs/en/hooks#elicitation
|
|
749
|
+
*/
|
|
750
|
+
export function elicitationHook(config, handler) {
|
|
751
|
+
return createHookFunction("Elicitation", config, handler);
|
|
752
|
+
}
|
|
753
|
+
// ============================================================================
|
|
754
|
+
// ElicitationResult Hook Factory
|
|
755
|
+
// ============================================================================
|
|
756
|
+
/**
|
|
757
|
+
* Creates an ElicitationResult hook handler.
|
|
758
|
+
*
|
|
759
|
+
* ElicitationResult hooks fire with the result of an MCP elicitation request,
|
|
760
|
+
* allowing you to:
|
|
761
|
+
* - Observe elicitation outcomes
|
|
762
|
+
* - Modify the result before it is returned to the MCP server
|
|
763
|
+
* - Log elicitation completions
|
|
764
|
+
*
|
|
765
|
+
* **Matcher**: No matcher support - fires on all elicitation result events
|
|
766
|
+
* @param config - Hook configuration with optional timeout
|
|
767
|
+
* @param handler - The handler function to execute
|
|
768
|
+
* @returns A hook function that can be exported as the default export
|
|
769
|
+
* @example
|
|
770
|
+
* ```typescript
|
|
771
|
+
* import { elicitationResultHook, elicitationResultOutput } from '@goodfoot/agent-hooks/claude-code';
|
|
772
|
+
*
|
|
773
|
+
* export default elicitationResultHook({}, async (input, { logger }) => {
|
|
774
|
+
* logger.info('Elicitation result', { action: input.action });
|
|
775
|
+
* return elicitationResultOutput({});
|
|
776
|
+
* });
|
|
777
|
+
* ```
|
|
778
|
+
* @see https://code.claude.com/docs/en/hooks#elicitationresult
|
|
779
|
+
*/
|
|
780
|
+
export function elicitationResultHook(config, handler) {
|
|
781
|
+
return createHookFunction("ElicitationResult", config, handler);
|
|
782
|
+
}
|
|
783
|
+
// ============================================================================
|
|
784
|
+
// ConfigChange Hook Factory
|
|
785
|
+
// ============================================================================
|
|
786
|
+
/**
|
|
787
|
+
* Creates a ConfigChange hook handler.
|
|
788
|
+
*
|
|
789
|
+
* ConfigChange hooks fire when Claude Code configuration changes, allowing you to:
|
|
790
|
+
* - React to settings file changes
|
|
791
|
+
* - Log or audit configuration changes
|
|
792
|
+
* - Apply custom logic when settings are updated
|
|
793
|
+
*
|
|
794
|
+
* **Matcher**: Matches against `source` ('user_settings', 'project_settings', etc.)
|
|
795
|
+
* @param config - Hook configuration with optional matcher and timeout
|
|
796
|
+
* @param handler - The handler function to execute
|
|
797
|
+
* @returns A hook function that can be exported as the default export
|
|
798
|
+
* @example
|
|
799
|
+
* ```typescript
|
|
800
|
+
* import { configChangeHook, configChangeOutput } from '@goodfoot/agent-hooks/claude-code';
|
|
801
|
+
*
|
|
802
|
+
* export default configChangeHook({}, async (input, { logger }) => {
|
|
803
|
+
* logger.info('Config changed', { source: input.source, file: input.file_path });
|
|
804
|
+
* return configChangeOutput({});
|
|
805
|
+
* });
|
|
806
|
+
* ```
|
|
807
|
+
* @see https://code.claude.com/docs/en/hooks#configchange
|
|
808
|
+
*/
|
|
809
|
+
export function configChangeHook(config, handler) {
|
|
810
|
+
return createHookFunction("ConfigChange", config, handler);
|
|
811
|
+
}
|
|
812
|
+
// ============================================================================
|
|
813
|
+
// InstructionsLoaded Hook Factory
|
|
814
|
+
// ============================================================================
|
|
815
|
+
/**
|
|
816
|
+
* Creates an InstructionsLoaded hook handler.
|
|
817
|
+
*
|
|
818
|
+
* InstructionsLoaded hooks fire when a CLAUDE.md or similar instructions file
|
|
819
|
+
* is loaded, allowing you to:
|
|
820
|
+
* - React to instructions being applied
|
|
821
|
+
* - Log which instruction files are active
|
|
822
|
+
* - Observe the instruction loading hierarchy
|
|
823
|
+
*
|
|
824
|
+
* **Matcher**: No matcher support - fires on all instruction load events
|
|
825
|
+
* @param config - Hook configuration with optional timeout
|
|
826
|
+
* @param handler - The handler function to execute
|
|
827
|
+
* @returns A hook function that can be exported as the default export
|
|
828
|
+
* @example
|
|
829
|
+
* ```typescript
|
|
830
|
+
* import { instructionsLoadedHook, instructionsLoadedOutput } from '@goodfoot/agent-hooks/claude-code';
|
|
831
|
+
*
|
|
832
|
+
* export default instructionsLoadedHook({}, async (input, { logger }) => {
|
|
833
|
+
* logger.info('Instructions loaded', { file: input.file_path, type: input.memory_type });
|
|
834
|
+
* return instructionsLoadedOutput({});
|
|
835
|
+
* });
|
|
836
|
+
* ```
|
|
837
|
+
* @see https://code.claude.com/docs/en/hooks#instructionsloaded
|
|
838
|
+
*/
|
|
839
|
+
export function instructionsLoadedHook(config, handler) {
|
|
840
|
+
return createHookFunction("InstructionsLoaded", config, handler);
|
|
841
|
+
}
|
|
842
|
+
// ============================================================================
|
|
843
|
+
// WorktreeCreate Hook Factory
|
|
844
|
+
// ============================================================================
|
|
845
|
+
/**
|
|
846
|
+
* Creates a WorktreeCreate hook handler.
|
|
847
|
+
*
|
|
848
|
+
* WorktreeCreate hooks fire when a git worktree is created, allowing you to:
|
|
849
|
+
* - Set up worktree-specific configuration
|
|
850
|
+
* - Log worktree creation events
|
|
851
|
+
* - Initialize worktree resources
|
|
852
|
+
*
|
|
853
|
+
* **Matcher**: No matcher support - fires on all worktree creation events
|
|
854
|
+
* @param config - Hook configuration with optional timeout
|
|
855
|
+
* @param handler - The handler function to execute
|
|
856
|
+
* @returns A hook function that can be exported as the default export
|
|
857
|
+
* @example
|
|
858
|
+
* ```typescript
|
|
859
|
+
* import { worktreeCreateHook, worktreeCreateOutput } from '@goodfoot/agent-hooks/claude-code';
|
|
860
|
+
*
|
|
861
|
+
* export default worktreeCreateHook({}, async (input, { logger }) => {
|
|
862
|
+
* const worktreePath = `${input.cwd}/.worktrees/${input.name}`;
|
|
863
|
+
* logger.info('Worktree created', { name: input.name, worktreePath });
|
|
864
|
+
* // WorktreeCreate is a command hook: the path is written to stdout as plain text.
|
|
865
|
+
* return worktreeCreateOutput({ worktreePath });
|
|
866
|
+
* });
|
|
867
|
+
* ```
|
|
868
|
+
* @see https://code.claude.com/docs/en/hooks#worktreecreate
|
|
869
|
+
*/
|
|
870
|
+
export function worktreeCreateHook(config, handler) {
|
|
871
|
+
return createHookFunction("WorktreeCreate", config, handler);
|
|
872
|
+
}
|
|
873
|
+
// ============================================================================
|
|
874
|
+
// WorktreeRemove Hook Factory
|
|
875
|
+
// ============================================================================
|
|
876
|
+
/**
|
|
877
|
+
* Creates a WorktreeRemove hook handler.
|
|
878
|
+
*
|
|
879
|
+
* WorktreeRemove hooks fire when a git worktree is removed, allowing you to:
|
|
880
|
+
* - Clean up worktree-specific resources
|
|
881
|
+
* - Log worktree removal events
|
|
882
|
+
*
|
|
883
|
+
* **Matcher**: No matcher support - fires on all worktree removal events
|
|
884
|
+
* @param config - Hook configuration with optional timeout
|
|
885
|
+
* @param handler - The handler function to execute
|
|
886
|
+
* @returns A hook function that can be exported as the default export
|
|
887
|
+
* @example
|
|
888
|
+
* ```typescript
|
|
889
|
+
* import { worktreeRemoveHook, worktreeRemoveOutput } from '@goodfoot/agent-hooks/claude-code';
|
|
890
|
+
*
|
|
891
|
+
* export default worktreeRemoveHook({}, async (input, { logger }) => {
|
|
892
|
+
* logger.info('Worktree removed', { path: input.worktree_path });
|
|
893
|
+
* return worktreeRemoveOutput({});
|
|
894
|
+
* });
|
|
895
|
+
* ```
|
|
896
|
+
* @see https://code.claude.com/docs/en/hooks#worktreeremove
|
|
897
|
+
*/
|
|
898
|
+
export function worktreeRemoveHook(config, handler) {
|
|
899
|
+
return createHookFunction("WorktreeRemove", config, handler);
|
|
900
|
+
}
|
|
901
|
+
// ============================================================================
|
|
902
|
+
// CwdChanged Hook Factory
|
|
903
|
+
// ============================================================================
|
|
904
|
+
/**
|
|
905
|
+
* Creates a CwdChanged hook handler.
|
|
906
|
+
*
|
|
907
|
+
* CwdChanged hooks fire when Claude Code's current working directory changes,
|
|
908
|
+
* allowing you to:
|
|
909
|
+
* - React to directory changes within a session
|
|
910
|
+
* - Update file watchers or environment state
|
|
911
|
+
* - Return `watchPaths` via `hookSpecificOutput` to register paths for FileChanged events
|
|
912
|
+
*
|
|
913
|
+
* **Matcher**: No matcher support - fires on all cwd change events
|
|
914
|
+
* @param config - Hook configuration with optional timeout
|
|
915
|
+
* @param handler - The handler function to execute
|
|
916
|
+
* @returns A hook function that can be exported as the default export
|
|
917
|
+
* @example
|
|
918
|
+
* ```typescript
|
|
919
|
+
* import { cwdChangedHook, cwdChangedOutput } from '@goodfoot/agent-hooks/claude-code';
|
|
920
|
+
*
|
|
921
|
+
* export default cwdChangedHook({}, async (input, { logger }) => {
|
|
922
|
+
* logger.info('Working directory changed', { from: input.old_cwd, to: input.new_cwd });
|
|
923
|
+
* return cwdChangedOutput({});
|
|
924
|
+
* });
|
|
925
|
+
* ```
|
|
926
|
+
* @see https://code.claude.com/docs/en/hooks#cwdchanged
|
|
927
|
+
*/
|
|
928
|
+
export function cwdChangedHook(config, handler) {
|
|
929
|
+
return createHookFunction("CwdChanged", config, handler);
|
|
930
|
+
}
|
|
931
|
+
// ============================================================================
|
|
932
|
+
// FileChanged Hook Factory
|
|
933
|
+
// ============================================================================
|
|
934
|
+
/**
|
|
935
|
+
* Creates a FileChanged hook handler.
|
|
936
|
+
*
|
|
937
|
+
* FileChanged hooks fire when a watched file changes on disk, allowing you to:
|
|
938
|
+
* - React to file system changes during a session
|
|
939
|
+
* - Invalidate caches or reload configuration
|
|
940
|
+
* - Return `watchPaths` via `hookSpecificOutput` to update the set of watched paths
|
|
941
|
+
*
|
|
942
|
+
* The input `event` field indicates the type of change:
|
|
943
|
+
* - `'change'` - File contents changed
|
|
944
|
+
* - `'add'` - File was created
|
|
945
|
+
* - `'unlink'` - File was deleted
|
|
946
|
+
*
|
|
947
|
+
* **Matcher**: No matcher support - fires on all file change events
|
|
948
|
+
* @param config - Hook configuration with optional timeout
|
|
949
|
+
* @param handler - The handler function to execute
|
|
950
|
+
* @returns A hook function that can be exported as the default export
|
|
951
|
+
* @example
|
|
952
|
+
* ```typescript
|
|
953
|
+
* import { fileChangedHook, fileChangedOutput } from '@goodfoot/agent-hooks/claude-code';
|
|
954
|
+
*
|
|
955
|
+
* export default fileChangedHook({}, async (input, { logger }) => {
|
|
956
|
+
* logger.info('File changed', { path: input.file_path, event: input.event });
|
|
957
|
+
* return fileChangedOutput({});
|
|
958
|
+
* });
|
|
959
|
+
* ```
|
|
960
|
+
* @see https://code.claude.com/docs/en/hooks#filechanged
|
|
961
|
+
*/
|
|
962
|
+
export function fileChangedHook(config, handler) {
|
|
963
|
+
return createHookFunction("FileChanged", config, handler);
|
|
964
|
+
}
|
|
965
|
+
// ============================================================================
|
|
966
|
+
// MessageDisplay Hook Factory
|
|
967
|
+
// ============================================================================
|
|
968
|
+
/**
|
|
969
|
+
* Creates a MessageDisplay hook handler.
|
|
970
|
+
*
|
|
971
|
+
* MessageDisplay hooks fire with each batch of newly completed lines while an
|
|
972
|
+
* assistant message streams. Display-only: the stored message and what the model
|
|
973
|
+
* sees are untouched. Allows you to:
|
|
974
|
+
* - Replace the delta shown on screen with custom content via `displayContent`
|
|
975
|
+
* - Observe and log message streaming events
|
|
976
|
+
*
|
|
977
|
+
* The input carries `turn_id`, `message_id`, `index`, `final`, and `delta` fields.
|
|
978
|
+
* The `final` flag indicates the last flush of a message — its `delta` is empty
|
|
979
|
+
* when the message ends on a newline; treat `final` as the end-of-message signal.
|
|
980
|
+
*
|
|
981
|
+
* **Matcher**: No matcher support - fires on all message display events
|
|
982
|
+
* @param config - Hook configuration with optional timeout
|
|
983
|
+
* @param handler - The handler function to execute
|
|
984
|
+
* @returns A hook function that can be exported as the default export
|
|
985
|
+
* @example
|
|
986
|
+
* ```typescript
|
|
987
|
+
* import { messageDisplayHook, messageDisplayOutput } from '@goodfoot/agent-hooks/claude-code';
|
|
988
|
+
*
|
|
989
|
+
* export default messageDisplayHook({}, async (input, { logger }) => {
|
|
990
|
+
* if (input.final) {
|
|
991
|
+
* logger.info('Message complete', { messageId: input.message_id });
|
|
992
|
+
* }
|
|
993
|
+
* return messageDisplayOutput({});
|
|
994
|
+
* });
|
|
995
|
+
* ```
|
|
996
|
+
* @see https://code.claude.com/docs/en/hooks#messagedisplay
|
|
997
|
+
*/
|
|
998
|
+
export function messageDisplayHook(config, handler) {
|
|
999
|
+
return createHookFunction("MessageDisplay", config, handler);
|
|
1000
|
+
}
|