/** * Claude Code Hooks Bridge — AuthGuardian-gated tool calls for coding agents. * * Claude Code (and other hook-capable agent CLIs) can call an external * command on every tool use (PreToolUse / PostToolUse hooks). This module * turns Network-AI into that command: every tool call an agent makes is * audited — and optionally permission-gated — through the same * `AuthGuardian` weighted scoring used for swarm agents (justification 40%, * trust 30%, risk 30%). * * Two modes: * - `'observe'` (default) — every tool call is audit-logged, nothing is * blocked. Zero-risk visibility into what the agent is doing. * - `'enforce'` — tool calls are mapped to Network-AI resource types * (Bash → SHELL_EXEC, Write/Edit → FILE_SYSTEM, WebFetch → * EXTERNAL_SERVICE, …) and must pass `AuthGuardian.requestPermission()`. * Denied calls return `'ask'` (escalate to the human) or `'deny'`. * * Wire-up (Claude Code `settings.json`): * ```json * { * "hooks": { * "PreToolUse": [{ * "matcher": "Bash|Write|Edit|WebFetch", * "hooks": [{ "type": "command", * "command": "npx -y -p network-ai network-ai hook pre-tool-use --mode enforce" }] * }] * } * } * ``` * See `examples/claude-code-hooks.json` for a complete config. * * @module ClaudeHooks * @version 1.0.0 */ import { AuthGuardian } from './auth-guardian'; /** Hook events supported by the bridge */ export type ClaudeHookEvent = 'PreToolUse' | 'PostToolUse'; /** JSON payload Claude Code writes to the hook's stdin */ export interface ClaudeHookInput { /** Claude Code session identifier */ session_id?: string; /** Path to the session transcript */ transcript_path?: string; /** Working directory of the session */ cwd?: string; /** Which hook event fired */ hook_event_name: string; /** Tool being invoked — e.g. 'Bash', 'Write', 'mcp__github__create_issue' */ tool_name?: string; /** Tool input parameters (shape depends on the tool) */ tool_input?: Record; /** Tool response (PostToolUse only) */ tool_response?: unknown; } /** Permission decision for a PreToolUse hook */ export type HookPermissionDecision = 'allow' | 'deny' | 'ask'; /** JSON the bridge writes to stdout for PreToolUse */ export interface PreToolUseHookOutput { hookSpecificOutput: { hookEventName: 'PreToolUse'; permissionDecision: HookPermissionDecision; permissionDecisionReason: string; }; } /** Audit entry emitted for every processed hook call */ export interface HookAuditEntry { timestamp: string; event: ClaudeHookEvent; toolName: string; target: string; decision?: HookPermissionDecision; reason?: string; sessionId?: string; agentId: string; mode: 'observe' | 'enforce'; } /** Options for the ClaudeHookBridge */ export interface ClaudeHookBridgeOptions { /** Existing AuthGuardian to gate through. Auto-created in enforce mode if omitted. */ guardian?: AuthGuardian; /** Agent identity used for permission requests (default: 'claude-code') */ agentId?: string; /** 'observe' (audit only, default) or 'enforce' (AuthGuardian-gated) */ mode?: 'observe' | 'enforce'; /** Trust level for the auto-created guardian identity (default: 0.7) */ trustLevel?: number; /** Tool names / targets matching any of these are denied outright (checked first) */ denyPatterns?: Array; /** Tool names / targets matching any of these are allowed without gating */ allowPatterns?: Array; /** Override the tool → resource-type mapping (merged over the defaults) */ toolResourceMap?: Record; /** Decision to return when the guardian denies: 'ask' escalates to the human (default), 'deny' blocks */ blockedDecision?: 'deny' | 'ask'; /** JSONL file to append hook audit entries to (observe mode has no guardian log) */ auditLogPath?: string; /** Audit log path for the auto-created guardian (defaults to AuthGuardian's standard path) */ guardianAuditLogPath?: string; /** Trust config path for the auto-created guardian */ trustConfigPath?: string; /** * Maximum length (in characters) of the extracted target string that will * be evaluated for deny/allow pattern matching. Targets longer than this * are DENIED outright (fail closed) instead of matched. This closes the * truncation-vs-execution mismatch where a security decision made against * a shortened preview could differ from the full command Claude Code * actually executes (GHSA-743h-jr5x-mpcr), and bounds regex evaluation * cost against unbounded attacker-supplied strings. Default: 65536 (64 KiB) * — far beyond any realistic single command/path/URL/prompt field. */ maxTargetLength?: number; /** Callback invoked with every audit entry */ onAudit?: (entry: HookAuditEntry) => void; } /** * Default mapping from Claude Code tool names to Network-AI resource types. * MCP tools (`mcp__*`) and unknown tools map to EXTERNAL_SERVICE. */ export declare const DEFAULT_TOOL_RESOURCE_MAP: Record; /** * Bridges coding-agent hook events (Claude Code PreToolUse / PostToolUse) * into Network-AI's AuthGuardian permission system and audit trail. */ export declare class ClaudeHookBridge { private readonly guardian; private readonly agentId; private readonly mode; private readonly denyPatterns; private readonly allowPatterns; private readonly toolResourceMap; private readonly blockedDecision; private readonly auditLogPath; private readonly onAudit; private readonly maxTargetLength; constructor(options?: ClaudeHookBridgeOptions); /** * Parse a raw hook stdin payload. Tolerates a leading UTF-8 BOM (some * shells prepend one when piping). Throws on malformed JSON or a payload * that is not an object. */ static parseInput(raw: string): ClaudeHookInput; /** * Handle a PreToolUse event: decide allow / deny / ask. * * Decision order: denyPatterns → allowPatterns → observe-mode allow → * AuthGuardian permission request (enforce mode). */ handlePreToolUse(input: ClaudeHookInput): Promise; /** * Handle a PostToolUse event: audit the completed call. Never blocks. * Returns an empty object (the hook-protocol no-op). */ handlePostToolUse(input: ClaudeHookInput): Promise>; /** * Dispatch a hook input by its `hook_event_name`. */ handle(input: ClaudeHookInput): Promise>; private decide; private audit; } //# sourceMappingURL=claude-hooks.d.ts.map