UNPKG

@yankeeinlondon/claudine

Version:

A simple library to help with Claude Code

198 lines (183 loc) 6.24 kB
import type { EmptyObject, IsUnion, Suggest } from "inferred-types"; /** * The hook's which Claude Code exposes. */ export type HookEventName = | "PreToolUse" | "PostToolUse" | "UserPromptSubmit" | "Stop" | "SubagentStope" | "Notification" | "PreCompact" | "SessionStart"; export type Tool = | "Write" | "Edit" | "Read" | "Glob" | "Grep" | "MultiEdit" | "WebFetch" | "WebSearch" | "Task" | `Bash(ls:*)` | `Bash(tsc:*)` | `Bash(rm:*)` | `Bash(git stash:*)` | `Bash(pnpm:*)` | `Bash(sed:*)`; export type SuggestMatcher = Suggest< | Tool | `Write|Edit` | `WebFetch|WebSearch` >; export interface HookCommand { /** optionally you may filter the Agent commands which will trigger this hook */ matcher?: SuggestMatcher; command: Suggest< | "$CLAUDE_PROJECT_DIR/.claude/hooks/check-style.sh" >; } export type Success = 0; export type Error = 1; export type BlockingError = 2; /** * **HookHandlerConfig** * * The structure of what you'd put in your `.settings.json` or `.settings.local.json` file * to add handling for a specific event. * * **Note:** each "handler" is placed inside of the `hooks: { [event]: HookHandlerConfig[] }` part of the configuration file. */ export interface HookHandlerConfig { /** * You may filter the handler to only execute when one of the * specified `AgentCommand`'s is the source. You may also use the `|` * operator inside your string configuration to indicate a _union_ of * AgentCommand's you will accept. */ matcher?: SuggestMatcher; /** the things you want to execute when */ hooks: HookCommand[]; } export type Hook<T extends HookEventName = HookEventName> = { session_id: string; transcript_path: string; cwd: string; hook_event_name: HookEventName; } & IsUnion<T> extends true ? EmptyObject : T extends "PreToolUse" ? { hook_event_name: "PreToolUse"; tool_name: Suggest<Tool>; tool_input: { file_path: string; content: string; }; } : T extends "PostToolUse" ? { hook_event_name: "PostToolUse"; tool_input: { file_path: string; content: string; }; tool_response: { filePath: string; success: boolean; }; } : T extends "Notification" ? { hook_event_name: "Notification"; message: string; } : T extends "UserPromptSubmit" ? { hook_event_name: "UserPromptSubmit"; prompt: string; } : T extends "Stop" ? { hook_event_name: "Stop"; stop_hook_active: boolean; } : T extends "SubagentStop" ? { hook_event_name: "SubagentStop"; stop_hook_active: boolean; } : T extends "SessionStart" ? { hook_event_name: "SessionStart"; source: Suggest<"startup">; } : EmptyObject; export type DecisionStrategy = "allow" | "deny" | "ask"; /** * The RAW response of a hook response is either a Unix exit code: * * - `0` - Success * - `1` - Error * - `2` - Blocking Error * * Or a JSON stringified string of `HookResponse` sent to STDOUT. */ export type HookResponseRaw = string | Success | Error | BlockingError; export type HookResponse<T extends HookEventName> = ( { continue?: boolean; stopReason?: string; suppressOutput?: boolean; } & T extends "PreToolUse" ? { hookSpecificOutput?: { hookEventName: "PreToolUse"; permissionDecision: DecisionStrategy; permissionDecisionReason: string; }; /** @deprecated */ decision?: DecisionStrategy; /** @deprecated */ reason?: string; } : T extends "PostToolUse" ? { decision?: "block" | undefined; reason: string; } : T extends "UserPromptSubmit" ? { decision?: "block" | undefined; reason: string; hookSpecificOutput?: { hookEventName: "UserPromptSubmit"; additionalContext: string; }; } : T extends "Stop" | "SubagentStop" ? { decision?: "block" | undefined; /** * Reason for stopping. * * **Note:* must be provided when Claude is blocked from stopping */ reason?: string; } : T extends "SessionStart" ? { hookSpecificOutput?: { hookEventName: "SessionStart"; additionalContext: string; }; } : EmptyObject ) | Success | Error | BlockingError; /** * A callback function which handle Claude Code hook events. */ export type HookHandler<T extends HookEventName> = <E extends Hook<T>>(event: E) => Promise<HookResponse<T>>;