/** * Project-local lifecycle hooks. * * User drops executable shell scripts in `.codeep/hooks/.sh` and Codeep * runs them at the relevant moment during a session. Generalises what the * `agentAutoCommit` and `agentAutoVerify` config flags do — anything those * can do, a `post_edit` hook can do too, without a code change in the CLI. * * Supported events: * * `pre_tool_call` — fires before every tool execution. NON-ZERO exit * BLOCKS the tool call (the agent gets a clear error * message). Use for policy enforcement: block writes * to certain paths, refuse risky commands, etc. * * `post_edit` — fires after a successful write_file or edit_file. * Exit code is ignored (auto-format / auto-lint: * failure shouldn't block the agent). Receives the * file path. Use for prettier/eslint/gofmt. * * `on_error` — fires when a tool call returns success=false. * Exit code ignored. Use for centralised logging * or alerting. * * `pre_commit` — fires before the /commit skill stages anything. * NON-ZERO exit BLOCKS the commit. Use for test * runs, lint gates, etc. * * Environment variables every hook receives: * CODEEP_HOOK_EVENT - one of the event names above * CODEEP_WORKSPACE - workspace root absolute path * CODEEP_SESSION_ID - current Codeep session id * * Event-specific extras: * pre_tool_call / on_error: * CODEEP_HOOK_TOOL - tool name (read_file, write_file, …) * CODEEP_HOOK_PARAMS - JSON-encoded tool parameters * post_edit: * CODEEP_HOOK_TOOL - 'write_file' | 'edit_file' * CODEEP_HOOK_FILE - absolute path of the file that was edited * * Security note: hooks run arbitrary shell. They are project-scoped — a * cloned repo with hostile hooks would execute its scripts on the user's * machine the first time they trigger an agent tool call. The welcome * banner warns when hooks exist (see `summarizeHooks`); we do not run * hooks from `~/.codeep/hooks/` (global) for that reason. * * Platform note: hooks are POSIX shell (`.sh`) scripts. On macOS/Linux they * run directly; on Windows they run through Git Bash's `sh` if installed. * Windows without a POSIX shell → hooks are reported `unsupported` and skipped * (never blocking). See `resolveShellMode` and the README "Windows notes". */ export declare function isHooksTrusted(workspaceRoot: string): boolean; export declare function trustWorkspaceHooks(workspaceRoot: string): void; export declare function untrustWorkspaceHooks(workspaceRoot: string): void; export type HookEvent = 'pre_tool_call' | 'post_edit' | 'on_error' | 'pre_commit'; export declare const HOOK_EVENTS: readonly HookEvent[]; export interface HookContext { event: HookEvent; workspaceRoot: string; sessionId?: string; /** For pre_tool_call / on_error / post_edit */ toolName?: string; /** For pre_tool_call / on_error */ toolParams?: Record; /** For post_edit */ filePath?: string; } export interface HookResult { /** True if a hook script existed and was actually invoked. */ executed: boolean; /** Exit code, or 0 if no hook was present. */ exitCode: number; stdout: string; stderr: string; /** True if this hook event blocks downstream work AND the hook failed. */ blocked: boolean; /** Path that was executed (useful for error messages). */ scriptPath?: string; /** True when a hook script exists but the workspace isn't trusted, so it was * skipped (not run). Lets callers surface "run /hooks trust to enable". */ untrusted?: boolean; /** True when a hook script exists but this OS can't run it — Codeep hooks are * POSIX shell (`.sh`) scripts and no `sh` was found (e.g. Windows without * Git Bash). A non-blocking skip; surfaced by `/hooks` + the welcome banner. */ unsupported?: boolean; } /** * Decide how a `.sh` hook runs on this platform. On POSIX it's executed * directly (shebang); on Windows it needs a `sh`/`bash` interpreter, and if * none is installed hooks are `unsupported` (skipped, never blocking). Pure + * injectable so the platform matrix is unit-testable. */ export declare function resolveShellMode(platform?: NodeJS.Platform, findShell?: () => string | null): { mode: 'direct'; } | { mode: 'shell'; shell: string; } | { mode: 'unsupported'; }; /** True when this OS can actually run `.sh` hooks. Drives the `/hooks` and * welcome-banner "unsupported" state. */ export declare function hooksExecutable(platform?: NodeJS.Platform, findShell?: () => string | null): boolean; /** * Execute the configured hook for an event, if any. Returns `executed: false` * if no script exists. Caller is responsible for checking `blocked` and * aborting the parent action when it's true. */ export declare function runHook(ctx: HookContext, opts?: { timeoutMs?: number; }): HookResult; /** * Inspect a workspace and return which hook scripts are installed. * Used by the welcome banner and `/hooks` slash command. */ export declare function listInstalledHooks(workspaceRoot: string): { event: HookEvent; scriptPath: string; }[]; /** * Render an installed-hook list as Markdown for `/hooks` output. */ export declare function formatHookList(hooks: ReturnType): string; /** * Build the trust banner for `/hooks` and the welcome screen. `workspaceRoot` * is needed to read trust state; returns '' if no hooks are installed. */ export declare function formatHookTrust(workspaceRoot: string): string; /** * Short one-line summary used in the welcome banner when hooks are present. * Returns empty string if no hooks installed. */ export declare function summarizeHooks(workspaceRoot: string): string;