Claude Code 源码分析Claude Code 源码分析
首页
源码统计
系统架构
UML 图表
工具系统
CodeGraph
首页
源码统计
系统架构
UML 图表
工具系统
CodeGraph
  • 概览

    • Claude Code 源码分析
    • 源码统计
    • CodeGraph 图谱
  • 架构

    • 系统架构
    • UML 图表索引
    • 查询引擎
    • 核心流程
    • 消息系统
    • 状态管理
  • 功能模块

    • 工具系统
    • 斜杠命令
    • 服务层
    • MCP 协议
    • Skills 技能
    • 子代理系统
  • 分层深度

    • 入口层
    • UI / Ink 层
    • utils 基础设施
    • 桥接 / 远程
    • 上下文压缩
  • 原理与安全

    • 底层原理
    • 技术难点
    • 权限与安全
    • 内部机制
    • 遥测与分析
  • 深度专题

    • Hooks 系统
    • 插件系统
    • 记忆系统
    • API 通信层
    • Ink 终端 UI
    • 认证系统
    • 构建与发布
    • 术语表
  • 调用分析

    • 调用链分析
    • 核心文件索引
  • 模块详解

    • utils

      • 模块: utils
      • messages · 消息工厂与规范化
      • session-storage · JSONL 会话持久化
      • permissions · 工具权限决策
      • shell-hooks · 用户 Shell Hook 系统
    • components

      • 模块: components
      • REPL · 主屏编排
      • messages · 消息行渲染
      • PermissionRequest · 权限弹窗
      • PromptInput · 底部输入
    • services

      • 模块: services
      • api-claude · Anthropic API 流式与重试
      • mcp-client · MCP 连接与工具调用
      • compact · 上下文压缩与自动触发
      • analytics · GrowthBook、Datadog 与 1P 事件
    • tools

      • 模块: tools
      • tool-interface · Tool 契约与注册表
      • bash-tool · Shell 执行与权限
      • streaming-executor · 流式工具并发调度
      • agent-tool · 子 Agent 委派
    • commands

      • 模块: commands
      • command-registry · commands.ts 注册与分派
      • model-command · /model 模型选择
      • mcp-commands · /mcp 服务器管理
      • compact-memory-commands · /compact 与 /memory
    • ink

      • 模块: ink
      • Ink 渲染管线 · Screen 与终端输出
      • 终端事件 · resize、paste、stdin
      • Ink Hooks · 输入、搜索、终端状态
      • Ink 组件 · Box、Text、ScrollBox 原语
    • hooks

      • 模块: hooks
      • useCanUseTool · 权限 UI 接缝
      • 输入与快捷键 Hook
      • 合并态 Hook(MCP + 本地)
      • notifs 通知 Hook
    • bridge

      • 模块: bridge
      • repl-bridge · REPL 桥初始化与传输
      • bridge-messaging · 桥消息路由与入站处理
      • remote-bridge-core · env-less 核心与守护主循环
      • bridge-permissions-ui · 权限、API 与 TUI
    • cli

      • 模块: cli
      • Structured IO · NDJSON SDK 协议
      • CLI Transports · Session Ingress 传输层
      • CLI Handlers · 子命令懒加载实现
      • Update & Upload · 自更新与串行上传原语
    • screens

      • 模块: screens
      • REPL 屏 · Screen 类型与顶层路由
      • ResumeConversation · 会话恢复选择器
      • Doctor · 安装诊断全屏
    • entrypoints

      • 模块: entrypoints
      • cli-entrypoint · Bootstrap 与快路径
      • sdk-types · core / control / runtime 类型体系
      • mcp-entrypoint · MCP stdio 服务器
      • sandbox-types · 沙箱配置单一真相源
    • skills

      • 模块: skills
      • skills-loading · 磁盘加载与 bundled 注册表
      • bundled-skills · 内置 skill 与 initBundledSkills
      • mcp-skills · MCP prompt 转 skill
      • skill-tool-integration · SkillTool 与命令注册
    • types

      • 模块: types
      • message-types · Message 联合与 content blocks
      • tool-permission-types · Tool、Permission、Command 类型
      • api-sdk-types · API 与 Hooks 协议类型
      • misc-types · ids、plugin、generated 与其余类型
    • tasks

      • 模块: tasks
      • local-agent-task · 本地 Agent 与主会话后台化
      • remote-agent-task · 远程 CCR 与 In-Process Teammate
      • shell-workflow-tasks · Bash 后台、Workflow 与 stopTask
      • dream-monitor-tasks · Dream、Monitor MCP 与 pill 文案
    • keybindings

      • 模块: keybindings
      • keybinding-registry · 注册、Provider 与 useKeybinding
      • default-bindings · 默认键位表与平台差异
      • command-bindings · command:* 动态斜杠命令绑定
      • vim-bindings · Vim 模式与 keybindings 边界
    • memdir

      • 模块: memdir
      • memdir-core · 路径、加载与 MEMORY.md
      • memory-extraction · extractMemories 与 SessionMemory
      • memdir-commands · /memory、/remember 与命令集成
    • state

      • 模块: state
      • app-state-core · store、AppState 类型与 Provider
      • app-state-selectors · selectors 与 onChangeAppState
      • teammate-state · 队友视图与 swarm 状态
      • state-boundaries · bootstrap、sessionStorage、FileStateCache
    • query

      • 模块: query
      • query config 与 deps · 配置快照与依赖注入
      • query tokenBudget · +500k 自动续跑
      • query transitions · Continue / Terminal 状态机
      • query stopHooks · Stop 事件与 turn 结束编排
  • 模块详解(扩展)

    • messages · 消息工厂与规范化
    • session-storage · JSONL 会话持久化
    • permissions · 工具权限决策
    • shell-hooks · 用户 Shell Hook 系统
    • REPL · 主屏编排
    • messages · 消息行渲染
    • PermissionRequest · 权限弹窗
    • PromptInput · 底部输入
    • api-claude · Anthropic API 流式与重试
    • mcp-client · MCP 连接与工具调用
    • compact · 上下文压缩与自动触发
    • analytics · GrowthBook、Datadog 与 1P 事件
    • tool-interface · Tool 契约与注册表
    • bash-tool · Shell 执行与权限
    • streaming-executor · 流式工具并发调度
    • agent-tool · 子 Agent 委派
    • command-registry · commands.ts 注册与分派
    • model-command · /model 模型选择
    • mcp-commands · /mcp 服务器管理
    • compact-memory-commands · /compact 与 /memory
    • Ink 渲染管线 · Screen 与终端输出
    • 终端事件 · resize、paste、stdin
    • Ink Hooks · 输入、搜索、终端状态
    • Ink 组件 · Box、Text、ScrollBox 原语
    • useCanUseTool · 权限 UI 接缝
    • 输入与快捷键 Hook
    • 合并态 Hook(MCP + 本地)
    • notifs 通知 Hook
    • repl-bridge · REPL 桥初始化与传输
    • bridge-messaging · 桥消息路由与入站处理
    • remote-bridge-core · env-less 核心与守护主循环
    • bridge-permissions-ui · 权限、API 与 TUI
    • Structured IO · NDJSON SDK 协议
    • CLI Transports · Session Ingress 传输层
    • CLI Handlers · 子命令懒加载实现
    • Update & Upload · 自更新与串行上传原语
    • REPL 屏 · Screen 类型与顶层路由
    • ResumeConversation · 会话恢复选择器
    • Doctor · 安装诊断全屏
    • cli-entrypoint · Bootstrap 与快路径
    • sdk-types · core / control / runtime 类型体系
    • mcp-entrypoint · MCP stdio 服务器
    • sandbox-types · 沙箱配置单一真相源
    • skills-loading · 磁盘加载与 bundled 注册表
    • bundled-skills · 内置 skill 与 initBundledSkills
    • mcp-skills · MCP prompt 转 skill
    • skill-tool-integration · SkillTool 与命令注册
    • message-types · Message 联合与 content blocks
    • tool-permission-types · Tool、Permission、Command 类型
    • api-sdk-types · API 与 Hooks 协议类型
    • misc-types · ids、plugin、generated 与其余类型
    • local-agent-task · 本地 Agent 与主会话后台化
    • remote-agent-task · 远程 CCR 与 In-Process Teammate
    • shell-workflow-tasks · Bash 后台、Workflow 与 stopTask
    • dream-monitor-tasks · Dream、Monitor MCP 与 pill 文案
    • keybinding-registry · 注册、Provider 与 useKeybinding
    • default-bindings · 默认键位表与平台差异
    • command-bindings · command:* 动态斜杠命令绑定
    • vim-bindings · Vim 模式与 keybindings 边界
    • memdir-core · 路径、加载与 MEMORY.md
    • memory-extraction · extractMemories 与 SessionMemory
    • memdir-commands · /memory、/remember 与命令集成
    • app-state-core · store、AppState 类型与 Provider
    • app-state-selectors · selectors 与 onChangeAppState
    • teammate-state · 队友视图与 swarm 状态
    • state-boundaries · bootstrap、sessionStorage、FileStateCache
    • query config 与 deps · 配置快照与依赖注入
    • query tokenBudget · +500k 自动续跑
    • query transitions · Continue / Terminal 状态机
    • query stopHooks · Stop 事件与 turn 结束编排
  • 工具详解

    • tool-interface · Tool 契约与注册表
    • tool-permission-types · Tool、Permission、Command 类型
    • 工具: Bash
    • 工具: PowerShell
    • 工具: Agent
    • 工具: LSP
    • 工具: FileEdit
    • 工具: FileRead
    • 工具: Skill
    • 工具: WebFetch
    • 工具: MCP
    • 工具: SendMessage
    • 工具: FileWrite
    • 工具: Config
    • 工具: Grep
    • 工具: Brief
    • 工具: ExitPlanMode
    • 工具: ToolSearch
    • 工具: NotebookEdit
    • 工具: TaskOutput
    • 工具: WebSearch
    • 工具: ScheduleCron

本章总览

先把握主线:api-sdk-types 定义了 Claude Code 与外部 Hook/SDK 之间的 JSON 协议边界,目标是“外部可扩展、内部可校验”。围绕这一主线,types/hooks.ts 提供 Zod 校验与事件细分输出,entrypoints/agentSdkTypes.ts 提供稳定 SDK 面,types/logs.ts 补充 resume/analytics 所需类型。

学完本章你应该能

  • 理解 hooks.ts 与 agentSdkTypes 的分工与 import 方向
  • 列举 syncHookResponseSchema 的 continue/decision/hookSpecificOutput 字段
  • 说明 PreToolUse hookSpecificOutput 如何携带 permissionDecision
  • 知道 PromptRequest/PromptResponse 与 async hook 的关系
  • 理解 isHookEvent 与 HOOK_EVENTS 运行时校验
  • 能在 utils/hooks 执行层找到 JSON parse 与 schema 的对应

核心概念(先读懂这些)

agentSdkTypes 是对外 SDK 面,hooks.ts 是内部扩展

entrypoints/agentSdkTypes.ts 打包给 @anthropic-ai/claude-agent-sdk 消费者,定义 HOOK_EVENTS、HookJSONOutput、PermissionUpdate 等稳定 API。types/hooks.ts 添加 zod lazySchema、与 AppState/Message 的交叉引用、以及更细的 hookSpecificOutput 变体——内部 REPL 与 CLI 使用完整 schema,SDK 导出子集。

hookSpecificOutput 是 per-event 判别联合

PreToolUse 可返回 permissionDecision、updatedInput、additionalContext。SessionStart 可带 initialUserMessage、watchPaths。PermissionRequest 嵌套 allow/deny decision 与 updatedPermissions 数组。Elicitation 与 ElicitationResult 配对处理 MCP elicitation UI。Zod union 保证 CLI hook 脚本输出可校验。

lazySchema 避免启动时全量编译 Zod

promptRequestSchema、syncHookResponseSchema 用 lazySchema(() => z.object(...)) 延迟构建,降低冷启动。与 utils/lazySchema.js 配合,settings 加载路径不 eagerly parse 巨大 hook schema。

建议学习步骤

  1. 阅读 hooks.ts 顶部 import 与 isHookEvent
  2. 浏览 syncHookResponseSchema 完整 union
  3. 对照 agentSdkTypes HookEvent 列表
  4. 阅读 PermissionRequest hookSpecificOutput 分支
  5. 查看 logs.ts LogOption 定义
  6. 在 postSamplingHooks 搜索 HookJSONOutput 消费

常见误区

注意

organizeImports 不可打乱 hooks.ts 的 ANT-ONLY import 标记

注意

AsyncHookJSONOutput 与 SyncHookJSONOutput 在 agentSdkTypes 分离

注意

PermissionUpdate schema 在 PermissionUpdateSchema.js,types 层仅 re-export 类型

注意

改 HookEvent 枚举需同步 SDK 文档与外部 hook 脚本示例

hooks.ts 依赖图

entrypoints/agentSdkTypes.ts  (HookEvent, HookInput, PermissionUpdate types)
        ↓
types/hooks.ts  (zod schemas + PromptRequest + extended hookSpecificOutput)
        ↓
utils/hooks/*, services/hooks, CLI hook runner
        ↓
types/message.ts, state/AppState, PermissionResult

isHookEvent(value) 用 HOOK_EVENTS.includes 做 string 窄化,settings.json hooks 配置校验与 Doctor 诊断共用。

源码引用: src/types/hooks.ts · 第 1–24 行(共 291 行)

   1| // biome-ignore-all assist/source/organizeImports: ANT-ONLY import markers must not be reordered
   2| import { z } from 'zod/v4'
   3| import { lazySchema } from '../utils/lazySchema.js'
   4| import {
   5|   type HookEvent,
   6|   HOOK_EVENTS,
   7|   type HookInput,
   8|   type PermissionUpdate,
   9| } from 'src/entrypoints/agentSdkTypes.js'
  10| import type {
  11|   HookJSONOutput,
  12|   AsyncHookJSONOutput,
  13|   SyncHookJSONOutput,
  14| } from 'src/entrypoints/agentSdkTypes.js'
  15| import type { Message } from 'src/types/message.js'
  16| import type { PermissionResult } from 'src/utils/permissions/PermissionResult.js'
  17| import { permissionBehaviorSchema } from 'src/utils/permissions/PermissionRule.js'
  18| import { permissionUpdateSchema } from 'src/utils/permissions/PermissionUpdateSchema.js'
  19| import type { AppState } from '../state/AppState.js'
  20| import type { AttributionState } from '../utils/commitAttribution.js'
  21| 
  22| export function isHookEvent(value: string): value is HookEvent {
  23|   return HOOK_EVENTS.includes(value as HookEvent)
  24| }

源码引用: src/types/hooks.ts · 第 22–24 行(共 291 行)

  22| export function isHookEvent(value: string): value is HookEvent {
  23|   return HOOK_EVENTS.includes(value as HookEvent)
  24| }

Prompt elicitation 协议

promptRequestSchema 定义 prompt(request id)、message、options[{ key, label, description? }]。PromptResponse 返回 prompt_response + selected。

与 async hook 的 {async:true} 模式类似,prompt 键作 discriminator。REPL 渲染选项列表,用户选择后 stdin 回写 JSON 给 hook 进程。SDK 消费者可实现相同协议嵌入自定义 UI。

源码引用: src/types/hooks.ts · 第 26–47 行(共 291 行)

  26| // Prompt elicitation protocol types. The `prompt` key acts as discriminator
  27| // (mirroring the {async:true} pattern), with the id as its value.
  28| export const promptRequestSchema = lazySchema(() =>
  29|   z.object({
  30|     prompt: z.string(), // request id
  31|     message: z.string(),
  32|     options: z.array(
  33|       z.object({
  34|         key: z.string(),
  35|         label: z.string(),
  36|         description: z.string().optional(),
  37|       }),
  38|     ),
  39|   }),
  40| )
  41| 
  42| export type PromptRequest = z.infer<ReturnType<typeof promptRequestSchema>>
  43| 
  44| export type PromptResponse = {
  45|   prompt_response: string // request id
  46|   selected: string
  47| }

syncHookResponseSchema 核心字段

字段作用
continue默认 true;false 时停止主循环
suppressOutput隐藏 stdout 不进 transcript
stopReasoncontinue false 时展示原因
decisionapprove / block(部分 event)
systemMessage用户可见警告
hookSpecificOutput按 hookEventName 变体

UserPromptSubmit 仅 additionalContext。PostToolUse 可 updatedMCPToolOutput。PermissionDenied 可 retry。

源码引用: src/types/hooks.ts · 第 49–75 行(共 291 行)

  49| // Sync hook response schema
  50| export const syncHookResponseSchema = lazySchema(() =>
  51|   z.object({
  52|     continue: z
  53|       .boolean()
  54|       .describe('Whether Claude should continue after hook (default: true)')
  55|       .optional(),
  56|     suppressOutput: z
  57|       .boolean()
  58|       .describe('Hide stdout from transcript (default: false)')
  59|       .optional(),
  60|     stopReason: z
  61|       .string()
  62|       .describe('Message shown when continue is false')
  63|       .optional(),
  64|     decision: z.enum(['approve', 'block']).optional(),
  65|     reason: z.string().describe('Explanation for the decision').optional(),
  66|     systemMessage: z
  67|       .string()
  68|       .describe('Warning message shown to the user')
  69|       .optional(),
  70|     hookSpecificOutput: z
  71|       .union([
  72|         z.object({
  73|           hookEventName: z.literal('PreToolUse'),
  74|           permissionDecision: permissionBehaviorSchema().optional(),
  75|           permissionDecisionReason: z.string().optional(),

源码引用: src/types/hooks.ts · 第 70–120 行(共 291 行)

  70|     hookSpecificOutput: z
  71|       .union([
  72|         z.object({
  73|           hookEventName: z.literal('PreToolUse'),
  74|           permissionDecision: permissionBehaviorSchema().optional(),
  75|           permissionDecisionReason: z.string().optional(),
  76|           updatedInput: z.record(z.string(), z.unknown()).optional(),
  77|           additionalContext: z.string().optional(),
  78|         }),
  79|         z.object({
  80|           hookEventName: z.literal('UserPromptSubmit'),
  81|           additionalContext: z.string().optional(),
  82|         }),
  83|         z.object({
  84|           hookEventName: z.literal('SessionStart'),
  85|           additionalContext: z.string().optional(),
  86|           initialUserMessage: z.string().optional(),
  87|           watchPaths: z
  88|             .array(z.string())
  89|             .describe('Absolute paths to watch for FileChanged hooks')
  90|             .optional(),
  91|         }),
  92|         z.object({
  93|           hookEventName: z.literal('Setup'),
  94|           additionalContext: z.string().optional(),
  95|         }),
  96|         z.object({
  97|           hookEventName: z.literal('SubagentStart'),
  98|           additionalContext: z.string().optional(),
  99|         }),
 100|         z.object({
 101|           hookEventName: z.literal('PostToolUse'),
 102|           additionalContext: z.string().optional(),
 103|           updatedMCPToolOutput: z
 104|             .unknown()
 105|             .describe('Updates the output for MCP tools')
 106|             .optional(),
 107|         }),
 108|         z.object({
 109|           hookEventName: z.literal('PostToolUseFailure'),
 110|           additionalContext: z.string().optional(),
 111|         }),
 112|         z.object({
 113|           hookEventName: z.literal('PermissionDenied'),
 114|           retry: z.boolean().optional(),
 115|         }),
 116|         z.object({
 117|           hookEventName: z.literal('Notification'),
 118|           additionalContext: z.string().optional(),
 119|         }),
 120|         z.object({

PermissionRequest 与 SessionStart

PermissionRequest hookSpecificOutput.decision 是 allow/deny 判别联合:

  • allow:可选 updatedInput、updatedPermissions(PermissionUpdate[])
  • deny:message、interrupt

SessionStart 可注入 initialUserMessage(自动提交首条 user 消息)、watchPaths(FileChanged hook 监视列表)。

这些类型直接驱动 useCanUseTool 与 permission dialog 的「hook 已决策」快速路径。

源码引用: src/types/hooks.ts · 第 84–134 行(共 291 行)

  84|           hookEventName: z.literal('SessionStart'),
  85|           additionalContext: z.string().optional(),
  86|           initialUserMessage: z.string().optional(),
  87|           watchPaths: z
  88|             .array(z.string())
  89|             .describe('Absolute paths to watch for FileChanged hooks')
  90|             .optional(),
  91|         }),
  92|         z.object({
  93|           hookEventName: z.literal('Setup'),
  94|           additionalContext: z.string().optional(),
  95|         }),
  96|         z.object({
  97|           hookEventName: z.literal('SubagentStart'),
  98|           additionalContext: z.string().optional(),
  99|         }),
 100|         z.object({
 101|           hookEventName: z.literal('PostToolUse'),
 102|           additionalContext: z.string().optional(),
 103|           updatedMCPToolOutput: z
 104|             .unknown()
 105|             .describe('Updates the output for MCP tools')
 106|             .optional(),
 107|         }),
 108|         z.object({
 109|           hookEventName: z.literal('PostToolUseFailure'),
 110|           additionalContext: z.string().optional(),
 111|         }),
 112|         z.object({
 113|           hookEventName: z.literal('PermissionDenied'),
 114|           retry: z.boolean().optional(),
 115|         }),
 116|         z.object({
 117|           hookEventName: z.literal('Notification'),
 118|           additionalContext: z.string().optional(),
 119|         }),
 120|         z.object({
 121|           hookEventName: z.literal('PermissionRequest'),
 122|           decision: z.union([
 123|             z.object({
 124|               behavior: z.literal('allow'),
 125|               updatedInput: z.record(z.string(), z.unknown()).optional(),
 126|               updatedPermissions: z.array(permissionUpdateSchema()).optional(),
 127|             }),
 128|             z.object({
 129|               behavior: z.literal('deny'),
 130|               message: z.string().optional(),
 131|               interrupt: z.boolean().optional(),
 132|             }),
 133|           ]),
 134|         }),

源码引用: src/types/hooks.ts · 第 84–91 行(共 291 行)

  84|           hookEventName: z.literal('SessionStart'),
  85|           additionalContext: z.string().optional(),
  86|           initialUserMessage: z.string().optional(),
  87|           watchPaths: z
  88|             .array(z.string())
  89|             .describe('Absolute paths to watch for FileChanged hooks')
  90|             .optional(),
  91|         }),

agentSdkTypes 入口类型

entrypoints/agentSdkTypes.ts 导出 SDK 稳定面:HookEvent 字符串联合、HookInput(含 transcript 快照)、HookJSONOutput、AsyncHookJSONOutput。

MCP entrypoint、sandbox types、cli structured IO 从 entrypoints/ 并列导出——types/hooks.ts 不重复定义 HookEvent,避免双源真相。

外部集成应 import SDK 包类型;阅读 Claude Code 源码时以 agentSdkTypes + hooks.ts 对照。

源码引用: src/entrypoints/agentSdkTypes.ts · 第 1–80 行(共 444 行)

   1| /**
   2|  * Main entrypoint for Claude Code Agent SDK types.
   3|  *
   4|  * This file re-exports the public SDK API from:
   5|  * - sdk/coreTypes.ts - Common serializable types (messages, configs)
   6|  * - sdk/runtimeTypes.ts - Non-serializable types (callbacks, interfaces)
   7|  *
   8|  * SDK builders who need control protocol types should import from
   9|  * sdk/controlTypes.ts directly.
  10|  */
  11| 
  12| import type {
  13|   CallToolResult,
  14|   ToolAnnotations,
  15| } from '@modelcontextprotocol/sdk/types.js'
  16| 
  17| // Control protocol types for SDK builders (bridge subpath consumers)
  18| /** @alpha */
  19| export type {
  20|   SDKControlRequest,
  21|   SDKControlResponse,
  22| } from './sdk/controlTypes.js'
  23| // Re-export core types (common serializable types)
  24| export * from './sdk/coreTypes.js'
  25| // Re-export runtime types (callbacks, interfaces with methods)
  26| export * from './sdk/runtimeTypes.js'
  27| 
  28| // Re-export settings types (generated from settings JSON schema)
  29| export type { Settings } from './sdk/settingsTypes.generated.js'
  30| // Re-export tool types (all marked @internal until SDK API stabilizes)
  31| export * from './sdk/toolTypes.js'
  32| 
  33| // ============================================================================
  34| // Functions
  35| // ============================================================================
  36| 
  37| import type {
  38|   SDKMessage,
  39|   SDKResultMessage,
  40|   SDKSessionInfo,
  41|   SDKUserMessage,
  42| } from './sdk/coreTypes.js'
  43| // Import types needed for function signatures
  44| import type {
  45|   AnyZodRawShape,
  46|   ForkSessionOptions,
  47|   ForkSessionResult,
  48|   GetSessionInfoOptions,
  49|   GetSessionMessagesOptions,
  50|   InferShape,
  51|   InternalOptions,
  52|   InternalQuery,
  53|   ListSessionsOptions,
  54|   McpSdkServerConfigWithInstance,
  55|   Options,
  56|   Query,
  57|   SDKSession,
  58|   SDKSessionOptions,
  59|   SdkMcpToolDefinition,
  60|   SessionMessage,
  61|   SessionMutationOptions,
  62| } from './sdk/runtimeTypes.js'
  63| 
  64| export type {
  65|   ListSessionsOptions,
  66|   GetSessionInfoOptions,
  67|   SessionMutationOptions,
  68|   ForkSessionOptions,
  69|   ForkSessionResult,
  70|   SDKSessionInfo,
  71| }
  72| 
  73| export function tool<Schema extends AnyZodRawShape>(
  74|   _name: string,
  75|   _description: string,
  76|   _inputSchema: Schema,
  77|   _handler: (
  78|     args: InferShape<Schema>,
  79|     extra: unknown,
  80|   ) => Promise<CallToolResult>,

源码缺失

File not found: c:\Users\123\Desktop\jd\Claude code源码\claude-code-complete\claude-code-complete\src-readable\entrypoints\sdk-types.ts

logs.ts 与 resume API

LogOption 控制 resume/load transcript 时的日志粒度(silent/verbose 等变体),LocalJSXCommandContext.resume 与 CLI --resume 共用。

类型保持最小——resume 参数组合在 command.ts ResumeEntrypoint 与 logs.ts 交叉引用,analytics 用 entrypoint 标记来源。

源码引用: src/types/logs.ts · 第 1–30 行(共 331 行)

   1| import type { UUID } from 'crypto'
   2| import type { FileHistorySnapshot } from 'src/utils/fileHistory.js'
   3| import type { ContentReplacementRecord } from 'src/utils/toolResultStorage.js'
   4| import type { AgentId } from './ids.js'
   5| import type { Message } from './message.js'
   6| import type { QueueOperationMessage } from './messageQueueTypes.js'
   7| 
   8| export type SerializedMessage = Message & {
   9|   cwd: string
  10|   userType: string
  11|   entrypoint?: string // CLAUDE_CODE_ENTRYPOINT — distinguishes cli/sdk-ts/sdk-py/etc.
  12|   sessionId: string
  13|   timestamp: string
  14|   version: string
  15|   gitBranch?: string
  16|   slug?: string // Session slug for files like plans (used for resume)
  17| }
  18| 
  19| export type LogOption = {
  20|   date: string
  21|   messages: SerializedMessage[]
  22|   fullPath?: string
  23|   value: number
  24|   created: Date
  25|   modified: Date
  26|   firstPrompt: string
  27|   messageCount: number
  28|   fileSize?: number // File size in bytes (for display)
  29|   isSidechain: boolean
  30|   isLite?: boolean // True for lite logs (messages not loaded)

源码引用: src/types/command.ts · 第 93–98 行(共 217 行)

  93|   resume?: (
  94|     sessionId: UUID,
  95|     log: LogOption,
  96|     entrypoint: ResumeEntrypoint,
  97|   ) => Promise<void>
  98| }

Hook 执行管线(类型视角)

Hook 脚本 stdout JSON → jsonParse → syncHookResponseSchema.safeParse → hookSpecificOutput 窄化 → 更新 PermissionContext / append Message / 修改 tool input。

类型失败时 fallback 为 continue:true 并 log 警告——schema 设计偏向「忽略未知字段」与 optional 字段,避免用户 hook 因多一个 key 而 crash 主会话。

SDK 面与内部面为何分开

HOOK_EVENTS 放在 entrypoints/sdk/coreTypes.ts,说明这些事件名属于外部可见协议:CLI、SDK host、MCP 相关集成和用户脚本都可能依赖这些字符串。types/hooks.ts 则把同一组事件名接到内部 Zod schema、PromptRequest、AppState、Message 与 PermissionResult 上,承担“把外部 JSON 变成内部动作”的边界层职责。阅读时不要把二者混成一个文件:agentSdkTypes/coreTypes 越稳定越好,hooks.ts 可以随着 REPL 行为增加更细的 hookSpecificOutput 分支。

这个分层也解释了为什么 hookSpecificOutput 不是一个大对象加很多 optional 字段,而是按 hookEventName 写成判别联合。SessionStart 能注入 initialUserMessage 和 watchPaths;PreToolUse 能给 additionalContext 或 permissionDecision;PermissionRequest 能返回 allow/deny 与 updatedPermissions;Elicitation 走 prompt_response 协议。每个分支都把“这个事件能改变什么”限制在本事件语义内,执行层拿到 safeParse 结果后再根据事件名窄化。对外新增 hook 能力时,应该先确认事件是否属于稳定 SDK 面,再决定只改内部 hooks.ts,还是同步更新 SDK schema、文档和示例 hook。

另一个阅读重点是同步响应和异步响应分流。syncHookResponseSchema 允许本次事件立即影响 continue、decision、systemMessage 或权限更新;async hook 只声明 async:true 与超时,由执行器另行等待或轮询结果。Prompt elicitation 又是第三种交互:hook 进程要求用户在若干选项里选择,CLI 把选择结果写回。三者都走 JSON 协议,但阻塞点不同,排错时要先判断 hook 是想立即改主循环、后台完成,还是向用户发起提问。

源码引用: src/entrypoints/sdk/coreTypes.ts · 第 24–53 行(共 63 行)

  24| // Const arrays for runtime usage
  25| export const HOOK_EVENTS = [
  26|   'PreToolUse',
  27|   'PostToolUse',
  28|   'PostToolUseFailure',
  29|   'Notification',
  30|   'UserPromptSubmit',
  31|   'SessionStart',
  32|   'SessionEnd',
  33|   'Stop',
  34|   'StopFailure',
  35|   'SubagentStart',
  36|   'SubagentStop',
  37|   'PreCompact',
  38|   'PostCompact',
  39|   'PermissionRequest',
  40|   'PermissionDenied',
  41|   'Setup',
  42|   'TeammateIdle',
  43|   'TaskCreated',
  44|   'TaskCompleted',
  45|   'Elicitation',
  46|   'ElicitationResult',
  47|   'ConfigChange',
  48|   'WorktreeCreate',
  49|   'WorktreeRemove',
  50|   'InstructionsLoaded',
  51|   'CwdChanged',
  52|   'FileChanged',
  53| ] as const

源码引用: src/types/hooks.ts · 第 49–91 行(共 291 行)

  49| // Sync hook response schema
  50| export const syncHookResponseSchema = lazySchema(() =>
  51|   z.object({
  52|     continue: z
  53|       .boolean()
  54|       .describe('Whether Claude should continue after hook (default: true)')
  55|       .optional(),
  56|     suppressOutput: z
  57|       .boolean()
  58|       .describe('Hide stdout from transcript (default: false)')
  59|       .optional(),
  60|     stopReason: z
  61|       .string()
  62|       .describe('Message shown when continue is false')
  63|       .optional(),
  64|     decision: z.enum(['approve', 'block']).optional(),
  65|     reason: z.string().describe('Explanation for the decision').optional(),
  66|     systemMessage: z
  67|       .string()
  68|       .describe('Warning message shown to the user')
  69|       .optional(),
  70|     hookSpecificOutput: z
  71|       .union([
  72|         z.object({
  73|           hookEventName: z.literal('PreToolUse'),
  74|           permissionDecision: permissionBehaviorSchema().optional(),
  75|           permissionDecisionReason: z.string().optional(),
  76|           updatedInput: z.record(z.string(), z.unknown()).optional(),
  77|           additionalContext: z.string().optional(),
  78|         }),
  79|         z.object({
  80|           hookEventName: z.literal('UserPromptSubmit'),
  81|           additionalContext: z.string().optional(),
  82|         }),
  83|         z.object({
  84|           hookEventName: z.literal('SessionStart'),
  85|           additionalContext: z.string().optional(),
  86|           initialUserMessage: z.string().optional(),
  87|           watchPaths: z
  88|             .array(z.string())
  89|             .describe('Absolute paths to watch for FileChanged hooks')
  90|             .optional(),
  91|         }),

源码引用: src/types/hooks.ts · 第 121–148 行(共 291 行)

 121|           hookEventName: z.literal('PermissionRequest'),
 122|           decision: z.union([
 123|             z.object({
 124|               behavior: z.literal('allow'),
 125|               updatedInput: z.record(z.string(), z.unknown()).optional(),
 126|               updatedPermissions: z.array(permissionUpdateSchema()).optional(),
 127|             }),
 128|             z.object({
 129|               behavior: z.literal('deny'),
 130|               message: z.string().optional(),
 131|               interrupt: z.boolean().optional(),
 132|             }),
 133|           ]),
 134|         }),
 135|         z.object({
 136|           hookEventName: z.literal('Elicitation'),
 137|           action: z.enum(['accept', 'decline', 'cancel']).optional(),
 138|           content: z.record(z.string(), z.unknown()).optional(),
 139|         }),
 140|         z.object({
 141|           hookEventName: z.literal('ElicitationResult'),
 142|           action: z.enum(['accept', 'decline', 'cancel']).optional(),
 143|           content: z.record(z.string(), z.unknown()).optional(),
 144|         }),
 145|         z.object({
 146|           hookEventName: z.literal('CwdChanged'),
 147|           watchPaths: z
 148|             .array(z.string())

Hook 输出落地到执行器的三种路径

从执行器视角看,hook 输出最终只有三种“可观察后果”。第一类是控制主循环:continue/stopReason/decision 直接影响下一步是否继续采样、是否阻断某次 tool 调用。第二类是修改输入与权限:updatedInput、updatedPermissions 把外部脚本决策注入内部 PermissionContext,与 PermissionUpdate 判别联合保持一致。第三类是附加上下文:systemMessage、additionalContext、updatedMCPToolOutput 或 prompt_response 结果进入 transcript/UI 或后续工具调用环境。

这个分流解释了 why hooks.ts 会把字段设计成“基础公共字段 + hookSpecificOutput 判别联合”。公共字段负责控制流和通用消息,event-specific 字段负责局部能力扩展。执行器只需先用 syncHookResponseSchema 做一次结构校验,再按 hookEventName 选择分支处理器。这样既能保证外部 hook 脚本的自由度,又能在内部保持稳定的状态转换路径,避免一个事件返回的字段意外污染另一个事件的执行语义。

源码引用: src/types/hooks.ts · 第 49–148 行(共 291 行)

  49| // Sync hook response schema
  50| export const syncHookResponseSchema = lazySchema(() =>
  51|   z.object({
  52|     continue: z
  53|       .boolean()
  54|       .describe('Whether Claude should continue after hook (default: true)')
  55|       .optional(),
  56|     suppressOutput: z
  57|       .boolean()
  58|       .describe('Hide stdout from transcript (default: false)')
  59|       .optional(),
  60|     stopReason: z
  61|       .string()
  62|       .describe('Message shown when continue is false')
  63|       .optional(),
  64|     decision: z.enum(['approve', 'block']).optional(),
  65|     reason: z.string().describe('Explanation for the decision').optional(),
  66|     systemMessage: z
  67|       .string()
  68|       .describe('Warning message shown to the user')
  69|       .optional(),
  70|     hookSpecificOutput: z
  71|       .union([
  72|         z.object({
  73|           hookEventName: z.literal('PreToolUse'),
  74|           permissionDecision: permissionBehaviorSchema().optional(),
  75|           permissionDecisionReason: z.string().optional(),
  76|           updatedInput: z.record(z.string(), z.unknown()).optional(),
  77|           additionalContext: z.string().optional(),
  78|         }),
  79|         z.object({
  80|           hookEventName: z.literal('UserPromptSubmit'),
  81|           additionalContext: z.string().optional(),
  82|         }),
  83|         z.object({
  84|           hookEventName: z.literal('SessionStart'),
  85|           additionalContext: z.string().optional(),
  86|           initialUserMessage: z.string().optional(),
  87|           watchPaths: z
  88|             .array(z.string())
  89|             .describe('Absolute paths to watch for FileChanged hooks')
  90|             .optional(),
  91|         }),
  92|         z.object({
  93|           hookEventName: z.literal('Setup'),
  94|           additionalContext: z.string().optional(),
  95|         }),
  96|         z.object({
  97|           hookEventName: z.literal('SubagentStart'),
  98|           additionalContext: z.string().optional(),
  99|         }),
 100|         z.object({
 101|           hookEventName: z.literal('PostToolUse'),
 102|           additionalContext: z.string().optional(),
 103|           updatedMCPToolOutput: z
 104|             .unknown()
 105|             .describe('Updates the output for MCP tools')
 106|             .optional(),
 107|         }),
 108|         z.object({
 109|           hookEventName: z.literal('PostToolUseFailure'),
 110|           additionalContext: z.string().optional(),
 111|         }),
 112|         z.object({
 113|           hookEventName: z.literal('PermissionDenied'),
 114|           retry: z.boolean().optional(),
 115|         }),
 116|         z.object({
 117|           hookEventName: z.literal('Notification'),
 118|           additionalContext: z.string().optional(),
 119|         }),
 120|         z.object({
 121|           hookEventName: z.literal('PermissionRequest'),
 122|           decision: z.union([
 123|             z.object({
 124|               behavior: z.literal('allow'),
 125|               updatedInput: z.record(z.string(), z.unknown()).optional(),
 126|               updatedPermissions: z.array(permissionUpdateSchema()).optional(),
 127|             }),
 128|             z.object({
 129|               behavior: z.literal('deny'),
 130|               message: z.string().optional(),
 131|               interrupt: z.boolean().optional(),
 132|             }),
 133|           ]),
 134|         }),
 135|         z.object({
 136|           hookEventName: z.literal('Elicitation'),
 137|           action: z.enum(['accept', 'decline', 'cancel']).optional(),
 138|           content: z.record(z.string(), z.unknown()).optional(),
 139|         }),
 140|         z.object({
 141|           hookEventName: z.literal('ElicitationResult'),
 142|           action: z.enum(['accept', 'decline', 'cancel']).optional(),
 143|           content: z.record(z.string(), z.unknown()).optional(),
 144|         }),
 145|         z.object({
 146|           hookEventName: z.literal('CwdChanged'),
 147|           watchPaths: z
 148|             .array(z.string())

源码引用: src/entrypoints/agentSdkTypes.ts · 第 26–61 行(共 444 行)

  26| export * from './sdk/runtimeTypes.js'
  27| 
  28| // Re-export settings types (generated from settings JSON schema)
  29| export type { Settings } from './sdk/settingsTypes.generated.js'
  30| // Re-export tool types (all marked @internal until SDK API stabilizes)
  31| export * from './sdk/toolTypes.js'
  32| 
  33| // ============================================================================
  34| // Functions
  35| // ============================================================================
  36| 
  37| import type {
  38|   SDKMessage,
  39|   SDKResultMessage,
  40|   SDKSessionInfo,
  41|   SDKUserMessage,
  42| } from './sdk/coreTypes.js'
  43| // Import types needed for function signatures
  44| import type {
  45|   AnyZodRawShape,
  46|   ForkSessionOptions,
  47|   ForkSessionResult,
  48|   GetSessionInfoOptions,
  49|   GetSessionMessagesOptions,
  50|   InferShape,
  51|   InternalOptions,
  52|   InternalQuery,
  53|   ListSessionsOptions,
  54|   McpSdkServerConfigWithInstance,
  55|   Options,
  56|   Query,
  57|   SDKSession,
  58|   SDKSessionOptions,
  59|   SdkMcpToolDefinition,
  60|   SessionMessage,
  61|   SessionMutationOptions,

本章小结与延伸

api-sdk-types 定义外部 hook 脚本与 REPL 的 JSON 契约。下一章 misc-types 读 ids、plugin、generated 等剩余类型文件。 继续学习:

  • misc-types
  • tool-permission-types
Prev
tool-permission-types · Tool、Permission、Command 类型
Next
misc-types · ids、plugin、generated 与其余类型