/** * Surgical mutator for a Claude Code `settings.json` object — adds/removes the * Assay PostToolUse hook without disturbing anything else in the file. * * Every function is PURE: it takes a parsed settings object and returns a NEW * one (deep-cloned), never mutating the input. The command handlers own the * fs read/write; this module owns the "don't trash the user's settings" logic * and is the unit-tested surface (fresh / populated / double-install / * uninstall). * * The identifying marker is the command string: any PostToolUse hook whose * command matches HOOK_COMMAND_MARKER is "ours". That is what makes install * idempotent and uninstall precise. */ /** The command Claude Code runs on each Write/Edit. `tryassay` is the global bin. */ export declare const HOOK_COMMAND = "tryassay hook-run"; /** Matches our command even if a user hand-edited flags onto it. */ export declare const HOOK_COMMAND_MARKER: RegExp; /** Matcher: PostToolUse fires this only for file-editing tools. */ export declare const HOOK_MATCHER = "Write|Edit"; /** Per-edit timeout (seconds). Advisory + fail-open, so a slow verify never wedges an edit. */ export declare const HOOK_TIMEOUT_SECONDS = 30; interface HookCommand { type: 'command'; command: string; timeout?: number; [k: string]: unknown; } interface HookEntry { matcher?: string; hooks?: HookCommand[]; [k: string]: unknown; } export interface Settings { hooks?: Record; [k: string]: unknown; } /** True if the settings already contain the Assay PostToolUse hook. */ export declare function hasHook(settings: Settings): boolean; /** * Add the Assay PostToolUse hook. Idempotent: if it is already present (by * command marker), the settings are returned unchanged. Everything else — * other hook events, other PostToolUse entries, unrelated top-level keys — is * preserved byte-for-byte. */ export declare function installHook(settings: Settings): Settings; /** * Remove exactly the Assay hook. Within each PostToolUse entry only OUR hook * object is dropped (a user who added our command to a shared matcher group * keeps their other hooks); an entry whose hooks become empty is dropped; a * PostToolUse array that becomes empty is deleted; a `hooks` object that * becomes empty is deleted. Nothing else is touched. */ export declare function uninstallHook(settings: Settings): Settings; export {};