Claude Code Wiki
首页 深入解析 命令系统

核心命令:commit、review、compact 实现解析

中级 命令系统

本文档深入解析 Claude Code CLI 中三个核心命令的实现机制,通过分析其架构模式、执行流程和设计决策,帮助开发者理解命令系统的工作原理和扩展方式。

命令架构基础:统一的类型系统

Claude Code 的命令系统建立在 三种核心命令类型 之上,每种类型对应不同的执行模式和复杂度等级。这种设计既保证了简单命令的轻量级实现,又为复杂交互提供了完整的生命周期管理。

Command 类型联合

type Command = CommandBase & (PromptCommand | LocalCommand | LocalJSXCommand)

所有命令共享 CommandBase 基础属性(名称、描述、启用状态等),但在执行机制上通过 类型鉴别器(type discriminator) 实现多态:

命令类型type 字段执行模式适用场景示例
PromptCommand'prompt'生成提示词 → 模型执行简单任务自动化/commit, /review
LocalCommand'local'本地函数调用纯逻辑操作/compact
LocalJSXCommand'local-jsx'React 组件渲染需要用户交互的复杂操作/ultrareview

Sources: types/command.ts

架构对比:三种命令类型的设计哲学

graph TB
    subgraph "PromptCommand 流程"
        P1[用户输入 /commit] --> P2[getPromptForCommand]
        P2 --> P3[生成动态提示词]
        P3 --> P4[注入 Shell 命令输出]
        P4 --> P5[发送给 Claude 模型]
        P5 --> P6[模型执行 git 操作]
    end
    
    subgraph "LocalCommand 流程"
        L1[用户输入 /compact] --> L2[懒加载命令模块]
        L2 --> L3[调用本地 call 函数]
        L3 --> L4[执行压缩逻辑]
        L4 --> L5[更新消息列表]
    end
    
    subgraph "LocalJSXCommand 流程"
        J1[用户输入 /ultrareview] --> J2[渲染 React 对话框]
        J2 --> J3[用户确认配额/付费]
        J3 --> J4[创建远程会话]
        J4 --> J5[轮询结果回传]
    end
    
    style P1 fill:#e1f5ff
    style L1 fill:#f3e5f5
    style J1 fill:#fff3e0

设计决策解析

  1. PromptCommand 采用 声明式编程 模式,命令只需定义”做什么”(通过提示词),模型负责”如何做”。这降低了实现复杂度,但牺牲了精确控制。

  2. LocalCommand 提供 命令式编程 能力,适合需要精确控制执行流程、访问本地状态或执行敏感操作的场景。

  3. LocalJSXCommand 结合了 React 的 组件化 UI 和命令执行,用于需要复杂用户交互(如确认对话框、表单输入)的场景。

Sources: types/command.ts, commands.ts


/commit:智能 Git 提交生成器

核心机制:动态提示词构建

/commit 命令通过 模板字符串 + Shell 命令插值 的方式构建上下文丰富的提示词。其核心创新在于使用 executeShellCommandsInPrompt 函数,在提示词发送给模型前动态注入实时 Git 状态。

const command = {
  type: 'prompt',
  name: 'commit',
  allowedTools: ['Bash(git add:*)', 'Bash(git status:*)', 'Bash(git commit:*)'],
  async getPromptForCommand(_args, context) {
    const promptContent = getPromptContent() // 包含 !`git status` 等插值
    const finalContent = await executeShellCommandsInPrompt(
      promptContent,
      context,
      '/commit'
    )
    return [{ type: 'text', text: finalContent }]
  },
}

关键设计点

  1. 工具白名单机制allowedTools 限制模型只能执行 Git 相关操作,防止越权。这体现了 最小权限原则(Principle of Least Privilege)。

  2. Shell 命令插值语法:提示词中的 !`git status` 会被替换为实际命令输出,使得模型能获取实时上下文而无需用户手动粘贴。

  3. Git 安全协议:提示词中内置了防护规则,如禁止修改配置、禁止跳过钩子、禁止 --amend(除非用户明确要求)。

Sources: commands/commit.ts

执行流程与上下文注入

sequenceDiagram
    participant U as 用户
    participant C as /commit 命令
    participant S as Shell 执行器
    participant M as Claude 模型
    participant G as Git 仓库
    
    U->>C: 输入 /commit
    C->>C: getPromptContent()
    Note over C: 生成包含插值的提示词模板
    
    C->>S: executeShellCommandsInPrompt
    S->>G: git status
    G-->>S: 工作树状态
    S->>G: git diff HEAD
    G-->>S: 变更差异
    S->>G: git log --oneline -10
    G-->>S: 提交历史
    S-->>C: 替换后的完整提示词
    
    C->>M: 发送提示词 + 工具白名单
    M->>M: 分析变更并起草提交消息
    M->>G: git add <files>
    M->>G: git commit -m "..."
    G-->>M: 提交成功
    M-->>U: 显示提交结果

上下文信息层次

上下文类型Shell 命令用途
工作树状态git status识别未跟踪文件和修改
变更差异git diff HEAD理解具体改动内容
当前分支git branch --show-current上下文感知
提交历史git log --oneline -10学习项目提交风格

这种 渐进式上下文披露(Progressive Context Disclosure)确保模型既能获得足够信息生成高质量提交消息,又不会因过多无关信息而分心。

Sources: commands/commit.ts

HEREDOC 语法与提交消息格式

命令强制使用 HEREDOC 语法创建提交,确保多行消息的正确处理:

git commit -m "$(cat <<'EOF'
Commit message here.
[Optional attribution footer]
EOF
)"

这种设计解决了两个问题:

  1. Shell 转义安全:HEREDOC 避免了消息中的特殊字符(如引号、美元符号)被 Shell 错误解析。

  2. 归属信息注入:通过 getAttributionTexts() 动态添加可选的 Co-authored-by 信息,支持多人协作场景。

Sources: commands/commit.ts


/review:多层次代码审查系统

双路径架构:本地与远程审查

/review 命令展现了 功能分层 的设计模式,提供两种审查路径以适应不同需求:

特性/review (本地)/ultrareview (远程)
执行位置本地 Claude 模型Claude Code on the Web
审查深度标准代码审查深度 Bug 检测(10-20分钟)
计费模式消耗本地配额独立配额/按需付费
实现类型PromptCommandLocalJSXCommand
用户交互需确认配额/付费

Sources: commands/review.ts

本地审查实现:简洁的提示词工程

本地 /review 使用 结构化提示词 引导模型执行标准审查流程:

const LOCAL_REVIEW_PROMPT = (args: string) => `
  You are an expert code reviewer. Follow these steps:
  
  1. If no PR number is provided, run \`gh pr list\` to show open PRs
  2. If a PR number is provided, run \`gh pr view <number>\` to get PR details
  3. Run \`gh pr diff <number>\` to get the diff
  4. Analyze the changes and provide a thorough code review that includes:
     - Overview of what the PR does
     - Analysis of code quality and style
     - Specific suggestions for improvements
     - Any potential issues or risks
  
  Keep your review concise but thorough. Focus on:
  - Code correctness
  - Following project conventions
  - Performance implications
  - Test coverage
  - Security considerations
  
  PR number: ${args}
`

提示词设计模式

  1. 步骤化指令:将复杂任务分解为明确的步骤(1-4),降低模型遗漏关键环节的概率。

  2. 结构化输出要求:通过列表形式规定审查维度,确保输出的全面性和一致性。

  3. 约束与平衡:既要求”concise”(简洁)又要求”thorough”(全面),引导模型在深度和广度间取得平衡。

Sources: commands/review.ts

远程审查实现:配额管理与用户确认

/ultrareview 采用 LocalJSXCommand 类型,需要处理复杂的用户交互和配额逻辑:

const ultrareview: Command = {
  type: 'local-jsx',
  name: 'ultrareview',
  description: `~10–20 min · Finds and verifies bugs in your branch. 
                 Runs in Claude Code on the web. See ${CCR_TERMS_URL}`,
  isEnabled: () => isUltrareviewEnabled(),
  load: () => import('./review/ultrareviewCommand.js'),
}

配额管理机制

graph TD
    A[用户调用 /ultrareview] --> B{检查订阅类型}
    B -->|Team/Enterprise| C[直接通过]
    B -->|Pro/Max| D[查询配额]
    D --> E{剩余审查次数}
    E -->|> 0| F[显示: 这是免费审查 X/Y]
    E -->|= 0| G{余额检查}
    G -->|充足| H[显示: 将使用额外用量]
    G -->|不足| I[显示: 余额不足]
    F --> J[用户确认对话框]
    H --> J
    J -->|确认| K[启动远程审查]
    J -->|取消| L[取消操作]

Sources: commands/review.ts, commands/review/reviewRemote.ts

远程任务执行流程

// 1. 检查资格和配额
const eligibility = await checkRemoteAgentEligibility()
if (!eligibility.ok) {
  throw new Error(formatPreconditionError(eligibility))
}

// 2. 创建远程会话
const sessionUrl = await teleportToRemote({
  repoPath: detectCurrentRepositoryWithHost(),
  branch: getCurrentBranch(),
})

// 3. 注册任务以便轮询结果
registerRemoteAgentTask({
  sessionId: remoteSessionId,
  onResult: (result) => {
    // 通过 task-notification 机制将结果注入本地会话
  }
})

这种 异步任务 + 轮询 模式解耦了远程长时间运行任务和本地 UI,用户可以在审查进行时继续其他工作。

Sources: commands/review/reviewRemote.ts


/compact:智能上下文压缩引擎

多级压缩策略:性能与质量的平衡

/compact 命令是 Claude Code 中最复杂的本地命令,实现了 三层层叠压缩策略 以优化 token 使用:

graph TB
    A[用户调用 /compact] --> B{有自定义指令?}
    B -->|否| C[尝试 Session Memory 压缩]
    B -->|是| D[跳过 Session Memory]
    
    C --> E{成功?}
    E -->|是| F[快速返回<br/>低成本压缩]
    E -->|否| G{Reactive-Only 模式?}
    
    D --> G
    G -->|是| H[Reactive Compact 路径]
    G -->|否| I[传统压缩路径]
    
    I --> J[Microcompact 预处理]
    J --> K[compactConversation 主压缩]
    
    H --> L[执行 Hooks]
    K --> L
    F --> M[清理与缓存重置]
    L --> M
    
    style C fill:#c8e6c9
    style F fill:#a5d6a7
    style H fill:#fff9c4
    style I fill:#ffccbc

三层层叠详解

层级策略Token 成本适用场景实现位置
1. Session Memory提取结构化记忆~1K tokens无自定义指令的常规压缩sessionMemoryCompact.ts
2. Reactive Compact增量式分组压缩~5K tokensReactive-Only 模式reactiveCompact.ts
3. Legacy Compact全量对话摘要~10K+ tokens需要自定义摘要指令compact.ts

Sources: commands/compact/compact.ts

Session Memory 压缩:低成本优先路径

Session Memory 压缩通过 结构化记忆提取 替代对话摘要,大幅降低 API 调用成本:

const sessionMemoryResult = await trySessionMemoryCompaction(
  messages,
  context.agentId,
)
if (sessionMemoryResult) {
  getUserContext.cache.clear?.()
  runPostCompactCleanup()
  return {
    type: 'compact',
    compactionResult: sessionMemoryResult,
    displayText: buildDisplayText(context),
  }
}

核心优势

  1. 零 API 调用:不需要调用 Claude API 生成摘要,直接从对话中提取结构化信息。

  2. 保留关键信息:通过启发式算法识别并保留决策点、错误解决方案等高价值内容。

  3. 快速执行:通常在 1-2 秒内完成,用户几乎无感知。

Sources: commands/compact/compact.ts

Legacy 压缩流程:完整实现剖析

当需要自定义摘要指令或 Session Memory 不适用时,系统回退到 Legacy 压缩路径:

1. Microcompact 预处理

const microcompactResult = await microcompactMessages(messages, context)
const messagesForCompact = microcompactResult.messages

作用:在主压缩前通过启发式规则快速移除冗余内容(如重复的文件读取结果),减少后续 API 调用的 token 消耗。

Sources: commands/compact/compact.ts

2. compactConversation 核心逻辑

const result = await compactConversation(
  messagesForCompact,      // 待压缩消息
  context,                 // 执行上下文
  await getCacheSharingParams(context, messagesForCompact), // 缓存参数
  false,                   // 是否部分压缩
  customInstructions,      // 用户自定义指令
  false,                   // 是否静默模式
)

关键步骤

sequenceDiagram
    participant C as compactConversation
    participant H as Pre-Compact Hooks
    participant A as Claude API
    participant P as Post-Compact Hooks
    
    C->>H: 执行前置钩子
    H-->>C: 返回自定义指令
    
    C->>C: stripImagesFromMessages
    Note over C: 移除图片以避免 PTL 错误
    
    C->>C: groupMessagesByApiRound
    Note over C: 按 API 调用轮次分组
    
    C->>A: 发送摘要请求
    A-->>C: 返回摘要文本
    
    C->>C: createCompactBoundaryMessage
    Note over C: 创建压缩边界标记
    
    C->>P: 执行后置钩子
    P-->>C: 返回用户显示消息
    
    C->>C: 恢复关键文件内容
    C->>C: 恢复技能指令

Sources: services/compact/compact.ts

3. 图片移除策略

为防止压缩 API 调用本身触发 prompt-too-long 错误,系统会移除图片并用文本标记替换:

export function stripImagesFromMessages(messages: Message[]): Message[] {
  return messages.map(message => {
    if (message.type !== 'user') return message
    
    const newContent = content.flatMap(block => {
      if (block.type === 'image') {
        return [{ type: 'text', text: '[image]' }]
      }
      if (block.type === 'document') {
        return [{ type: 'text', text: '[document]' }]
      }
      // 处理 tool_result 中嵌套的图片
      return [block]
    })
    
    return { ...message, message: { ...message.message, content: newContent } }
  })
}

设计权衡:牺牲图片信息以换取压缩成功率,但保留 [image] 标记让摘要提及”用户分享了图片”。

Sources: services/compact/compact.ts

4. Post-Compact 恢复机制

压缩后会智能恢复 关键文件内容技能指令,确保后续对话的连贯性:

export const POST_COMPACT_MAX_FILES_TO_RESTORE = 5
export const POST_COMPACT_TOKEN_BUDGET = 50_000
export const POST_COMPACT_MAX_TOKENS_PER_FILE = 5_000
export const POST_COMPACT_SKILLS_TOKEN_BUDGET = 25_000
export const POST_COMPACT_MAX_TOKENS_PER_SKILL = 5_000

Token 预算分配

  • 文件恢复:50K 总预算,单个文件最多 5K,最多恢复 5 个最近访问的文件
  • 技能恢复:25K 总预算,单个技能最多 5K(技能文件通常较大,如 verify=18.7KB)

Sources: services/compact/compact.ts

Hook 系统:扩展压缩生命周期

压缩命令提供了 两个扩展点 允许自定义逻辑注入:

Hook 类型执行时机用途参数
Pre-Compact压缩开始前添加自定义摘要指令、记录状态{ trigger, customInstructions }
Post-Compact压缩完成后清理、通知、状态同步{ trigger, customInstructions, compactionResult }
// Pre-Compact Hook 示例
const hookResult = await executePreCompactHooks(
  { trigger: 'manual', customInstructions: customInstructions || null },
  context.abortController.signal,
)

// 合并 Hook 返回的自定义指令
const mergedInstructions = mergeHookInstructions(
  customInstructions,
  hookResult.newCustomInstructions,
)

实际应用场景

  1. 团队规范注入:Pre-Compact Hook 自动添加”优先保留架构决策”的指令。
  2. 外部系统集成:Post-Compact Hook 将压缩事件同步到监控平台。
  3. 自定义摘要格式:通过 customInstructions 要求摘要遵循特定模板。

Sources: commands/compact/compact.ts, services/compact/compact.ts


设计模式总结与最佳实践

三种命令类型的选型指南

需求特征推荐类型理由
简单自动化任务,可由模型完成PromptCommand实现简单,声明式定义
需要访问本地状态或执行敏感操作LocalCommand完全控制执行流程
需要复杂用户交互(对话框、表单)LocalJSXCommandReact 组件化 UI
需要长时间运行或远程执行LocalJSXCommand异步任务管理

命令实现的关键原则

  1. 最小权限原则:通过 allowedTools 限制模型能力范围,防止越权操作(见 /commit)。

  2. 渐进式上下文披露:只提供任务所需的最小上下文,避免信息过载(见 /commit 的 Git 状态注入)。

  3. 优雅降级:为复杂操作提供多层回退策略,确保基本功能可用(见 /compact 的三层层叠)。

  4. 用户确认机制:对不可逆或高成本操作,通过 LocalJSXCommand 提供交互式确认(见 /ultrareview)。

  5. 扩展性设计:通过 Hook 系统允许第三方注入自定义逻辑,保持核心简洁。

性能优化技巧

  1. 懒加载模块:LocalCommand 和 LocalJSXCommand 使用 load() 函数延迟加载重型依赖。
const compact = {
  type: 'local',
  load: () => import('./compact.js'), // 只在调用时加载
}
  1. 缓存清理:压缩后主动清理 getUserContext.cache 防止内存泄漏。

  2. 并发执行:独立操作(如 Pre-Compact Hooks 和缓存参数构建)并行执行以减少延迟。

const [hookResult, cacheSafeParams] = await Promise.all([
  executePreCompactHooks(...),
  getCacheSharingParams(...),
])

Sources: commands/compact/index.ts, commands/compact/compact.ts


延伸阅读

要深入理解命令系统的完整架构,建议按以下顺序阅读相关文档: