第一节:Hooks 概述与类型
Hook 系统与核心概念

作者:小学子 📚 | 日期:2026年4月2日 | 第六阶段 · 模块六


# 第六阶段 · 模块六 · 第一节:Hooks 概述与类型

核心问题

什么是 Hooks?Claude Code 支持哪些 Hook 事件?每个事件的触发时机和作用是什么?


◇ 本节位置


        Claude Code 全局架构
        
        ┌─────────────────────────────────────────────────────────────────────┐
        │  Hooks 系统 ← 本节                                                  │
        │                                                                      │
        │  HookEvent ──> 事件类型定义                                        │
        │  HookHandler ──> 事件处理器                                        │
        │  hookEvents.ts ──> 事件常量                                        │
        └─────────────────────────────────────────────────────────────────────┘
        


一、Hooks 概述

1.1 什么是 Hooks


        Hooks = 生命周期钩子
        
        在 Claude Code 运行过程中的特定时机插入自定义逻辑
        
        ┌─────────────────────────────────────────────────────────────────────┐
        │  用户输入 ──> UserPromptSubmit Hook ──> AI 处理                  │
        │                                                                      │
        │  AI 决定 ──> ToolCall ──> PreToolUse Hook ──> 工具执行           │
        │                                                                      │
        │  工具执行 ──> PostToolUse Hook ──> 返回结果                       │
        └─────────────────────────────────────────────────────────────────────┘
        

1.2 Hooks 的作用


        // Hooks 可以:
        // 1. 在事件前后执行自定义逻辑
        // 2. 修改输入/输出
        // 3. 阻止或允许操作
        // 4. 记录日志或指标
        // 5. 触发副作用
        

1.3 五问分析

问 1:Hooks 和插件的区别?


        // Hooks:事件驱动的拦截点
        // 插件:功能模块的扩展
        
        // Hook 适合:
        // - 修改行为(拦截工具调用)
        // - 添加验证(日志、审计)
        // - 注入逻辑(修改输入输出)
        
        // 插件适合:
        // - 添加新功能
        // - 打包多个 Hooks
        // - 分发独立模块
        


二、HookEvent 类型

2.1 完整事件列表

源码位置:`src/entrypoints/sdk/coreTypes.ts` 第 25 行


        export const HOOK_EVENTS = [
          // 工具相关
          'PreToolUse',           // 工具执行前
          'PostToolUse',          // 工具执行后
          'PostToolUseFailure',   // 工具执行失败
        
          // 消息相关
          'UserPromptSubmit',     // 用户提交消息
          'Notification',         // 通知
        
          // 会话相关
          'SessionStart',         // 会话开始
          'SessionEnd',           // 会话结束
        
          // 控制流
          'Stop',                 // 停止生成
          'StopFailure',         // 停止失败
        
          // 子代理
          'SubagentStart',       // 子代理启动
          'SubagentStop',        // 子代理停止
        
          // 压缩相关
          'PreCompact',          // 压缩前
          'PostCompact',         // 压缩后
        
          // 权限相关
          'PermissionRequest',   // 权限请求
          'PermissionDenied',     // 权限被拒绝
        
          // 任务相关
          'TaskCreated',         // 任务创建
          'TaskCompleted',       // 任务完成
        
          // 其他
          'Elicitation',         // 提示用户选择
          'ElicitationResult',   // 选择结果
          'Setup',               // 初始化设置
          'ConfigChange',         // 配置变更
          'CwdChanged',          // 工作目录变更
          'WorktreeCreate',      // Git worktree 创建
          'WorktreeRemove',      // Git worktree 删除
          'InstructionsLoaded',   // 指令加载
          'TeammateIdle',        // 队友空闲
        ]
        

2.2 工具相关 Hooks

PreToolUse


        // 触发时机:工具执行前
        // 源码位置:src/types/hooks.ts 第 73 行
        
        type PreToolUseHook = {
          hookEventName: 'PreToolUse'
          toolName: string           // 工具名
          toolInput: object          // 工具输入
          sessionId: string          // 会话 ID
          invocationId: string        // 调用 ID
        }
        
        // 可返回
        {
          continue?: boolean         // 是否继续执行
          updatedInput?: object      // 修改后的输入
          additionalContext?: string // 额外上下文
          permissionDecision?: {
            behavior: 'allow' | 'deny' | 'pause'
            reason?: string
          }
        }
        

PostToolUse


        // 触发时机:工具执行后(成功)
        // 源码位置:src/types/hooks.ts 第 101 行
        
        type PostToolUseHook = {
          hookEventName: 'PostToolUse'
          toolName: string
          toolInput: object
          toolOutput: unknown         // 工具返回结果
          wasRateLimited?: boolean   // 是否被限流
          invocationId: string
        }
        
        // 可返回
        {
          continue?: boolean
          updatedMCPToolOutput?: unknown  // 修改 MCP 工具输出
          additionalContext?: string
        }
        

PostToolUseFailure


        // 触发时机:工具执行失败
        // 源码位置:src/types/hooks.ts 第 109 行
        
        type PostToolUseFailureHook = {
          hookEventName: 'PostToolUseFailure'
          toolName: string
          toolInput: object
          error: string              // 错误消息
          errorCode?: string          // 错误码
          invocationId: string
        }
        

2.3 五问分析

问 1:PreToolUse 和 PostToolUse 的区别?


        // PreToolUse:在工具执行前
        // - 可以修改输入参数
        // - 可以阻止执行
        // - 可以决定权限(allow/deny/pause)
        
        // PostToolUse:在工具执行后
        // - 可以读取输出
        // - 可以修改输出(仅 MCP 工具)
        // - 不能阻止执行(已执行完)
        


三、消息与会话 Hooks

3.1 UserPromptSubmit


        // 触发时机:用户提交消息后,发送给 AI 前
        // 源码位置:src/types/hooks.ts 第 80 行
        
        type UserPromptSubmitHook = {
          hookEventName: 'UserPromptSubmit'
          userPrompt: string         // 用户输入
          promptElicitation?: {      // 提示选择
            id: string
            message: string
            options: Array<{
              key: string
              label: string
              description?: string
            }>
          }
        }
        
        // 可返回
        {
          continue?: boolean
          userPrompt?: string         // 修改后的 prompt
          additionalContext?: string
        }
        

3.2 SessionStart / SessionEnd


        // SessionStart:会话开始时
        // SessionEnd:会话结束时
        
        type SessionHook = {
          hookEventName: 'SessionStart' | 'SessionEnd'
          sessionId: string
          initialUserMessage?: string  // 初始消息(仅 SessionStart)
          additionalContext?: string
        }
        

3.3 五问分析

问 1:SessionStart 可以做什么?


        // 初始化操作
        export const sessionStart: HookHandler = async (input) => {
          // 加载会话特定配置
          await loadSessionConfig(input.sessionId)
        
          // 初始化资源
          await initializeResources()
        
          // 添加会话上下文
          return {
            continue: true,
            additionalContext: 'Session initialized at ' + new Date().toISOString()
          }
        }
        


四、权限相关 Hooks

4.1 PermissionRequest


        // 触发时机:工具需要权限时
        // 源码位置:src/types/hooks.ts 第 121 行
        
        type PermissionRequestHook = {
          hookEventName: 'PermissionRequest'
          toolName: string
          toolInput: object
          permission: {
            type: string       // 权限类型
            reason: string     // 为什么需要
          }
          prompt?: string      // 提示用户的信息
          invocationId: string
        }
        
        // 可返回
        {
          decision: {
            behavior: 'allow' | 'deny' | 'pause'
            updatedInput?: object       // 修改输入
            updatedPermissions?: PermissionUpdate[]
            message?: string
            interrupt?: boolean        // 是否中断
          }
        }
        

4.2 PermissionDenied


        // 触发时机:权限被拒绝时
        
        type PermissionDeniedHook = {
          hookEventName: 'PermissionDenied'
          toolName: string
          toolInput: object
          permission: {
            type: string
            reason: string
          }
          retry?: boolean    // 是否可以重试
        }
        

4.3 五问分析

问 1:allow、deny、pause 的区别?


        // allow:自动批准,继续执行
        // deny:拒绝执行,记录拒绝
        // pause:暂停,等待用户确认
        
        // interrupt: true:在 pause 时也中断流程
        


五、压缩相关 Hooks

5.1 PreCompact / PostCompact


        // PreCompact:上下文压缩前
        // PostCompact:上下文压缩后
        
        type CompactHook = {
          hookEventName: 'PreCompact' | 'PostCompact'
          messages: Message[]         // 当前消息列表
          reason: string              // 压缩原因
          additionalContext?: string
        }
        


六、思考题

思考题 1:如何选择合适的 Hook?

答案


        // 需要修改输入 → PreToolUse
        // 需要读取输出 → PostToolUse
        // 需要验证权限 → PermissionRequest
        // 需要记录日志 → PostToolUse
        // 需要修改 prompt → UserPromptSubmit
        


思考题 2:多个 Hook 执行顺序?

答案


        // 按配置顺序执行
        // 如果某个 Hook 返回 continue: false,后续 Hook 不执行
        
        // 配置
        hooks:
          PreToolUse:
            - hook1.ts  // 先执行
            - hook2.ts  // 后执行
        
        // hook1 返回 continue: false
        // → hook2 不执行
        


思考题 3:Hook 失败会中断流程吗?

答案


        // 取决于错误类型
        // - 同步错误:可能中断
        // - 返回 { continue: true } 即使出错:继续
        
        // 最佳实践
        export const myHook: HookHandler = async (input) => {
          try {
            return await process(input)
          } catch (error) {
            logError(error)
            return { continue: true }  // 不阻塞流程
          }
        }
        


七、延伸阅读

文件核心内容
`src/entrypoints/sdk/coreTypes.ts`HOOK_EVENTS 定义
`src/types/hooks.ts`Hook 类型定义
`src/utils/hooks/hookEvents.ts`事件发射逻辑


八、下节预告

下一节我们将深入 内置 Hooks 详解

- PreToolUse 完整参数

- PostToolUse 完整参数

- PermissionRequest 完整参数


*- 第一轮:□ 事实准确性*

*- 第二轮:□ 深度与洞见*

*- 第三轮:□ 可读性与价值*