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

本章总览

先抓主轴:tool-permission-types 描述了“命令如何触发工具、工具如何受权限约束、执行过程如何反馈进度”的类型合同。围绕这条主轴,types/command.ts 管命令形态,types/permissions.ts 管决策与更新协议,types/tools.ts 管统一进度载荷。

学完本章你应该能

  • 说明 permissions.ts 打破循环依赖的动机
  • 列举 ExternalPermissionMode 与 InternalPermissionMode 差异
  • 理解 PermissionRule、PermissionUpdate 判别联合
  • 区分 PromptCommand 与 LocalJSXCommand 的 load/call 模式
  • 知道 ToolProgressData 为何统一用 kind + index signature
  • 能 trace LocalJSXCommandContext 与 ToolUseContext 的扩展关系

核心概念(先读懂这些)

permissions.ts 是类型层的安全阀

文件头注释明确:仅类型与无 runtime 依赖的常量。EXTERNAL_PERMISSION_MODES、INTERNAL_PERMISSION_MODES 用 feature gate 注入 auto 模式。utils/permissions/* 实现 import 此文件,hooks 与 state 引用 PermissionMode 而不拉入 PermissionRule 求值逻辑。

Command 三种 type 字面量

prompt:技能/插件提供的模型侧命令,getPromptForCommand 返回 ContentBlockParam[]。local:纯 TS 函数,返回 LocalCommandResult(text/compact/skip)。local-jsx:Ink Dialog,load() 懒加载,call(onDone, context, args) 返回 ReactNode。LocalJSXCommandOnDone 的 shouldQuery、metaMessages 控制命令后是否继续 query。

Tool progress 类型是标记联合的松散版

BashProgress、MCPProgress、AgentToolProgress 等均 extends ToolProgressData。kind 字段供 UI 选择渲染器;其余字段 unknown 扩展,避免每加一个 Tool 就改中央联合。streaming executor 在运行时 narrow kind。

建议学习步骤

  1. 阅读 permissions.ts PERMISSION_MODES 与 PermissionBehavior
  2. 浏览 PermissionUpdate 五种 operation 变体
  3. 阅读 command.ts PromptCommand 与 fork/inline context
  4. 对照 LocalJSXCommandContext 的 setMessages、resume 字段
  5. 查看 tools.ts 全部 Progress 别名
  6. 在 commands/registry 搜索 Command union 窄化

常见误区

注意

PermissionUpdateDestination 与 PermissionRuleSource 相似但不等价

注意

LocalCommandResult compact 变体携带 CompactionResult,勿与 /compact 命令混淆

注意

PromptCommand paths glob 仅影响可见性,不改变 type

注意

WorkingDirectorySource 注释说明未来可能与 RuleSource 分叉

permissions.ts 结构

文件分块:Modes → Behaviors → Rules → Updates → Decisions → Context。

PermissionMode = ExternalPermissionMode | 'auto' | 'bubble'。用户可设 defaultMode 的运行时集合是 INTERNAL_PERMISSION_MODES,TRANSCRIPT_CLASSIFIER feature 开启时含 auto。

PermissionRule 三元组:source(userSettings/projectSettings/.../session)、ruleBehavior(allow/deny/ask)、ruleValue(toolName + 可选 ruleContent)。

PermissionUpdate 判别联合支持 addRules、replaceRules、removeRules、setMode、addDirectories、removeDirectories——Permission UI 与 hooks 的 PermissionRequest 回调共用此形状。

源码引用: src/types/permissions.ts · 第 16–38 行(共 442 行)

  16| export const EXTERNAL_PERMISSION_MODES = [
  17|   'acceptEdits',
  18|   'bypassPermissions',
  19|   'default',
  20|   'dontAsk',
  21|   'plan',
  22| ] as const
  23| 
  24| export type ExternalPermissionMode = (typeof EXTERNAL_PERMISSION_MODES)[number]
  25| 
  26| // Exhaustive mode union for typechecking. The user-addressable runtime set
  27| // is INTERNAL_PERMISSION_MODES below.
  28| export type InternalPermissionMode = ExternalPermissionMode | 'auto' | 'bubble'
  29| export type PermissionMode = InternalPermissionMode
  30| 
  31| // Runtime validation set: modes that are user-addressable (settings.json
  32| // defaultMode, --permission-mode CLI flag, conversation recovery).
  33| export const INTERNAL_PERMISSION_MODES = [
  34|   ...EXTERNAL_PERMISSION_MODES,
  35|   ...(feature('TRANSCRIPT_CLASSIFIER') ? (['auto'] as const) : ([] as const)),
  36| ] as const satisfies readonly PermissionMode[]
  37| 
  38| export const PERMISSION_MODES = INTERNAL_PERMISSION_MODES

源码引用: src/types/permissions.ts · 第 54–79 行(共 442 行)

  54| export type PermissionRuleSource =
  55|   | 'userSettings'
  56|   | 'projectSettings'
  57|   | 'localSettings'
  58|   | 'flagSettings'
  59|   | 'policySettings'
  60|   | 'cliArg'
  61|   | 'command'
  62|   | 'session'
  63| 
  64| /**
  65|  * The value of a permission rule - specifies which tool and optional content
  66|  */
  67| export type PermissionRuleValue = {
  68|   toolName: string
  69|   ruleContent?: string
  70| }
  71| 
  72| /**
  73|  * A permission rule with its source and behavior
  74|  */
  75| export type PermissionRule = {
  76|   source: PermissionRuleSource
  77|   ruleBehavior: PermissionBehavior
  78|   ruleValue: PermissionRuleValue
  79| }

源码引用: src/types/permissions.ts · 第 98–131 行(共 442 行)

  98| export type PermissionUpdate =
  99|   | {
 100|       type: 'addRules'
 101|       destination: PermissionUpdateDestination
 102|       rules: PermissionRuleValue[]
 103|       behavior: PermissionBehavior
 104|     }
 105|   | {
 106|       type: 'replaceRules'
 107|       destination: PermissionUpdateDestination
 108|       rules: PermissionRuleValue[]
 109|       behavior: PermissionBehavior
 110|     }
 111|   | {
 112|       type: 'removeRules'
 113|       destination: PermissionUpdateDestination
 114|       rules: PermissionRuleValue[]
 115|       behavior: PermissionBehavior
 116|     }
 117|   | {
 118|       type: 'setMode'
 119|       destination: PermissionUpdateDestination
 120|       mode: ExternalPermissionMode
 121|     }
 122|   | {
 123|       type: 'addDirectories'
 124|       destination: PermissionUpdateDestination
 125|       directories: string[]
 126|     }
 127|   | {
 128|       type: 'removeDirectories'
 129|       destination: PermissionUpdateDestination
 130|       directories: string[]
 131|     }

PermissionDecision 与 ToolPermissionContext

PermissionDecision、PermissionResult 相关类型(文件后半)描述单次 tool 调用求值结果:behavior、updatedInput、updatedPermissions、interrupt 等。

ToolPermissionContext 类型在 permissions.ts 或相邻 export 定义 mode、rules、additionalWorkingDirectories、bypass 标志——AppState.toolPermissionContext 字段类型源。

Permission UI(components/permissions-ui)与 useCanUseTool 仅依赖 types/permissions + PermissionResult,不 import Tool 实现,这是 extract 的主要收益。

源码引用: src/types/permissions.ts · 第 148–200 行(共 442 行)

 148| // ============================================================================
 149| // Permission Decisions & Results
 150| // ============================================================================
 151| 
 152| /**
 153|  * Minimal command shape for permission metadata.
 154|  * This is intentionally a subset of the full Command type to avoid import cycles.
 155|  * Only includes properties needed by permission-related components.
 156|  */
 157| export type PermissionCommandMetadata = {
 158|   name: string
 159|   description?: string
 160|   // Allow additional properties for forward compatibility
 161|   [key: string]: unknown
 162| }
 163| 
 164| /**
 165|  * Metadata attached to permission decisions
 166|  */
 167| export type PermissionMetadata =
 168|   | { command: PermissionCommandMetadata }
 169|   | undefined
 170| 
 171| /**
 172|  * Result when permission is granted
 173|  */
 174| export type PermissionAllowDecision<
 175|   Input extends { [key: string]: unknown } = { [key: string]: unknown },
 176| > = {
 177|   behavior: 'allow'
 178|   updatedInput?: Input
 179|   userModified?: boolean
 180|   decisionReason?: PermissionDecisionReason
 181|   toolUseID?: string
 182|   acceptFeedback?: string
 183|   contentBlocks?: ContentBlockParam[]
 184| }
 185| 
 186| /**
 187|  * Metadata for a pending classifier check that will run asynchronously.
 188|  * Used to enable non-blocking allow classifier evaluation.
 189|  */
 190| export type PendingClassifierCheck = {
 191|   command: string
 192|   cwd: string
 193|   descriptions: string[]
 194| }
 195| 
 196| /**
 197|  * Result when user should be prompted
 198|  */
 199| export type PermissionAskDecision<
 200|   Input extends { [key: string]: unknown } = { [key: string]: unknown },

源码引用: src/types/permissions.ts · 第 250–320 行(共 442 行)

 250|  */
 251| export type PermissionResult<
 252|   Input extends { [key: string]: unknown } = { [key: string]: unknown },
 253| > =
 254|   | PermissionDecision<Input>
 255|   | {
 256|       behavior: 'passthrough'
 257|       message: string
 258|       decisionReason?: PermissionDecision<Input>['decisionReason']
 259|       suggestions?: PermissionUpdate[]
 260|       blockedPath?: string
 261|       /**
 262|        * If set, an allow classifier check should be run asynchronously.
 263|        * The classifier may auto-approve the permission before the user responds.
 264|        */
 265|       pendingClassifierCheck?: PendingClassifierCheck
 266|     }
 267| 
 268| /**
 269|  * Explanation of why a permission decision was made
 270|  */
 271| export type PermissionDecisionReason =
 272|   | {
 273|       type: 'rule'
 274|       rule: PermissionRule
 275|     }
 276|   | {
 277|       type: 'mode'
 278|       mode: PermissionMode
 279|     }
 280|   | {
 281|       type: 'subcommandResults'
 282|       reasons: Map<string, PermissionResult>
 283|     }
 284|   | {
 285|       type: 'permissionPromptTool'
 286|       permissionPromptToolName: string
 287|       toolResult: unknown
 288|     }
 289|   | {
 290|       type: 'hook'
 291|       hookName: string
 292|       hookSource?: string
 293|       reason?: string
 294|     }
 295|   | {
 296|       type: 'asyncAgent'
 297|       reason: string
 298|     }
 299|   | {
 300|       type: 'sandboxOverride'
 301|       reason: 'excludedCommand' | 'dangerouslyDisableSandbox'
 302|     }
 303|   | {
 304|       type: 'classifier'
 305|       classifier: string
 306|       reason: string
 307|     }
 308|   | {
 309|       type: 'workingDir'
 310|       reason: string
 311|     }
 312|   | {
 313|       type: 'safetyCheck'
 314|       reason: string
 315|       // When true, auto mode lets the classifier evaluate this instead of
 316|       // forcing a prompt. True for sensitive-file paths (.claude/, .git/,
 317|       // shell configs) — the classifier can see context and decide. False
 318|       // for Windows path bypass attempts and cross-machine bridge messages.
 319|       classifierApprovable: boolean
 320|     }

tools.ts Progress 类型

ToolProgressData 基类:

{ kind?: string; [key: string]: unknown }

派生别名覆盖 Bash、PowerShell、MCP、Skill、TaskOutput、WebSearch、Agent、REPL、SdkWorkflow 等 Tool。Streaming executor 把 Tool 回调的 progress 对象塞进 ProgressMessage 或 inline UI。

行数少(约 16 行)但引用面广——新增 Tool 时复制别名模式即可,无需改 message.ts。

源码引用: src/types/tools.ts · 第 1–16 行(共 16 行)

   1| export type ToolProgressData = {
   2|   kind?: string
   3|   [key: string]: unknown
   4| }
   5| 
   6| export type ShellProgress = ToolProgressData
   7| export type BashProgress = ToolProgressData
   8| export type PowerShellProgress = ToolProgressData
   9| export type MCPProgress = ToolProgressData
  10| export type SkillToolProgress = ToolProgressData
  11| export type TaskOutputProgress = ToolProgressData
  12| export type WebSearchProgress = ToolProgressData
  13| export type AgentToolProgress = ToolProgressData
  14| export type REPLToolProgress = ToolProgressData
  15| export type SdkWorkflowProgress = ToolProgressData
  16| 

PromptCommand 与技能 fork

PromptCommand 字段 Highlights:

字段作用
sourcebuiltin / mcp / plugin / bundled / SettingSource
contextinline(展开进对话)或 fork(子 agent)
agentfork 时 agent 类型名
allowedTools限制技能可用工具集
hooks调用时注册 HooksSettings
pathsglob 触达后才在 autocomplete 显示

getPromptForCommand(args, ToolUseContext) 异步返回 ContentBlockParam[],与 API messages 对齐。

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

  25| export type PromptCommand = {
  26|   type: 'prompt'
  27|   progressMessage: string
  28|   contentLength: number // Length of command content in characters (used for token estimation)
  29|   argNames?: string[]
  30|   allowedTools?: string[]
  31|   model?: string
  32|   source: SettingSource | 'builtin' | 'mcp' | 'plugin' | 'bundled'
  33|   pluginInfo?: {
  34|     pluginManifest: PluginManifest
  35|     repository: string
  36|   }
  37|   disableNonInteractive?: boolean
  38|   // Hooks to register when this skill is invoked
  39|   hooks?: HooksSettings
  40|   // Base directory for skill resources (used to set CLAUDE_PLUGIN_ROOT environment variable for skill hooks)
  41|   skillRoot?: string
  42|   // Execution context: 'inline' (default) or 'fork' (run as sub-agent)
  43|   // 'inline' = skill content expands into the current conversation
  44|   // 'fork' = skill runs in a sub-agent with separate context and token budget
  45|   context?: 'inline' | 'fork'
  46|   // Agent type to use when forked (e.g., 'Bash', 'general-purpose')
  47|   // Only applicable when context is 'fork'
  48|   agent?: string
  49|   effort?: EffortValue
  50|   // Glob patterns for file paths this skill applies to
  51|   // When set, the skill is only visible after the model touches matching files
  52|   paths?: string[]
  53|   getPromptForCommand(
  54|     args: string,
  55|     context: ToolUseContext,
  56|   ): Promise<ContentBlockParam[]>
  57| }

Local 与 LocalJSX 命令

LocalCommand type: 'local',load() → { call: LocalCommandCall }。call 返回 LocalCommandResult:

  • text:用户可见字符串
  • compact:CompactionResult + 可选 displayText
  • skip:不产生 transcript 行

LocalJSXCommand type: 'local-jsx',call 签名接收 onDone、扩展 context、args。LocalJSXCommandOnDone 支持 display: skip/system/user、shouldQuery、metaMessages、nextInput。

/memory 命令即 LocalJSXCommandCall:打开 MemoryFileSelector Dialog。

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

  16| export type LocalCommandResult =
  17|   | { type: 'text'; value: string }
  18|   | {
  19|       type: 'compact'
  20|       compactionResult: CompactionResult
  21|       displayText?: string
  22|     }
  23|   | { type: 'skip' } // Skip messages
  24| 

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

  74| type LocalCommand = {
  75|   type: 'local'
  76|   supportsNonInteractive: boolean
  77|   load: () => Promise<LocalCommandModule>
  78| }
  79| 
  80| export type LocalJSXCommandContext = ToolUseContext & {
  81|   canUseTool?: CanUseToolFn
  82|   setMessages: (updater: (prev: Message[]) => Message[]) => void
  83|   options: {
  84|     dynamicMcpConfig?: Record<string, ScopedMcpServerConfig>
  85|     ideInstallationStatus: IDEExtensionInstallationStatus | null
  86|     theme: ThemeName
  87|   }
  88|   onChangeAPIKey: () => void
  89|   onChangeDynamicMcpConfig?: (
  90|     config: Record<string, ScopedMcpServerConfig>,
  91|   ) => void
  92|   onInstallIDEExtension?: (ide: IdeType) => void
  93|   resume?: (
  94|     sessionId: UUID,
  95|     log: LogOption,
  96|     entrypoint: ResumeEntrypoint,
  97|   ) => Promise<void>
  98| }

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

 117| export type LocalJSXCommandOnDone = (
 118|   result?: string,
 119|   options?: {
 120|     display?: CommandResultDisplay
 121|     shouldQuery?: boolean
 122|     metaMessages?: string[]
 123|     nextInput?: string
 124|     submitNextInput?: boolean
 125|   },
 126| ) => void
 127| 
 128| /**
 129|  * The call signature for a local JSX command implementation.
 130|  */
 131| export type LocalJSXCommandCall = (
 132|   onDone: LocalJSXCommandOnDone,
 133|   context: ToolUseContext & LocalJSXCommandContext,
 134|   args: string,
 135| ) => Promise<React.ReactNode>
 136| 
 137| /**
 138|  * Module shape returned by load() for lazy-loaded commands.
 139|  */
 140| export type LocalJSXCommandModule = {
 141|   call: LocalJSXCommandCall
 142| }
 143| 
 144| type LocalJSXCommand = {
 145|   type: 'local-jsx'
 146|   /**
 147|    * Lazy-load the command implementation.
 148|    * Returns a module with a call() function.
 149|    * This defers loading heavy dependencies until the command is invoked.
 150|    */
 151|   load: () => Promise<LocalJSXCommandModule>
 152| }
 153| 
 154| /**
 155|  * Declares which auth/provider environments a command is available in.

ResumeEntrypoint 与 CommandResultDisplay

ResumeEntrypoint 枚举 cli_flag、slash_command_picker、slash_command_session_id、slash_command_title、fork——analytics 与 sessionStorage 用来标记 resume 来源。

CommandResultDisplay = skip | system | user 控制命令完成后的 transcript 展示层级。memory 命令 onDone 使用 display: system 展示编辑器提示。

LocalJSXCommandContext 扩展 ToolUseContext,注入 canUseTool、setMessages、theme、IDE 状态、onChangeAPIKey 等 REPL 专用回调。

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

 100| export type ResumeEntrypoint =
 101|   | 'cli_flag'
 102|   | 'slash_command_picker'
 103|   | 'slash_command_session_id'
 104|   | 'slash_command_title'
 105|   | 'fork'
 106| 
 107| export type CommandResultDisplay = 'skip' | 'system' | 'user'
 108| 
 109| /**
 110|  * Callback when a command completes.
 111|  * @param result - Optional user-visible message to display
 112|  * @param options - Optional configuration for command completion
 113|  * @param options.display - How to display the result: 'skip' | 'system' | 'user' (default)
 114|  * @param options.shouldQuery - If true, send messages to the model after command completes
 115|  * @param options.metaMessages - Additional messages to insert as isMeta (model-visible but hidden)

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

 107| export type CommandResultDisplay = 'skip' | 'system' | 'user'

三类型在运行时的汇合点

用户 /commit 或 keybinding command:commit
  → commands registry 查 Command union
  → local-jsx / local / prompt 分支
  → ToolUseContext + PermissionMode (types/permissions)
  → Tool 执行 → ToolProgressData (types/tools) → ProgressMessage (types/message)

类型层不包含 registry 逻辑,但 Command 与 PermissionUpdate 形状必须 stable,否则 SDK 与外部 hooks 配置会静默不兼容。

权限类型的分层边界

permissions.ts 的关键价值不是“把所有权限逻辑写在一个文件”,而是把纯类型与可运行求值器拆开。PermissionRule 描述规则来自哪里、匹配哪个 tool、行为是 allow/deny/ask;PermissionUpdate 描述一次配置变更要写到 userSettings、projectSettings、session 还是 cliArg;真正的规则合并、持久化、危险规则剥离和 hook 决策应用留在 utils/permissions。这样组件、SDK schema、hook 输出校验和 AppState 可以共享同一组名词,却不会因为 import 一个求值函数而拉进配置、文件系统或 GrowthBook 依赖。

ToolPermissionContext 又在 Tool.ts 中用 DeepImmutable 包住,说明运行时把它当“当前权限快照”传给工具,而不是让工具随手改全局状态。mode、alwaysAllowRules、alwaysDenyRules、alwaysAskRules、additionalWorkingDirectories 与 bypass/auto 可用性共同决定一次调用是否弹窗。PermissionUpdateSchema 在 SDK schema 中复刻同一判别联合,是外部 hook 与结构化 IO 能返回 updatedPermissions 的原因;因此改字段名或 destination 取值时必须同时考虑内部 TypeScript 类型、Zod schema、持久化实现和 CLI/SDK 兼容性。

源码引用: src/types/permissions.ts · 第 85–132 行(共 442 行)

  85| /**
  86|  * Where a permission update should be persisted
  87|  */
  88| export type PermissionUpdateDestination =
  89|   | 'userSettings'
  90|   | 'projectSettings'
  91|   | 'localSettings'
  92|   | 'session'
  93|   | 'cliArg'
  94| 
  95| /**
  96|  * Update operations for permission configuration
  97|  */
  98| export type PermissionUpdate =
  99|   | {
 100|       type: 'addRules'
 101|       destination: PermissionUpdateDestination
 102|       rules: PermissionRuleValue[]
 103|       behavior: PermissionBehavior
 104|     }
 105|   | {
 106|       type: 'replaceRules'
 107|       destination: PermissionUpdateDestination
 108|       rules: PermissionRuleValue[]
 109|       behavior: PermissionBehavior
 110|     }
 111|   | {
 112|       type: 'removeRules'
 113|       destination: PermissionUpdateDestination
 114|       rules: PermissionRuleValue[]
 115|       behavior: PermissionBehavior
 116|     }
 117|   | {
 118|       type: 'setMode'
 119|       destination: PermissionUpdateDestination
 120|       mode: ExternalPermissionMode
 121|     }
 122|   | {
 123|       type: 'addDirectories'
 124|       destination: PermissionUpdateDestination
 125|       directories: string[]
 126|     }
 127|   | {
 128|       type: 'removeDirectories'
 129|       destination: PermissionUpdateDestination
 130|       directories: string[]
 131|     }
 132| 

源码引用: src/Tool.ts · 第 122–138 行(共 793 行)

 122| // Apply DeepImmutable to the imported type
 123| export type ToolPermissionContext = DeepImmutable<{
 124|   mode: PermissionMode
 125|   additionalWorkingDirectories: Map<string, AdditionalWorkingDirectory>
 126|   alwaysAllowRules: ToolPermissionRulesBySource
 127|   alwaysDenyRules: ToolPermissionRulesBySource
 128|   alwaysAskRules: ToolPermissionRulesBySource
 129|   isBypassPermissionsModeAvailable: boolean
 130|   isAutoModeAvailable?: boolean
 131|   strippedDangerousRules?: ToolPermissionRulesBySource
 132|   /** When true, permission prompts are auto-denied (e.g., background agents that can't show UI) */
 133|   shouldAvoidPermissionPrompts?: boolean
 134|   /** When true, automated checks (classifier, hooks) are awaited before showing the permission dialog (coordinator workers) */
 135|   awaitAutomatedChecksBeforeDialog?: boolean
 136|   /** Stores the permission mode before model-initiated plan mode entry, so it can be restored on exit */
 137|   prePlanMode?: PermissionMode
 138| }>

源码引用: src/entrypoints/sdk/coreSchemas.ts · 第 263–298 行(共 1890 行)

 263| export const PermissionUpdateSchema = lazySchema(() =>
 264|   z.discriminatedUnion('type', [
 265|     z.object({
 266|       type: z.literal('addRules'),
 267|       rules: z.array(PermissionRuleValueSchema()),
 268|       behavior: PermissionBehaviorSchema(),
 269|       destination: PermissionUpdateDestinationSchema(),
 270|     }),
 271|     z.object({
 272|       type: z.literal('replaceRules'),
 273|       rules: z.array(PermissionRuleValueSchema()),
 274|       behavior: PermissionBehaviorSchema(),
 275|       destination: PermissionUpdateDestinationSchema(),
 276|     }),
 277|     z.object({
 278|       type: z.literal('removeRules'),
 279|       rules: z.array(PermissionRuleValueSchema()),
 280|       behavior: PermissionBehaviorSchema(),
 281|       destination: PermissionUpdateDestinationSchema(),
 282|     }),
 283|     z.object({
 284|       type: z.literal('setMode'),
 285|       mode: z.lazy(() => PermissionModeSchema()),
 286|       destination: PermissionUpdateDestinationSchema(),
 287|     }),
 288|     z.object({
 289|       type: z.literal('addDirectories'),
 290|       directories: z.array(z.string()),
 291|       destination: PermissionUpdateDestinationSchema(),
 292|     }),
 293|     z.object({
 294|       type: z.literal('removeDirectories'),
 295|       directories: z.array(z.string()),
 296|       destination: PermissionUpdateDestinationSchema(),
 297|     }),
 298|   ]),

本章小结与延伸

tool-permission-types 连接 Tool 流式 UI、权限规则引擎与命令注册表。下一章 api-sdk-types 读 hooks 与 SDK 协议类型。 继续学习:

  • api-sdk-types
  • message-types
Prev
message-types · Message 联合与 content blocks
Next
api-sdk-types · API 与 Hooks 协议类型