/** * Hooks — Vigil-style shell-command hooks that fire around * tool execution. Lets users customize agent behavior without * editing source: run a linter after every Edit, log Bash commands, * block dangerous tools, etc. * * Settings file (per Vigil convention): * { * "hooks": { * "PreToolUse": [ * { "matcher": "Bash", "hooks": [{ "type": "command", "command": "/path/to/script.sh" }] } * ], * "PostToolUse": [ ... ] * } * } * * Loaded from (in priority order): * 1. /.vigil/settings.json (project-local) * 2. ~/.vigil/settings.json (user-global) * * Both load — project-local extends user-global; matchers from both * files fire if applicable. * * Hook contract: the command receives a JSON envelope on stdin, * shape: * { event: 'PreToolUse'|'PostToolUse', toolName, toolArgs, toolResult? } * The command exits 0 + writes a JSON response on stdout to either * pass through or shape the result: * {} — pass through * { "decision": "block", * "reason": "string" } — PreToolUse: block the tool call * { "appendToResult": "..." } — PostToolUse: append text to the * model-visible tool result * * Hooks are best-effort: a hook that times out, errors, or returns * malformed JSON is logged and skipped — never crashes the agent. */ export type HookEvent = 'PreToolUse' | 'PostToolUse' | 'UserPromptSubmit' | 'Stop' | 'SessionStart'; export interface HookCommand { /** Always 'command' for now; reserved for future inline-JS hooks. */ type: 'command'; /** Shell command to invoke. Run via the user's default shell. */ command: string; /** Per-hook timeout in ms. Default: 5000. Cap: 30000. */ timeoutMs?: number; } export interface HookMatcher { /** * For PreToolUse / PostToolUse: a tool-name regex (anchored). Use * "*" or omit to match every tool. For other events: ignored. */ matcher?: string; hooks: HookCommand[]; } export interface HooksConfig { hooks?: Partial>; } export interface PreToolUseInput { event: 'PreToolUse'; toolName: string; toolArgs: unknown; } export interface PostToolUseInput { event: 'PostToolUse'; toolName: string; toolArgs: unknown; toolResult: unknown; } export interface PreToolUseDecision { decision?: 'block'; reason?: string; } export interface PostToolUseDecision { appendToResult?: string; } /** * Read + merge settings from project-local + user-global locations. * Returns an empty config if neither file exists. Malformed JSON is * silently skipped (with a console.warn). */ export declare function loadHooksConfig(workingDir: string): HooksConfig; /** * Run all PreToolUse hooks matching `toolName`. Returns the FIRST * blocking decision encountered, or null if no hook blocks. */ export declare function runPreToolUseHooks(config: HooksConfig, toolName: string, toolArgs: unknown): Promise; /** * Run all PostToolUse hooks matching `toolName`. Concatenates any * appendToResult strings (in matcher order) so multiple hooks can * each contribute a note. */ export declare function runPostToolUseHooks(config: HooksConfig, toolName: string, toolArgs: unknown, toolResult: unknown): Promise<{ appendToResult: string; } | null>; //# sourceMappingURL=hooks.d.ts.map