cc-hooks-ts 2.0.0 → 2.0.43
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 +17 -33
- package/dist/index.d.mts +207 -200
- package/dist/index.mjs +14 -3
- package/package.json +13 -12
package/README.md
CHANGED
|
@@ -14,43 +14,22 @@ npx nypm add cc-hooks-ts
|
|
|
14
14
|
|
|
15
15
|
## Basic Usage
|
|
16
16
|
|
|
17
|
-
> [!NOTE]
|
|
18
|
-
> We highly recommend using Bun or Deno for automatic dependency downloading at runtime.
|
|
19
|
-
>
|
|
20
|
-
> - Bun: <https://bun.com/docs/runtime/autoimport>
|
|
21
|
-
> - Deno: <https://docs.deno.com/runtime/fundamentals/modules/#managing-third-party-modules-and-libraries>
|
|
22
|
-
|
|
23
17
|
### Define a Hook
|
|
24
18
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
```typescript
|
|
28
|
-
#!/usr/bin/env -S bun run --silent
|
|
29
|
-
import { defineHook, runHook } from "cc-hooks-ts";
|
|
30
|
-
|
|
31
|
-
// Session start hook
|
|
32
|
-
const sessionHook = defineHook({
|
|
33
|
-
trigger: { SessionStart: true },
|
|
34
|
-
run: (context) => {
|
|
35
|
-
// do something great
|
|
36
|
-
return context.success({
|
|
37
|
-
messageForUser: "Welcome to your coding session!"
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
await runHook(sessionHook);
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
Or with Deno:
|
|
19
|
+
Example of running a simple SessionStart hook on Bun:
|
|
46
20
|
|
|
47
21
|
```typescript
|
|
48
|
-
|
|
49
|
-
import { defineHook, runHook } from "npm:cc-hooks-ts";
|
|
22
|
+
import { defineHook } from "cc-hooks-ts";
|
|
50
23
|
|
|
51
|
-
// Session start hook
|
|
52
24
|
const sessionHook = defineHook({
|
|
53
|
-
trigger: {
|
|
25
|
+
trigger: {
|
|
26
|
+
// Specify the hook event to listen for
|
|
27
|
+
SessionStart: true,
|
|
28
|
+
PreToolUse: {
|
|
29
|
+
// PreToolUser and PostToolUse can be tool-specific. (affects type of context)
|
|
30
|
+
Read: true
|
|
31
|
+
}
|
|
32
|
+
},
|
|
54
33
|
run: (context) => {
|
|
55
34
|
// do something great
|
|
56
35
|
return context.success({
|
|
@@ -59,7 +38,11 @@ const sessionHook = defineHook({
|
|
|
59
38
|
}
|
|
60
39
|
});
|
|
61
40
|
|
|
62
|
-
|
|
41
|
+
// import.meta.main is available in Node.js 24.2+ and Bun and Deno
|
|
42
|
+
if (import.meta.main) {
|
|
43
|
+
const { runHook } = await import("cc-hooks-ts");
|
|
44
|
+
await runHook(sessionHook);
|
|
45
|
+
}
|
|
63
46
|
```
|
|
64
47
|
|
|
65
48
|
### Call from Claude Code
|
|
@@ -74,7 +57,7 @@ Then, load defined hooks in your Claude Code settings at `~/.claude/settings.jso
|
|
|
74
57
|
"hooks": [
|
|
75
58
|
{
|
|
76
59
|
"type": "command",
|
|
77
|
-
"command": "
|
|
60
|
+
"command": "bun run --silent path/to/your/sessionHook.ts"
|
|
78
61
|
}
|
|
79
62
|
]
|
|
80
63
|
}
|
|
@@ -149,6 +132,7 @@ const multiEventHook = defineHook({
|
|
|
149
132
|
PreToolUse: { Read: true, WebFetch: true },
|
|
150
133
|
PostToolUse: { Read: true }
|
|
151
134
|
},
|
|
135
|
+
// Optional: Define when the hook should run.
|
|
152
136
|
shouldRun: () => process.env.NODE_ENV === 'development',
|
|
153
137
|
run: (context) => {
|
|
154
138
|
// Handle different events and tools based on context.input
|
package/dist/index.d.mts
CHANGED
|
@@ -1,162 +1,11 @@
|
|
|
1
1
|
import * as v from "valibot";
|
|
2
|
-
import { BashInput, ExitPlanModeInput, FileEditInput, FileReadInput, FileWriteInput, GlobInput, GrepInput, NotebookEditInput, TodoWriteInput, WebFetchInput, WebSearchInput } from "@anthropic-ai/claude-
|
|
2
|
+
import { AgentInput, BashInput, BashOutputInput, ExitPlanModeInput, FileEditInput, FileReadInput, FileWriteInput, GlobInput, GrepInput, KillShellInput, ListMcpResourcesInput, NotebookEditInput, ReadMcpResourceInput, TodoWriteInput, WebFetchInput, WebSearchInput } from "@anthropic-ai/claude-agent-sdk/sdk-tools";
|
|
3
3
|
|
|
4
4
|
//#region src/utils/types.d.ts
|
|
5
5
|
type Awaitable<T> = Promise<T> | T;
|
|
6
6
|
type AutoComplete<T extends string> = Record<string, never> & T;
|
|
7
7
|
//#endregion
|
|
8
|
-
//#region src/
|
|
9
|
-
declare const SUPPORTED_HOOK_EVENTS: readonly ["PreToolUse", "PostToolUse", "Notification", "UserPromptSubmit", "SessionStart", "SessionEnd", "Stop", "SubagentStop", "PreCompact"];
|
|
10
|
-
/**
|
|
11
|
-
* @see {@link https://docs.anthropic.com/en/docs/claude-code/hooks#hook-events}
|
|
12
|
-
*/
|
|
13
|
-
type SupportedHookEvent = (typeof SUPPORTED_HOOK_EVENTS)[number];
|
|
14
|
-
//#endregion
|
|
15
|
-
//#region src/output.d.ts
|
|
16
|
-
type HookOutput = {
|
|
17
|
-
PreToolUse: PreToolUseHookOutput;
|
|
18
|
-
PostToolUse: PostToolUseHookOutput;
|
|
19
|
-
UserPromptSubmit: UserPromptSubmitHookOutput;
|
|
20
|
-
Stop: StopHookOutput;
|
|
21
|
-
SubagentStop: SubagentStopHookOutput;
|
|
22
|
-
SessionStart: SessionStartHookOutput;
|
|
23
|
-
Notification: CommonHookOutputs;
|
|
24
|
-
PreCompact: CommonHookOutputs;
|
|
25
|
-
SessionEnd: CommonHookOutputs;
|
|
26
|
-
};
|
|
27
|
-
type ExtractHookOutput<TEvent$1 extends SupportedHookEvent> = HookOutput extends Record<SupportedHookEvent, unknown> ? HookOutput[TEvent$1] : never;
|
|
28
|
-
/**
|
|
29
|
-
* Common fields of hook outputs
|
|
30
|
-
*
|
|
31
|
-
* @see {@link https://docs.anthropic.com/en/docs/claude-code/hooks#common-json-fields}
|
|
32
|
-
*/
|
|
33
|
-
type CommonHookOutputs = {
|
|
34
|
-
/**
|
|
35
|
-
* Whether Claude should continue after hook execution
|
|
36
|
-
*
|
|
37
|
-
* If `continue` is false, Claude stops processing after the hooks run.
|
|
38
|
-
* @default true
|
|
39
|
-
*/
|
|
40
|
-
continue?: boolean;
|
|
41
|
-
/**
|
|
42
|
-
* Accompanies `continue` with a `reason` shown to the user, not shown to Claude.
|
|
43
|
-
*
|
|
44
|
-
* NOT FOR CLAUDE
|
|
45
|
-
*/
|
|
46
|
-
stopReason?: string;
|
|
47
|
-
/**
|
|
48
|
-
* If `true`, user cannot see the stdout of this hook.
|
|
49
|
-
*
|
|
50
|
-
* @default false
|
|
51
|
-
*/
|
|
52
|
-
suppressOutput?: boolean;
|
|
53
|
-
/**
|
|
54
|
-
* Optional warning message shown to the user
|
|
55
|
-
*/
|
|
56
|
-
systemMessage?: string;
|
|
57
|
-
/**
|
|
58
|
-
* Use `hookSpecificOutput` in appropriate hook events instead.
|
|
59
|
-
*
|
|
60
|
-
* @deprecated
|
|
61
|
-
*/
|
|
62
|
-
reason?: string;
|
|
63
|
-
/**
|
|
64
|
-
* Use `hookSpecificOutput` in appropriate hook events instead.
|
|
65
|
-
*
|
|
66
|
-
* @deprecated
|
|
67
|
-
*/
|
|
68
|
-
decision?: "approve" | "block";
|
|
69
|
-
};
|
|
70
|
-
/**
|
|
71
|
-
* @see {@link https://docs.anthropic.com/en/docs/claude-code/hooks#pretooluse-decision-control}
|
|
72
|
-
*/
|
|
73
|
-
interface PreToolUseHookOutput extends CommonHookOutputs {
|
|
74
|
-
hookSpecificOutput?: {
|
|
75
|
-
hookEventName: "PreToolUse";
|
|
76
|
-
/**
|
|
77
|
-
* - `allow` bypasses the permission system. `permissionDecisionReason` is shown to the user but not to Claude.
|
|
78
|
-
* - `deny` prevents the tool call from executing. `permissionDecisionReason` is shown to Claude.
|
|
79
|
-
* - `ask` asks the user to confirm the tool call in the UI. `permissionDecisionReason` is shown to the user but not to Claude.
|
|
80
|
-
*/
|
|
81
|
-
permissionDecision?: "allow" | "ask" | "deny";
|
|
82
|
-
permissionDecisionReason?: string;
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
|
-
* @see {@link https://docs.anthropic.com/en/docs/claude-code/hooks#posttooluse-decision-control}
|
|
87
|
-
*/
|
|
88
|
-
interface PostToolUseHookOutput extends CommonHookOutputs {
|
|
89
|
-
/**
|
|
90
|
-
* - `approve` has no effect; the tool response is processed normally.
|
|
91
|
-
* - `block` automatically prompts Claude with `reason`.
|
|
92
|
-
*/
|
|
93
|
-
decision?: "approve" | "block";
|
|
94
|
-
hookSpecificOutput?: {
|
|
95
|
-
hookEventName: "PostToolUse";
|
|
96
|
-
/**
|
|
97
|
-
* Adds context for Claude to consider.
|
|
98
|
-
*/
|
|
99
|
-
additionalContext?: string;
|
|
100
|
-
};
|
|
101
|
-
reason?: string;
|
|
102
|
-
}
|
|
103
|
-
/**
|
|
104
|
-
* @see {@link https://docs.anthropic.com/en/docs/claude-code/hooks#userpromptsubmit-decision-control}
|
|
105
|
-
*/
|
|
106
|
-
interface UserPromptSubmitHookOutput extends CommonHookOutputs {
|
|
107
|
-
/**
|
|
108
|
-
* - `approve` has no effect; the tool response is processed normally.
|
|
109
|
-
* - `block` prevents the prompt from being processed.
|
|
110
|
-
* The submitted prompt is erased from context. `reason` is shown to the user but not added to context.
|
|
111
|
-
*/
|
|
112
|
-
decision?: "approve" | "block";
|
|
113
|
-
hookSpecificOutput?: {
|
|
114
|
-
hookEventName: "UserPromptSubmit";
|
|
115
|
-
/**
|
|
116
|
-
* Adds the string to the context if not blocked.
|
|
117
|
-
*/
|
|
118
|
-
additionalContext?: string;
|
|
119
|
-
};
|
|
120
|
-
reason?: string;
|
|
121
|
-
}
|
|
122
|
-
/**
|
|
123
|
-
* @see {@link https://docs.anthropic.com/en/docs/claude-code/hooks#stop%2Fsubagentstop-decision-control}
|
|
124
|
-
*/
|
|
125
|
-
interface StopHookOutput extends CommonHookOutputs {
|
|
126
|
-
/**
|
|
127
|
-
* - `approve` has no effect; the tool response is processed normally.
|
|
128
|
-
* - `block` prevents Claude from stopping. You must populate `reason` for Claude to know how to proceed.
|
|
129
|
-
*/
|
|
130
|
-
decision?: "approve" | "block";
|
|
131
|
-
/**
|
|
132
|
-
* Reason for the decision.
|
|
133
|
-
*/
|
|
134
|
-
reason?: string;
|
|
135
|
-
}
|
|
136
|
-
/**
|
|
137
|
-
* @see {@link https://docs.anthropic.com/en/docs/claude-code/hooks#stop%2Fsubagentstop-decision-control}
|
|
138
|
-
*/
|
|
139
|
-
interface SubagentStopHookOutput extends CommonHookOutputs {
|
|
140
|
-
/**
|
|
141
|
-
* - `approve` has no effect; the tool response is processed normally.
|
|
142
|
-
* - `block` prevents Claude from stopping. You must populate `reason` for Claude to know how to proceed.
|
|
143
|
-
*/
|
|
144
|
-
/**
|
|
145
|
-
* Reason for the decision.
|
|
146
|
-
*/
|
|
147
|
-
reason?: string;
|
|
148
|
-
}
|
|
149
|
-
interface SessionStartHookOutput extends CommonHookOutputs {
|
|
150
|
-
hookSpecificOutput?: {
|
|
151
|
-
hookEventName: "SessionStart";
|
|
152
|
-
/**
|
|
153
|
-
* Adds the string to the context.
|
|
154
|
-
*/
|
|
155
|
-
additionalContext?: string;
|
|
156
|
-
};
|
|
157
|
-
}
|
|
158
|
-
//#endregion
|
|
159
|
-
//#region src/input/schemas.d.ts
|
|
8
|
+
//#region src/hooks/input/schemas.d.ts
|
|
160
9
|
/**
|
|
161
10
|
* @package
|
|
162
11
|
*/
|
|
@@ -170,6 +19,7 @@ declare const HookInputSchemas: {
|
|
|
170
19
|
} & {
|
|
171
20
|
tool_name: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TransformAction<string, AutoComplete<string>>]>;
|
|
172
21
|
tool_input: v.UnknownSchema;
|
|
22
|
+
tool_use_id: v.StringSchema<undefined>;
|
|
173
23
|
}, undefined>;
|
|
174
24
|
readonly PostToolUse: v.ObjectSchema<{
|
|
175
25
|
readonly cwd: v.StringSchema<undefined>;
|
|
@@ -181,6 +31,7 @@ declare const HookInputSchemas: {
|
|
|
181
31
|
tool_name: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TransformAction<string, AutoComplete<string>>]>;
|
|
182
32
|
tool_input: v.UnknownSchema;
|
|
183
33
|
tool_response: v.UnknownSchema;
|
|
34
|
+
tool_use_id: v.StringSchema<undefined>;
|
|
184
35
|
}, undefined>;
|
|
185
36
|
readonly Notification: v.ObjectSchema<{
|
|
186
37
|
readonly cwd: v.StringSchema<undefined>;
|
|
@@ -190,6 +41,7 @@ declare const HookInputSchemas: {
|
|
|
190
41
|
readonly hook_event_name: v.LiteralSchema<"Notification", undefined>;
|
|
191
42
|
} & {
|
|
192
43
|
message: v.StringSchema<undefined>;
|
|
44
|
+
notification_type: v.StringSchema<undefined>;
|
|
193
45
|
title: v.ExactOptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
194
46
|
}, undefined>;
|
|
195
47
|
readonly UserPromptSubmit: v.ObjectSchema<{
|
|
@@ -210,6 +62,16 @@ declare const HookInputSchemas: {
|
|
|
210
62
|
} & {
|
|
211
63
|
stop_hook_active: v.BooleanSchema<undefined>;
|
|
212
64
|
}, undefined>;
|
|
65
|
+
readonly SubagentStart: v.ObjectSchema<{
|
|
66
|
+
readonly cwd: v.StringSchema<undefined>;
|
|
67
|
+
readonly permission_mode: v.ExactOptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
68
|
+
readonly session_id: v.StringSchema<undefined>;
|
|
69
|
+
readonly transcript_path: v.StringSchema<undefined>;
|
|
70
|
+
readonly hook_event_name: v.LiteralSchema<"SubagentStart", undefined>;
|
|
71
|
+
} & {
|
|
72
|
+
agent_id: v.StringSchema<undefined>;
|
|
73
|
+
agent_type: v.StringSchema<undefined>;
|
|
74
|
+
}, undefined>;
|
|
213
75
|
readonly SubagentStop: v.ObjectSchema<{
|
|
214
76
|
readonly cwd: v.StringSchema<undefined>;
|
|
215
77
|
readonly permission_mode: v.ExactOptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
@@ -217,6 +79,8 @@ declare const HookInputSchemas: {
|
|
|
217
79
|
readonly transcript_path: v.StringSchema<undefined>;
|
|
218
80
|
readonly hook_event_name: v.LiteralSchema<"SubagentStop", undefined>;
|
|
219
81
|
} & {
|
|
82
|
+
agent_id: v.StringSchema<undefined>;
|
|
83
|
+
agent_transcript_path: v.StringSchema<undefined>;
|
|
220
84
|
stop_hook_active: v.BooleanSchema<undefined>;
|
|
221
85
|
}, undefined>;
|
|
222
86
|
readonly PreCompact: v.ObjectSchema<{
|
|
@@ -249,7 +113,15 @@ declare const HookInputSchemas: {
|
|
|
249
113
|
}, undefined>;
|
|
250
114
|
};
|
|
251
115
|
//#endregion
|
|
252
|
-
//#region src/
|
|
116
|
+
//#region src/hooks/event.d.ts
|
|
117
|
+
/**
|
|
118
|
+
* @see {@link https://docs.anthropic.com/en/docs/claude-code/hooks#hook-events}
|
|
119
|
+
*
|
|
120
|
+
* @package
|
|
121
|
+
*/
|
|
122
|
+
type SupportedHookEvent = "PreToolUse" | "PostToolUse" | "Notification" | "UserPromptSubmit" | "SessionStart" | "SessionEnd" | "Stop" | "SubagentStop" | "PreCompact" | "SubagentStart";
|
|
123
|
+
//#endregion
|
|
124
|
+
//#region src/hooks/input/types.d.ts
|
|
253
125
|
/**
|
|
254
126
|
* Internal type that combines base hook inputs with tool-specific inputs for PreToolUse events.
|
|
255
127
|
* For non-PreToolUse events, this is equivalent to BaseHookInputs.
|
|
@@ -261,7 +133,7 @@ declare const HookInputSchemas: {
|
|
|
261
133
|
* ```
|
|
262
134
|
* @package
|
|
263
135
|
*/
|
|
264
|
-
type
|
|
136
|
+
type HookInput = { [EventKey in SupportedHookEvent]: EventKey extends "PreToolUse" ? ToolSpecificPreToolUseInput & {
|
|
265
137
|
default: BaseHookInputs["PreToolUse"];
|
|
266
138
|
} : EventKey extends "PostToolUse" ? ToolSpecificPostToolUseInput & {
|
|
267
139
|
default: BaseHookInputs["PostToolUse"];
|
|
@@ -285,7 +157,7 @@ type HookInputs = { [EventKey in SupportedHookEvent]: EventKey extends "PreToolU
|
|
|
285
157
|
* ```
|
|
286
158
|
* @package
|
|
287
159
|
*/
|
|
288
|
-
type ExtractAllHookInputsForEvent<TEvent$1 extends SupportedHookEvent> = { [K in keyof
|
|
160
|
+
type ExtractAllHookInputsForEvent<TEvent$1 extends SupportedHookEvent> = { [K in keyof HookInput[TEvent$1]]: HookInput[TEvent$1][K] }[keyof HookInput[TEvent$1]];
|
|
289
161
|
/**
|
|
290
162
|
* Extracts the hook input type for a specific tool within a given event type.
|
|
291
163
|
* This type utility is used to get strongly-typed inputs for tool-specific hook handlers.
|
|
@@ -306,11 +178,11 @@ type ExtractAllHookInputsForEvent<TEvent$1 extends SupportedHookEvent> = { [K in
|
|
|
306
178
|
* ```
|
|
307
179
|
* @package
|
|
308
180
|
*/
|
|
309
|
-
type ExtractSpecificHookInputForEvent<TEvent$1 extends SupportedHookEvent, TSpecificKey extends ExtractExtendedSpecificKeys<TEvent$1>> = TSpecificKey extends keyof
|
|
181
|
+
type ExtractSpecificHookInputForEvent<TEvent$1 extends SupportedHookEvent, TSpecificKey extends ExtractExtendedSpecificKeys<TEvent$1>> = TSpecificKey extends keyof HookInput[TEvent$1] ? HookInput[TEvent$1][TSpecificKey] : never;
|
|
310
182
|
/**
|
|
311
183
|
* @package
|
|
312
184
|
*/
|
|
313
|
-
type ExtractExtendedSpecificKeys<TEvent$1 extends SupportedHookEvent> = Exclude<keyof
|
|
185
|
+
type ExtractExtendedSpecificKeys<TEvent$1 extends SupportedHookEvent> = Exclude<keyof HookInput[TEvent$1], "default">;
|
|
314
186
|
type BaseHookInputs = { [EventKey in SupportedHookEvent]: v.InferOutput<(typeof HookInputSchemas)[EventKey]> };
|
|
315
187
|
type ToolSpecificPreToolUseInput = { [K in keyof ToolSchema]: Omit<BaseHookInputs["PreToolUse"], "tool_input" | "tool_name"> & {
|
|
316
188
|
tool_input: ToolSchema[K]["input"];
|
|
@@ -322,6 +194,168 @@ type ToolSpecificPostToolUseInput = { [K in keyof ToolSchema]: Omit<BaseHookInpu
|
|
|
322
194
|
tool_response: ToolSchema[K]["response"];
|
|
323
195
|
} };
|
|
324
196
|
//#endregion
|
|
197
|
+
//#region src/hooks/output/index.d.ts
|
|
198
|
+
/**
|
|
199
|
+
* @package
|
|
200
|
+
*/
|
|
201
|
+
type HookOutput = {
|
|
202
|
+
PreToolUse: PreToolUseHookOutput;
|
|
203
|
+
PostToolUse: PostToolUseHookOutput;
|
|
204
|
+
UserPromptSubmit: UserPromptSubmitHookOutput;
|
|
205
|
+
Stop: StopHookOutput;
|
|
206
|
+
SubagentStart: SubagentStartHookOutput;
|
|
207
|
+
SubagentStop: SubagentStopHookOutput;
|
|
208
|
+
SessionStart: SessionStartHookOutput;
|
|
209
|
+
Notification: CommonHookOutputs;
|
|
210
|
+
PreCompact: CommonHookOutputs;
|
|
211
|
+
SessionEnd: CommonHookOutputs;
|
|
212
|
+
};
|
|
213
|
+
/**
|
|
214
|
+
* @package
|
|
215
|
+
*/
|
|
216
|
+
type ExtractHookOutput<TEvent$1 extends SupportedHookEvent> = HookOutput extends Record<SupportedHookEvent, unknown> ? HookOutput[TEvent$1] : never;
|
|
217
|
+
/**
|
|
218
|
+
* Common fields of hook outputs
|
|
219
|
+
*
|
|
220
|
+
* @see {@link https://docs.anthropic.com/en/docs/claude-code/hooks#common-json-fields}
|
|
221
|
+
*/
|
|
222
|
+
type CommonHookOutputs = {
|
|
223
|
+
/**
|
|
224
|
+
* Whether Claude should continue after hook execution
|
|
225
|
+
*
|
|
226
|
+
* If `continue` is false, Claude stops processing after the hooks run.
|
|
227
|
+
* @default true
|
|
228
|
+
*/
|
|
229
|
+
continue?: boolean;
|
|
230
|
+
/**
|
|
231
|
+
* Accompanies `continue` with a `reason` shown to the user, not shown to Claude.
|
|
232
|
+
*
|
|
233
|
+
* NOT FOR CLAUDE
|
|
234
|
+
*/
|
|
235
|
+
stopReason?: string;
|
|
236
|
+
/**
|
|
237
|
+
* If `true`, user cannot see the stdout of this hook.
|
|
238
|
+
*
|
|
239
|
+
* @default false
|
|
240
|
+
*/
|
|
241
|
+
suppressOutput?: boolean;
|
|
242
|
+
/**
|
|
243
|
+
* Optional warning message shown to the user
|
|
244
|
+
*/
|
|
245
|
+
systemMessage?: string;
|
|
246
|
+
/**
|
|
247
|
+
* Use `hookSpecificOutput` in appropriate hook events instead.
|
|
248
|
+
*
|
|
249
|
+
* @deprecated
|
|
250
|
+
*/
|
|
251
|
+
reason?: string;
|
|
252
|
+
/**
|
|
253
|
+
* Use `hookSpecificOutput` in appropriate hook events instead.
|
|
254
|
+
*
|
|
255
|
+
* @deprecated
|
|
256
|
+
*/
|
|
257
|
+
decision?: "approve" | "block";
|
|
258
|
+
};
|
|
259
|
+
/**
|
|
260
|
+
* @see {@link https://docs.anthropic.com/en/docs/claude-code/hooks#pretooluse-decision-control}
|
|
261
|
+
*/
|
|
262
|
+
interface PreToolUseHookOutput extends CommonHookOutputs {
|
|
263
|
+
hookSpecificOutput?: {
|
|
264
|
+
hookEventName: "PreToolUse";
|
|
265
|
+
/**
|
|
266
|
+
* - `allow` bypasses the permission system. `permissionDecisionReason` is shown to the user but not to Claude.
|
|
267
|
+
* - `deny` prevents the tool call from executing. `permissionDecisionReason` is shown to Claude.
|
|
268
|
+
* - `ask` asks the user to confirm the tool call in the UI. `permissionDecisionReason` is shown to the user but not to Claude.
|
|
269
|
+
*/
|
|
270
|
+
permissionDecision?: "allow" | "ask" | "deny";
|
|
271
|
+
permissionDecisionReason?: string;
|
|
272
|
+
updatedInput?: Record<string, unknown>;
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* @see {@link https://docs.anthropic.com/en/docs/claude-code/hooks#posttooluse-decision-control}
|
|
277
|
+
*/
|
|
278
|
+
interface PostToolUseHookOutput extends CommonHookOutputs {
|
|
279
|
+
/**
|
|
280
|
+
* - `approve` has no effect; the tool response is processed normally.
|
|
281
|
+
* - `block` automatically prompts Claude with `reason`.
|
|
282
|
+
*/
|
|
283
|
+
decision?: "approve" | "block";
|
|
284
|
+
hookSpecificOutput?: {
|
|
285
|
+
hookEventName: "PostToolUse";
|
|
286
|
+
/**
|
|
287
|
+
* Adds context for Claude to consider.
|
|
288
|
+
*/
|
|
289
|
+
additionalContext?: string;
|
|
290
|
+
updatedMCPToolOutput?: unknown;
|
|
291
|
+
};
|
|
292
|
+
reason?: string;
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* @see {@link https://docs.anthropic.com/en/docs/claude-code/hooks#userpromptsubmit-decision-control}
|
|
296
|
+
*/
|
|
297
|
+
interface UserPromptSubmitHookOutput extends CommonHookOutputs {
|
|
298
|
+
/**
|
|
299
|
+
* - `approve` has no effect; the tool response is processed normally.
|
|
300
|
+
* - `block` prevents the prompt from being processed.
|
|
301
|
+
* The submitted prompt is erased from context. `reason` is shown to the user but not added to context.
|
|
302
|
+
*/
|
|
303
|
+
decision?: "approve" | "block";
|
|
304
|
+
hookSpecificOutput?: {
|
|
305
|
+
hookEventName: "UserPromptSubmit";
|
|
306
|
+
/**
|
|
307
|
+
* Adds the string to the context if not blocked.
|
|
308
|
+
*/
|
|
309
|
+
additionalContext?: string;
|
|
310
|
+
};
|
|
311
|
+
reason?: string;
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* @see {@link https://docs.anthropic.com/en/docs/claude-code/hooks#stop%2Fsubagentstop-decision-control}
|
|
315
|
+
*/
|
|
316
|
+
interface StopHookOutput extends CommonHookOutputs {
|
|
317
|
+
/**
|
|
318
|
+
* - `approve` has no effect; the tool response is processed normally.
|
|
319
|
+
* - `block` prevents Claude from stopping. You must populate `reason` for Claude to know how to proceed.
|
|
320
|
+
*/
|
|
321
|
+
decision?: "approve" | "block";
|
|
322
|
+
/**
|
|
323
|
+
* Reason for the decision.
|
|
324
|
+
*/
|
|
325
|
+
reason?: string;
|
|
326
|
+
}
|
|
327
|
+
interface SubagentStartHookOutput extends CommonHookOutputs {
|
|
328
|
+
hookSpecificOutput?: {
|
|
329
|
+
hookEventName: "SubagentStart";
|
|
330
|
+
/**
|
|
331
|
+
* Adds the string to the context.
|
|
332
|
+
*/
|
|
333
|
+
additionalContext?: string;
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* @see {@link https://docs.anthropic.com/en/docs/claude-code/hooks#stop%2Fsubagentstop-decision-control}
|
|
338
|
+
*/
|
|
339
|
+
interface SubagentStopHookOutput extends CommonHookOutputs {
|
|
340
|
+
/**
|
|
341
|
+
* - `approve` has no effect; the tool response is processed normally.
|
|
342
|
+
* - `block` prevents Claude from stopping. You must populate `reason` for Claude to know how to proceed.
|
|
343
|
+
*/
|
|
344
|
+
/**
|
|
345
|
+
* Reason for the decision.
|
|
346
|
+
*/
|
|
347
|
+
reason?: string;
|
|
348
|
+
}
|
|
349
|
+
interface SessionStartHookOutput extends CommonHookOutputs {
|
|
350
|
+
hookSpecificOutput?: {
|
|
351
|
+
hookEventName: "SessionStart";
|
|
352
|
+
/**
|
|
353
|
+
* Adds the string to the context.
|
|
354
|
+
*/
|
|
355
|
+
additionalContext?: string;
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
//#endregion
|
|
325
359
|
//#region src/types.d.ts
|
|
326
360
|
type HookTrigger = Partial<{ [TEvent in SupportedHookEvent]: true | Partial<{ [SchemaKey in ExtractExtendedSpecificKeys<TEvent>]?: true }> }>;
|
|
327
361
|
type ExtractTriggeredHookInput<TTrigger extends HookTrigger> = { [EventKey in keyof TTrigger]: EventKey extends SupportedHookEvent ? TTrigger[EventKey] extends true ? ExtractAllHookInputsForEvent<EventKey> : TTrigger[EventKey] extends Record<PropertyKey, true> ? { [SpecificKey in keyof TTrigger[EventKey]]: SpecificKey extends ExtractExtendedSpecificKeys<EventKey> ? ExtractSpecificHookInputForEvent<EventKey, SpecificKey> : never }[keyof TTrigger[EventKey]] : never : never }[keyof TTrigger];
|
|
@@ -570,6 +604,10 @@ interface ToolSchema {
|
|
|
570
604
|
stdout: string;
|
|
571
605
|
};
|
|
572
606
|
};
|
|
607
|
+
BashOutput: {
|
|
608
|
+
input: BashOutputInput;
|
|
609
|
+
response: unknown;
|
|
610
|
+
};
|
|
573
611
|
Edit: {
|
|
574
612
|
input: FileEditInput;
|
|
575
613
|
response: {
|
|
@@ -610,44 +648,13 @@ interface ToolSchema {
|
|
|
610
648
|
numLines: number;
|
|
611
649
|
};
|
|
612
650
|
};
|
|
613
|
-
|
|
614
|
-
input:
|
|
615
|
-
|
|
616
|
-
};
|
|
617
|
-
response: string;
|
|
651
|
+
KillBash: {
|
|
652
|
+
input: KillShellInput;
|
|
653
|
+
response: unknown;
|
|
618
654
|
};
|
|
619
|
-
|
|
620
|
-
input:
|
|
621
|
-
|
|
622
|
-
new_string: string;
|
|
623
|
-
old_string: string;
|
|
624
|
-
/**
|
|
625
|
-
* @default false
|
|
626
|
-
*/
|
|
627
|
-
replace_all?: boolean;
|
|
628
|
-
}>;
|
|
629
|
-
file_path: string;
|
|
630
|
-
};
|
|
631
|
-
response: {
|
|
632
|
-
edits: Array<{
|
|
633
|
-
new_string: string;
|
|
634
|
-
old_string: string;
|
|
635
|
-
/**
|
|
636
|
-
* @default false
|
|
637
|
-
*/
|
|
638
|
-
replace_all?: boolean;
|
|
639
|
-
}>;
|
|
640
|
-
filePath: string;
|
|
641
|
-
originalFileContents: string;
|
|
642
|
-
structuredPatch: Array<{
|
|
643
|
-
lines: string[];
|
|
644
|
-
newLines: number;
|
|
645
|
-
newStart: number;
|
|
646
|
-
oldLines: number;
|
|
647
|
-
oldStart: number;
|
|
648
|
-
}>;
|
|
649
|
-
userModified: boolean;
|
|
650
|
-
};
|
|
655
|
+
ListMcpResources: {
|
|
656
|
+
input: ListMcpResourcesInput;
|
|
657
|
+
response: unknown;
|
|
651
658
|
};
|
|
652
659
|
NotebookEdit: {
|
|
653
660
|
input: NotebookEditInput;
|
|
@@ -687,12 +694,12 @@ interface ToolSchema {
|
|
|
687
694
|
type: "text";
|
|
688
695
|
};
|
|
689
696
|
};
|
|
697
|
+
ReadMcpResource: {
|
|
698
|
+
input: ReadMcpResourceInput;
|
|
699
|
+
response: unknown;
|
|
700
|
+
};
|
|
690
701
|
Task: {
|
|
691
|
-
input:
|
|
692
|
-
description: string;
|
|
693
|
-
prompt: string;
|
|
694
|
-
subagent_type: AutoComplete<"general-purpose" | "output-style-setup" | "statusline-setup">;
|
|
695
|
-
};
|
|
702
|
+
input: AgentInput;
|
|
696
703
|
response: {
|
|
697
704
|
content: Array<{
|
|
698
705
|
text: string;
|
package/dist/index.mjs
CHANGED
|
@@ -44,20 +44,31 @@ function buildHookInputSchema(hook_event_name, entries) {
|
|
|
44
44
|
const HookInputSchemas = {
|
|
45
45
|
PreToolUse: buildHookInputSchema("PreToolUse", {
|
|
46
46
|
tool_name: v.pipe(v.string(), v.transform((s) => s)),
|
|
47
|
-
tool_input: v.unknown()
|
|
47
|
+
tool_input: v.unknown(),
|
|
48
|
+
tool_use_id: v.string()
|
|
48
49
|
}),
|
|
49
50
|
PostToolUse: buildHookInputSchema("PostToolUse", {
|
|
50
51
|
tool_name: v.pipe(v.string(), v.transform((s) => s)),
|
|
51
52
|
tool_input: v.unknown(),
|
|
52
|
-
tool_response: v.unknown()
|
|
53
|
+
tool_response: v.unknown(),
|
|
54
|
+
tool_use_id: v.string()
|
|
53
55
|
}),
|
|
54
56
|
Notification: buildHookInputSchema("Notification", {
|
|
55
57
|
message: v.string(),
|
|
58
|
+
notification_type: v.string(),
|
|
56
59
|
title: v.exactOptional(v.string())
|
|
57
60
|
}),
|
|
58
61
|
UserPromptSubmit: buildHookInputSchema("UserPromptSubmit", { prompt: v.string() }),
|
|
59
62
|
Stop: buildHookInputSchema("Stop", { stop_hook_active: v.boolean() }),
|
|
60
|
-
|
|
63
|
+
SubagentStart: buildHookInputSchema("SubagentStart", {
|
|
64
|
+
agent_id: v.string(),
|
|
65
|
+
agent_type: v.string()
|
|
66
|
+
}),
|
|
67
|
+
SubagentStop: buildHookInputSchema("SubagentStop", {
|
|
68
|
+
agent_id: v.string(),
|
|
69
|
+
agent_transcript_path: v.string(),
|
|
70
|
+
stop_hook_active: v.boolean()
|
|
71
|
+
}),
|
|
61
72
|
PreCompact: buildHookInputSchema("PreCompact", {
|
|
62
73
|
custom_instructions: v.nullable(v.string()),
|
|
63
74
|
trigger: v.union([v.literal("manual"), v.literal("auto")])
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cc-hooks-ts",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.43",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Write claude code hooks with type safety",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -43,32 +43,33 @@
|
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@arethetypeswrong/core": "0.18.2",
|
|
46
|
-
"@biomejs/biome": "2.3.
|
|
47
|
-
"@types/node": "24.10.
|
|
46
|
+
"@biomejs/biome": "2.3.5",
|
|
47
|
+
"@types/node": "24.10.1",
|
|
48
48
|
"@typescript/native-preview": "^7.0.0-dev.20251108.1",
|
|
49
49
|
"@virtual-live-lab/eslint-config": "2.3.1",
|
|
50
50
|
"@virtual-live-lab/tsconfig": "2.1.21",
|
|
51
51
|
"eslint": "9.39.1",
|
|
52
|
-
"eslint-plugin-import-access": "3.
|
|
52
|
+
"eslint-plugin-import-access": "3.1.0",
|
|
53
53
|
"pkg-pr-new": "0.0.60",
|
|
54
54
|
"publint": "0.3.15",
|
|
55
55
|
"release-it": "19.0.6",
|
|
56
56
|
"release-it-pnpm": "4.6.6",
|
|
57
|
-
"tsdown": "0.16.
|
|
57
|
+
"tsdown": "0.16.4",
|
|
58
58
|
"type-fest": "5.2.0",
|
|
59
59
|
"typescript": "5.9.3",
|
|
60
|
-
"typescript-eslint": "8.46.
|
|
61
|
-
"unplugin-unused": "0.5.
|
|
62
|
-
"vitest": "4.0.
|
|
60
|
+
"typescript-eslint": "8.46.4",
|
|
61
|
+
"unplugin-unused": "0.5.6",
|
|
62
|
+
"vitest": "4.0.9"
|
|
63
63
|
},
|
|
64
64
|
"dependencies": {
|
|
65
|
-
"@anthropic-ai/claude-
|
|
65
|
+
"@anthropic-ai/claude-agent-sdk": "0.1.43",
|
|
66
66
|
"valibot": "^1.1.0"
|
|
67
67
|
},
|
|
68
68
|
"scripts": {
|
|
69
|
-
"
|
|
70
|
-
"
|
|
71
|
-
"format
|
|
69
|
+
"check": "pnpm run format:check && pnpm run lint && pnpm run typecheck && pnpm run test && pnpm run build",
|
|
70
|
+
"lint": "eslint --max-warnings 0",
|
|
71
|
+
"format": "biome format --write",
|
|
72
|
+
"format:check": "biome format --reporter=github",
|
|
72
73
|
"typecheck": "tsgo --noEmit",
|
|
73
74
|
"test": "vitest --run",
|
|
74
75
|
"build": "tsdown",
|