深入拆解 Claude Code 源码(四):77 个斜杠命令背后的三种设计模式与插件迁移之路

系列:深入拆解 Claude Code 源码 | 第 4 篇 / 共 8 篇
关键词:Claude Code, 斜杠命令, Command 接口, prompt 命令, local 命令, 插件系统


开篇:一个命令,三种命运

在 Claude Code 里输入 /commit,AI 会帮你写一个 commit message 并提交代码。输入 /vim,终端会切换到 Vim 编辑模式。输入 /help,会弹出一个漂亮的 React 帮助面板。

这三个命令看起来都是"斜杠命令",但它们的内部实现完全不同:

  • /commitprompt 类型 —— 它生成一段 AI 提示词,交给对话引擎处理
  • /vimlocal 类型 —— 它直接在本地执行 JavaScript 逻辑
  • /helplocal-jsx 类型 —— 它渲染一个 React/Ink 组件到终端

这三种类型,就是 Claude Code 命令系统的核心设计模式。今天我们就来拆解这 77 个命令背后的架构。


一、Command 接口:12 个字段的精密设计

所有命令都实现同一个接口,定义在 src/commands.ts 中。这个接口有 12 个字段,每一个都有其存在的理由:

// src/types/command.ts → src/commands.ts
interface Command {
  // ─── 身份标识 ───
  name: string              // 命令名称(不含 /),如 'commit', 'clear'
  type: 'prompt' | 'local' | 'local-jsx'  // 命令类型,决定执行路径
  description: string       // 命令描述,显示在 /help 面板中
  aliases: string[]         // 别名列表,如 /reset → /clear, /continue → /resume

  // ─── 生命周期控制 ───
  isEnabled: () => boolean  // 动态判断是否启用(运行时检查环境变量、Feature Flag 等)
  isHidden: boolean         // 是否在帮助面板中隐藏(如 /heapdump、/thinkback-play)
  immediate: boolean        // 是否立即执行,不等用户确认(如 /rename、/mcp、/status)

  // ─── 运行环境 ───
  supportsNonInteractive: boolean  // 是否支持 SDK/CLI 非交互模式(如 /compact、/advisor)
  availability: string[]    // 可用环境限制:'claude-ai'(订阅用户)、'console'(API 用户)
  source: 'builtin' | 'plugin'  // 来源:内置 or 插件

  // ─── 实现 ───
  argumentHint: string      // 参数提示,显示在命令名后面,如 '<model>|off'
  load: () => Promise       // 延迟加载工厂函数,返回命令的实际实现
}

关键设计:load() 是延迟加载的核心。每个命令的实际实现被封装在一个返回 Promise 的工厂函数中。只有当用户真正输入某个命令时,对应的代码才会被 import() 动态加载到内存中。/insights 命令的实现文件有 3201 行(113KB),如果没有延迟加载,它会在启动时白白占用内存。

availability 字段是一个精巧的访问控制机制。在 src/commands.ts 中,meetsAvailabilityRequirement() 函数会根据用户的认证状态过滤命令:

// src/commands.ts
export function meetsAvailabilityRequirement(cmd: Command): boolean {
  if (!cmd.availability) return true  // 无限制 = 所有人可用
  for (const a of cmd.availability) {
    switch (a) {
      case 'claude-ai':
        if (isClaudeAISubscriber()) return true  // claude.ai 订阅用户
        break
      case 'console':
        // Console API 用户 = 第一方 API 客户端(排除 Bedrock/Vertex/Foundry)
        if (!isClaudeAISubscriber() && !isUsing3PServices()
            && isFirstPartyAnthropicBaseUrl())
          return true
        break
    }
  }
  return false
}

这就是为什么 /usage/upgrade/chrome 等命令在使用第三方 API 时不会出现 —— 它们的 availability 设置了 'claude-ai' 限制。


二、三种命令类型详解

类型一:prompt 命令 —— AI 的"剧本"

prompt 命令不直接执行任何操作,它只是生成一段精心构造的提示词,交给 AI 处理。这是 Claude Code 命令系统中最巧妙的设计 —— 把人类的意图转化为 AI 能理解的"剧本"

/commit:93 行代码的 Git 提交自动化

/commit 命令看起来简单,但它的 getPromptContent() 函数包含了一整套精心设计的"安全协议":

// src/commands/commit.ts (93 行)
const ALLOWED_TOOLS = [
  'Bash(git add:*)',
  'Bash(git status:*)',
  'Bash(git commit:*)',
]

function getPromptContent(): string {
  const { commit: commitAttribution } = getAttributionTexts()

  // undercover 模式:Anthropic 内部使用的特殊指令前缀
  let prefix = ''
  if (process.env.USER_TYPE === 'ant' && isUndercover()) {
    prefix = getUndercoverInstructions() + '\n'
  }

  return `${prefix}## Context
- Current git status: !\`git status\`
- Current git diff (staged and unstaged changes): !\`git diff HEAD\`
- Current branch: !\`git branch --show-current\`
- Recent commits: !\`git log --oneline -10\`

## Git Safety Protocol
- NEVER update the git config
- NEVER skip hooks (--no-verify, --no-gpg-sign, etc)
- CRITICAL: ALWAYS create NEW commits. NEVER use git commit --amend
- Do not commit files that likely contain secrets (.env, credentials.json, etc)
- If there are no changes to commit, do not create an empty commit
- Never use git commands with the -i flag (interactive input not supported)

## Your task
Based on the above changes, create a single git commit:
1. Analyze all staged changes, draft a concise commit message (1-2 sentences, focus on "why")
2. Stage relevant files and create the commit using HEREDOC syntax
   (commitAttribution 自动附加到 commit message 末尾)
`
}

注意那个 !\``git status\`` 语法 —— 这是 Claude Code 的 内联 Shell 执行 机制。executeShellCommandsInPrompt() 函数会在发送给 AI 之前,先在本地执行这些命令,把结果替换到提示词中。AI 看到的不是 !\git status``,而是真实的 git 状态输出。

还有一个细节:getAttributionTexts() 会返回类似 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> 的归因文本,自动附加到 commit message 中。

/commit-push-pr:159 行的全流程自动化

如果说 /commit 是"一键提交",那 /commit-push-pr 就是"一键发 PR"。它的工作量大得多:

// src/commands/commit-push-pr.ts (159 行)
const ALLOWED_TOOLS = [
  'Bash(git checkout --branch:*)',
  'Bash(git checkout -b:*)',
  'Bash(git add:*)',
  'Bash(git status:*)',
  'Bash(git push:*)',
  'Bash(git commit:*)',
  'Bash(gh pr create:*)',
  'Bash(gh pr edit:*)',
  'Bash(gh pr view:*)',
  'Bash(gh pr merge:*)',
  'ToolSearch',                              // 搜索可用工具
  'mcp__slack__send_message',               // Slack MCP 集成
  'mcp__claude_ai_Slack__slack_send_message', // claude.ai Slack 集成
]

getPromptContent() 函数的核心逻辑:

function getPromptContent(defaultBranch: string, prAttribution?: string): string {
  const safeUser = process.env.SAFEUSER || ''
  const username = process.env.USER || ''

  // undercover 模式下:移除 reviewer 和 Slack 步骤
  let reviewerArg = ' and `--reviewer anthropics/claude-code`'
  let slackStep = `5. After creating PR, check CLAUDE.md for Slack channels...`
  if (process.env.USER_TYPE === 'ant' && isUndercover()) {
    reviewerArg = ''; slackStep = ''
  }

  return `## Context
- SAFEUSER: ${safeUser}, whoami: ${username}
- git status/diff/branch: !\`git status\` !\`git diff HEAD\` !\`git branch --show-current\`
- diff from ${defaultBranch}: !\`git diff ${defaultBranch}...HEAD\`

## Your task
1. Create new branch if on ${defaultBranch} (use SAFEUSER for prefix, fallback to whoami)
2. Commit with heredoc syntax (include commitAttribution)
3. Push to origin
4. Create or update PR (title < 70 chars)${reviewerArg}
   ...${slackStep}`
}

关键设计点:

  • 分支命名:使用 SAFEUSER 环境变量(而非直接用 USER),回退到 whoami。这是为了避免在共享环境中泄露用户名。
  • 并行解析getPromptForCommand() 中用 Promise.all() 并行获取 defaultBranchprAttribution
  • Slack 集成:通过 ToolSearch 动态搜索 Slack 工具,而非硬编码依赖。找到后询问用户是否发送,找不到则静默跳过。
  • PR 归因getEnhancedPRAttribution() 会生成比 commit 更详细的 PR 归因文本,包含 PR body 的 footer 部分。
/security-review:196 行安全审查提示词

/security-review 是整个命令系统中提示词最长的 prompt 命令。它的核心是 SECURITY_REVIEW_MARKDOWN —— 一个 196 行的 Markdown 模板,定义了完整的安全审查流程。

// src/commands/security-review.ts (244 行)
const SECURITY_REVIEW_MARKDOWN = `---
allowed-tools: Bash(git diff:*), Bash(git status:*), Bash(git log:*),
  Bash(git show:*), Bash(git remote show:*), Read, Glob, Grep, LS, Task
---

You are a senior security engineer conducting a focused security review.
...(自动注入 git status、diff、commit 日志)

OBJECTIVE: Identify HIGH-CONFIDENCE security vulnerabilities.
CRITICAL: Only flag issues where you're >80% confident of actual exploitability.

ANALYSIS METHODOLOGY:
Phase 1 - Repository Context Research: 识别安全框架、编码模式、消毒/验证模式
Phase 2 - Comparative Analysis: 对比新代码与现有安全模式,识别偏差
Phase 3 - Vulnerability Assessment: 追踪数据流,检查注入点和不安全反序列化

START ANALYSIS (3 steps):
1. Use a sub-task to identify vulnerabilities
2. For each vulnerability, create a parallel sub-task to filter false-positives
3. Filter out any vulnerabilities where confidence < 8`

安全检查 5 大类

类别 检查项
输入验证 SQL 注入、命令注入、XXE、模板注入、NoSQL 注入、路径遍历
认证授权 认证绕过、提权路径、会话管理、JWT 漏洞、授权逻辑绕过
加密密钥 硬编码密钥、弱算法、密钥存储不当、随机数问题、证书验证绕过
注入执行 RCE(反序列化)、Pickle 注入、YAML 反序列化、Eval 注入、XSS
数据暴露 敏感数据日志、PII 处理、API 数据泄露、调试信息暴露

误报过滤 17+ 条硬排除规则 + 12 条先例规则:这是安全审查中最实用的部分。Claude Code 的工程师们把常见的误报模式硬编码进了提示词。挑几条最有代表性的:

HARD EXCLUSIONS(自动排除):
- DOS 漏洞、磁盘密钥存储、速率限制、内存安全(Rust 等内存安全语言不报告)
- 单元测试文件、日志欺骗、仅控制路径的 SSRF、正则注入/DOS
- GitHub Action 工作流中的输入消毒(除非明确可通过不可信输入触发)
- React/Angular 中的 XSS(除非使用了 dangerouslySetInnerHTML)
- 客户端 JS/TS 中缺少权限检查(服务端负责,不是漏洞)

PRECEDENTS(先例判定):
- 记录高价值密钥明文是漏洞,记录 URL 不是
- UUID 可假定为不可猜测,无需验证
- 环境变量和 CLI 标志是可信值,依赖控制环境变量的攻击无效
- ipython notebook 中的漏洞通常不可实际利用,除非有明确攻击路径

注意最终的 3 步分析流程:子任务识别漏洞 → 并行子任务过滤误报 → 过滤置信度 < 8 的结果。这意味着每个发现的漏洞都会被一个独立的 AI 子任务重新审查一遍,大幅降低了误报率。

/init:NEW_INIT 的 8 阶段交互式设置

/init 命令有两个版本,由 feature('NEW_INIT') 控制。旧版本(OLD_INIT_PROMPT)只是一个简单的"帮我创建 CLAUDE.md"提示词。新版本(NEW_INIT_PROMPT,约 200 行)是一个完整的 8 阶段交互式流程。命令入口根据 USER_TYPE === 'ant' 和环境变量 CLAUDE_CODE_NEW_INIT 决定使用哪个版本,执行时调用 maybeMarkProjectOnboardingComplete() 标记 onboarding 完成。

NEW_INIT 的 8 个阶段

阶段 名称 做什么
Phase 1 询问偏好 AskUserQuestion 问用户:要设置哪个 CLAUDE.md?要设置 skills 和 hooks 吗?
Phase 2 探索代码库 启动子 Agent 扫描:package.json、README、CI 配置、现有 CLAUDE.md、.cursor/rules、.copilot-instructions.md 等
Phase 3 填补空白 AskUserQuestion 补充代码无法回答的问题:团队规范、分支策略、测试怪癖等
Phase 4 写入 CLAUDE.md 在项目根目录写入精简的 CLAUDE.md,每行都通过"删掉它 Claude 会犯错吗?"测试
Phase 5 写入 CLAUDE.local.md 写入个人偏好文件(自动加入 .gitignore),包含角色、沙箱 URL、沟通偏好等
Phase 6 建议技能 根据 Phase 3 的偏好队列创建 .claude/skills/<name>/SKILL.md,并建议额外技能
Phase 7 建议优化 检查 GitHub CLI、lint 配置、formatter hook 等,逐项询问用户是否需要
Phase 8 摘要 回顾设置内容,提供后续优化建议(如安装插件、设置测试框架等)

NEW_INIT 的设计哲学是"只写 Claude 会犯错的东西"。Phase 4 的 CLAUDE.md 写入规则非常严格:

  • 包含:非标准的构建/测试/lint 命令、与语言默认不同的代码风格、测试怪癖、环境变量要求
  • 排除:文件结构列表(Claude 可以自己读)、标准语言惯例、通用建议、频繁变化的信息(用 @path 引用代替)

prompt 命令的代表清单

命令 功能 允许的工具
/commit Git 提交 git add, git status, git commit
/commit-push-pr 提交+推送+创建 PR git + gh pr create/edit/view/merge + Slack MCP
/review PR 审查 gh pr 命令
/init 项目初始化 文件读写
/insights 使用分析报告 文件读取
/security-review 安全审查 git diff/status/log/show, Read, Glob, Grep, LS, Task

类型二:local 命令 —— 本地的"快速反应"

local 命令直接执行 JavaScript 逻辑,不经过 AI。适合不需要 AI 参与的纯操作。

// 示例:/version 命令
{
  name: 'version',
  type: 'local',
  async load() {
    return () => {
      console.log(MACRO.VERSION)
      if (MACRO.BUILD_TIME) {
        console.log(`Build: ${MACRO.BUILD_TIME}`)
      }
    }
  }
}
/compact:对话压缩的核心机制

/compact 是 local 命令中最复杂的一个。它不只是"清除历史",而是一套精心设计的对话压缩系统。命令定义很简单:isEnabledDISABLE_COMPACT 环境变量门控,支持非交互模式,支持自定义摘要指令作为参数。

compact.ts 的实现(约 100+ 行)包含多层压缩策略:

  1. 会话记忆压缩trySessionMemoryCompaction):优先尝试,不支持自定义指令
  2. 标准压缩compactConversation):调用 AI 生成对话摘要
  3. 微压缩microcompactMessages):对消息进行细粒度裁剪
  4. 响应式压缩reactiveCompact):Feature Flag REACTIVE_COMPACT 门控的实验性方案

压缩完成后还会执行一系列清理操作:清除用户上下文缓存、运行后压缩 hooks(runPostCompactCleanup)、通知缓存断裂检测(notifyCompaction)、标记压缩状态(markPostCompaction)、抑制压缩警告(suppressCompactWarning)。

/rewind:回到过去

/rewind(别名 checkpoint)支持恢复代码和/或对话到之前的状态。checkpoint 别名暗示了它的用途 —— 在关键时刻创建检查点,方便回溯。supportsNonInteractive: false,不支持 SDK 模式。

/clear:一键清空

/clear 有三个入口:/clear/reset/new。实现分为两层:clearSessionCaches(清除会话缓存)和 clearConversation(清除对话)。注意 supportsNonInteractive: false —— 在 SDK 非交互模式下,/clear 不会清除当前会话,而是应该创建一个全新的会话。

/advisor:模型顾问的三层验证
// src/commands/advisor.ts (110 行)
const advisor = {
  type: 'local',
  name: 'advisor',
  description: 'Configure the advisor model',
  argumentHint: '[<model>|off]',
  isEnabled: () => canUserConfigureAdvisor(),  // GrowthBook 配置门控
  get isHidden() {
    return !canUserConfigureAdvisor()  // 未启用时隐藏
  },
  supportsNonInteractive: true,
  load: () => Promise.resolve({ call }),  // 直接返回,无需动态导入
}

/advisor 支持三种操作:show(显示当前配置)、set <model>(设置模型)、unset/off(关闭)。设置模型时有三层验证:parseUserSpecifiedModel() 解析名称 → validateModel() 验证 API 有效性 → isValidAdvisorModel() 验证业务适配性。通过后持久化到用户设置,并检查当前主模型是否兼容 advisor 角色。

local 命令的代表清单

命令 功能 别名
/clear 清除对话历史 reset, new
/compact 压缩对话(保留摘要)
/rewind 恢复到之前状态 checkpoint
/vim 切换 Vim 模式
/cost 显示当前费用
/version 显示版本号
/advisor 配置 advisor 模型

类型三:local-jsx 命令 —— 终端里的"UI 组件"

local-jsx 命令渲染 React/Ink 组件,提供丰富的交互式界面。

// 示例:/help 命令
{
  name: 'help',
  type: 'local-jsx',
  async load() {
    return ({ onExit }) => (
      <Dialog title="Help" onCancel={onExit}>
        <Box flexDirection="column">
          <Text bold>Available Commands:</Text>
          {commands.map(cmd => (
            <ListItem key={cmd.name}>
              <Text color="blue">/{cmd.name}</Text>
              <Text dimColor>{cmd.description}</Text>
            </ListItem>
          ))}
        </Box>
      </Dialog>
    )
  }
}
/resume:恢复对话

/resume(别名 continue)渲染一个对话选择器 UI,让用户从历史会话列表中选择要恢复的会话。continue 别名的设计很贴心 —— 用户可以自然地说"继续上次的对话"。支持通过参数 [conversation id or search term] 直接指定会话。

/branch:对话分叉

/branch 在当前对话点创建一个分支。它的别名设计很有趣:当 FORK_SUBAGENT Feature Flag 开启时,fork 别名会被移除(aliases: feature('FORK_SUBAGENT') ? [] : ['fork']),因为此时存在一个独立的 /fork 命令(用于创建子 Agent)。这是一个别名冲突避免的典型案例。

/export:导出对话

/export 支持两种导出目标:文件(指定文件名参数)或剪贴板(不指定文件名)。

/brief:Kairos 的简要模式
// src/commands/brief.ts (131 行)
const brief = {
  type: 'local-jsx',
  name: 'brief',
  description: 'Toggle brief-only mode',
  isEnabled: () => {
    if (feature('KAIROS') || feature('KAIROS_BRIEF')) {
      return getBriefConfig().enable_slash_command  // GrowthBook 配置
    }
    return false
  },
  immediate: true,
  // load 直接返回 Promise.resolve,无需动态导入
}

/brief 是 Kairos 系统的一部分,它切换"简要模式"—— 在这个模式下,AI 只能通过特定的 Brief 工具输出内容,普通文本输出会被隐藏。它的实现有 131 行,包含几个精妙的设计:

  • Zod schema 验证:GrowthBook 推送的配置通过 z.object({ enable_slack_command: z.boolean() }) 验证,防止错误配置
  • 权益检查只在开启时生效:关闭 brief 模式总是允许的 —— 如果 GrowthBook 门控中途翻转,已开启 brief 模式的用户不会被卡住
  • userMsgOptIn 双向同步:确保 Brief 工具可用性与 brief 模式状态一致,但这会导致 prompt cache 失效
  • 系统提醒注入:工具列表变化不足以让模型"改习惯",所以显式注入 <system-reminder> 告诉模型行为切换
  • Kairos 活跃时跳过提醒getKairosActive() 时 Kairos 系统提示词已经强制使用 SendUserMessage,无需额外提醒

local-jsx 命令的代表清单

命令 功能 别名
/help 帮助信息
/config 配置管理 settings
/model 模型选择
/mcp MCP 管理
/permissions 权限管理 allowed-tools
/resume 恢复对话 continue
/branch 对话分叉 fork(条件)
/export 导出对话
/brief 简要模式
/diff 查看差异
/agents Agent 管理
/skills 技能列表

三、命令注册表:754 行的中央调度

src/commands.ts 是命令的集中注册表,754 行代码,管理着所有命令的生命周期。

注册结构

// src/commands.ts — 命令注册表(简化版)
const COMMANDS = memoize((): Command[] => [
  // ─── 会话管理 ───
  clear, compact, resume, session, exportCommand,
  rename, branch, rewind,

  // ─── 配置 ───
  config, color, theme, vim, keybindings, permissions,
  outputStyle, sandboxToggle, terminalSetup,

  // ─── 认证 ───
  login(), logout, usage, upgrade, extraUsage, passes, privacySettings,

  // ─── MCP 与集成 ───
  mcp, ide, chrome, desktop, mobile, installGitHubApp, installSlackApp,

  // ─── 代码审查与 Git ───
  review, ultrareview, securityReview, pr_comments, diff,

  // ─── 任务/Agent ───
  tasks, agents, plan, skills, memory,

  // ─── 信息 ───
  help, status, cost, stats, context, doctor, files, releaseNotes,

  // ─── AI 功能 ───
  usageReport, thinkback, thinkbackPlay, btw,

  // ─── 开发工具 ───
  hooks, heapDump, copy, reloadPlugins,

  // ─── 其他 ───
  exit, feedback, stickers, tag, statusline,

  // ─── 条件命令(Feature Flag 门控)───
  ...(webCmd ? [webCmd] : []),
  ...(forkCmd ? [forkCmd] : []),
  ...(buddy ? [buddy] : []),
  ...(proactive ? [proactive] : []),
  ...(briefCommand ? [briefCommand] : []),
  ...(assistantCommand ? [assistantCommand] : []),
  ...(bridge ? [bridge] : []),
  ...(remoteControlServerCommand ? [remoteControlServerCommand] : []),
  ...(voiceCommand ? [voiceCommand] : []),
  ...(peersCmd ? [peersCmd] : []),
  ...(workflowsCmd ? [workflowsCmd] : []),
  ...(torch ? [torch] : []),

  // ─── 内部命令(ant-only)───
  ...(process.env.USER_TYPE === 'ant' && !process.env.IS_DEMO
    ? INTERNAL_ONLY_COMMANDS : []),
])

动态命令加载

COMMANDS() 只是基础命令列表。完整的命令列表还需要合并来自四个来源的动态命令:

// src/commands.ts
const loadAllCommands = memoize(async (cwd: string): Promise<Command[]> => {
  const [
    { skillDirCommands, pluginSkills, bundledSkills, builtinPluginSkills },
    pluginCommands,
    workflowCommands,
  ] = await Promise.all([
    getSkills(cwd),           // .claude/skills/ 目录下的技能命令
    getPluginCommands(),      // 插件提供的命令
    getWorkflowCommands(cwd), // 工作流脚本命令
  ])

  return [
    ...bundledSkills,         // 内置技能
    ...builtinPluginSkills,   // 内置插件技能
    ...skillDirCommands,      // 用户自定义技能
    ...workflowCommands,      // 工作流命令
    ...pluginCommands,        // 插件命令
    ...pluginSkills,          // 插件技能
    ...COMMANDS(),            // 基础命令(最后,优先级最低)
  ]
})

最终的 getCommands() 函数会过滤掉不满足 availability 要求和 isEnabled() 返回 false 的命令,并合并运行时动态发现的技能。


四、条件加载与 Feature Flag

Claude Code 大量使用 bun:bundlefeature() 宏进行编译时死代码消除。以下是所有受 Feature Flag 控制的命令:

// src/commands.ts — 条件导入(编译时消除),共 15 个 Flag 门控命令
// 模式:feature('FLAG') ? require('./commands/xxx.js').default : null

// 单 Flag 门控
const voiceCommand = feature('VOICE_MODE')
  ? require('./commands/voice/index.js').default : null
const bridge = feature('BRIDGE_MODE')
  ? require('./commands/bridge/index.js').default : null

// OR 组合(任一 Flag 开启即可)
const proactive = feature('PROACTIVE') || feature('KAIROS')
  ? require('./commands/proactive.js').default : null
const briefCommand = feature('KAIROS') || feature('KAIROS_BRIEF')
  ? require('./commands/brief.js').default : null

// AND 组合(两个 Flag 都需开启)
const remoteControlServerCommand =
  feature('DAEMON') && feature('BRIDGE_MODE')
    ? require('./commands/remoteControlServer/index.js').default : null

// 其他 Flag:FORK_SUBAGENT, BUDDY, WORKFLOW_SCRIPTS, CCR_REMOTE_SETUP,
// KAIROS_GITHUB_WEBHOOKS, ULTRAPLAN, TORCH, UDS_INBOX, HISTORY_SNIP ...

完整的 Feature Flag 命令对照表

命令 Feature Flag(s) 说明
/proactive PROACTIVE OR KAIROS 主动模式
/brief KAIROS OR KAIROS_BRIEF 简要模式
/assistant KAIROS 助手模式
/remote-control BRIDGE_MODE 远程控制
/remote-control-server DAEMON AND BRIDGE_MODE 远程控制服务端
/voice VOICE_MODE 语音模式
/fork FORK_SUBAGENT 子 Agent 分叉
/buddy BUDDY 伙伴模式
/workflows WORKFLOW_SCRIPTS 工作流脚本
/web-setup CCR_REMOTE_SETUP Web 远程设置
/subscribe-pr KAIROS_GITHUB_WEBHOOKS PR 订阅
/ultraplan ULTRAPLAN 超级计划模式
/torch TORCH Torch 模式
/peers UDS_INBOX 同行消息
force-snip HISTORY_SNIP 历史裁剪(内部)

注意 remoteControlServerCommand 需要两个 Flag 同时开启(DAEMON AND BRIDGE_MODE),这体现了它对运行环境的严格要求。


五、环境变量控制:企业级的命令禁用机制

除了 Feature Flag,Claude Code 还支持通过环境变量在运行时禁用特定命令。这主要用于企业部署场景 —— 企业管理员不希望员工使用某些命令(如登录、反馈、升级)。每个被禁用的命令都有一个对应的 isEnabled 检查:isEnabled: () => !isEnvTruthy(process.env.DISABLE_XXX)

完整的环境变量控制表

环境变量 影响的命令 说明
DISABLE_COMPACT /compact 禁用压缩命令
DISABLE_DOCTOR_COMMAND /doctor 禁用诊断命令
DISABLE_LOGIN_COMMAND /login 禁用登录命令
DISABLE_LOGOUT_COMMAND /logout 禁用登出命令
DISABLE_FEEDBACK_COMMAND /feedback 禁用反馈命令
DISABLE_BUG_COMMAND /feedback 禁用 bug 命令(别名)
DISABLE_EXTRA_USAGE_COMMAND /extra-usage 禁用超额使用命令
DISABLE_UPGRADE_COMMAND /upgrade 禁用升级命令
DISABLE_INSTALL_GITHUB_APP_COMMAND /install-github-app 禁用 GitHub App 安装
CLAUDE_CODE_USE_BEDROCK /feedback Bedrock 模式自动禁用反馈
CLAUDE_CODE_USE_VERTEX /feedback Vertex 模式自动禁用反馈
CLAUDE_CODE_USE_FOUNDRY /feedback Foundry 模式自动禁用反馈
USER_TYPE 多个 ant 时启用内部命令和 undercover 模式

注意 /feedback 命令的禁用逻辑最复杂 —— 它同时被 6 个环境变量控制。这是因为第三方服务提供商(Bedrock/Vertex/Foundry)不支持 Anthropic 的反馈通道,所以需要自动禁用。


六、insights.ts:3201 行的巨型命令

/insights 是整个命令系统中最大的单文件(3201 行,113KB),它生成一个完整的 HTML 使用分析报告。正因为它太大,commands.ts 中专门用了一个延迟加载 shim:

// src/commands.ts — 延迟加载 shim
const usageReport: Command = {
  type: 'prompt',
  name: 'insights',
  description: 'Generate a report analyzing your Claude Code sessions',
  contentLength: 0,
  progressMessage: 'analyzing your sessions',
  source: 'builtin',
  async getPromptForCommand(args, context) {
    const real = (await import('./commands/insights.js')).default
    if (real.type !== 'prompt') throw new Error('unreachable')
    return real.getPromptForCommand(args, context)
  },
}

6 阶段报告生成流程

Phase 1: Lite Scan
  → scanAllSessions() 扫描文件系统元数据(无 JSONL 解析)
  → 仅读取目录结构和文件大小,快速估算工作量

Phase 2: SessionMeta 加载
  → loadCachedSessionMeta() 尝试从缓存加载
  → logToSessionMeta() 解析未缓存的 JSONL 会话日志
  → deduplicateSessionBranches() 去重会话分支(同一会话的不同分支)

Phase 3: 特征提取
  → loadCachedFacets() 尝试从缓存加载
  → extractFacetsFromAPI() 对未缓存会话调用 API 提取特征
  → formatTranscriptForFacets() 格式化转录用于特征提取
  → saveFacets() 缓存提取结果

Phase 4: 聚合
  → aggregateData() 聚合所有会话数据
  → detectMultiClauding() 检测并行会话使用(多开 Claude Code)

Phase 5: 洞察生成
  → generateParallelInsights() 并行调用 Claude 生成 6+ 个洞察部分
  → 每个洞察部分独立生成,互不依赖

Phase 6: HTML 生成
  → generateHtmlReport() 生成完整 HTML 报告(~800 行 HTML)
  → generateBarChart() 生成柱状图
  → generateResponseTimeHistogram() 生成响应时间分布图
  → generateTimeOfDayChart() 生成时段使用图
  → buildExportData() 构建导出数据结构

核心数据结构

// 会话元数据 —— 从 JSONL 日志中提取
type SessionMeta = {
  session_id: string
  start_time: string
  end_time: string
  user_message_count: number
  assistant_message_count: number
  duration_minutes: number
  lines_added: number
  lines_removed: number
  files_modified: string[]
  git_commits: number
  language_counts: Record<string, number>  // 如 {"TypeScript": 42, "Python": 10}
  tool_counts: Record<string, number>      // 如 {"Bash": 15, "Read": 30}
}

// 会话特征 —— 通过 API 从转录中提取
type SessionFacets = {
  underlying_goal: string           // 用户的根本目标
  outcome: string                   // 会话结果
  brief_summary: string             // 简要摘要
  goal_categories: string[]         // 目标分类
  user_satisfaction_counts: Record<string, number>  // 满意度统计
  friction_counts: Record<string, number>           // 摩擦点统计
}

// 聚合数据 —— 所有会话的汇总
type AggregatedData = {
  total_messages: number
  total_sessions: number
  date_range: { start: string, end: string }
  languages: Record<string, number>
  tool_counts: Record<string, number>
  goal_categories: Record<string, number>
  outcomes: Record<string, number>
  satisfaction: Record<string, number>
  friction: Record<string, number>
  message_hours: Record<string, number>       // 按小时分布
  tool_error_categories: Record<string, number>
  multi_clauding: { sessions: number, peak: number }
}

// AI 生成的洞察结果
type InsightResults = {
  at_a_glance: string          // 一目了然的总结
  project_areas: string        // 项目区域分析
  interaction_style: string    // 交互风格分析
  what_works: string           // 什么有效
  friction_analysis: string    // 摩擦点分析
  suggestions: string          // 改进建议
  on_the_horizon: string       // 展望
}

关键函数一览

函数 说明
extractToolStats(log) 从会话日志提取工具使用统计
logToSessionMeta(log) 会话日志转元数据(解析消息数、修改文件、语言分布等)
deduplicateSessionBranches(metas) 去重会话分支(同一会话的不同 fork)
formatTranscriptForFacets(log) 格式化转录用于 API 特征提取
extractFacetsFromAPI(log, sessionId) 调用 Claude API 从转录中提取会话特征
detectMultiClauding(metas) 检测并行会话使用(多开 Claude Code)
aggregateData(metas, facets) 聚合所有会话数据
generateParallelInsights(data, facets) 并行调用 Claude 生成 6+ 个洞察部分
generateHtmlReport(data, insights) 生成完整 HTML 报告(~800 行)
generateBarChart / generateResponseTimeHistogram / generateTimeOfDayChart 各类图表生成
buildExportData(data, insights, facets, remoteStats?) 构建导出数据结构
scanAllSessions() 扫描所有项目目录(仅文件系统元数据)
generateUsageReport(options?) 主入口函数

远程主机数据采集(ant-only)

对于 Anthropic 内部用户,/insights 还支持从远程开发主机收集数据:

// 远程主机数据采集
getRunningRemoteHosts()              // 获取运行中的远程主机列表
getRemoteHostSessionCount(host)      // 获取单个主机的会话数
collectFromRemoteHost(host, destDir) // 从单个主机收集数据到本地目录
collectAllRemoteHostData(destDir)    // 从所有主机批量收集

这些远程主机通常是 Anthropic 内部的云开发环境,工程师可能同时在多个环境中使用 Claude Code。


七、插件迁移模式:从内置到插件的无缝过渡

这是命令系统中最有趣的设计之一。部分内置命令正在从"编译进二进制"迁移到"插件安装"。

createMovedToPluginCommand 工厂(66 行)

// src/commands/createMovedToPluginCommand.ts (66 行)
export function createMovedToPluginCommand({
  name, description, progressMessage,
  pluginName, pluginCommand,
  getPromptWhileMarketplaceIsPrivate,  // 市场未公开时的回退逻辑
}: Options): Command {
  return {
    type: 'prompt',
    name,
    description,
    progressMessage,
    contentLength: 0,
    source: 'builtin',
    async getPromptForCommand(args, context): Promise<ContentBlockParam[]> {
      // ─── Ant 用户:显示插件安装指引 ───
      if (process.env.USER_TYPE === 'ant') {
        return [{
          type: 'text',
          text: `This command has been moved to a plugin. Tell the user:
1. Install: claude plugin install ${pluginName}@claude-code-marketplace
2. Use: /${pluginName}:${pluginCommand}
3. Docs: https://github.com/anthropics/claude-code-marketplace/blob/main/${pluginName}/README.md`,
        }]
      }
      // ─── 其他用户:保留原始 prompt 逻辑 ───
      return getPromptWhileMarketplaceIsPrivate(args, context)
    },
  }
}

这个工厂函数的核心是一个两阶段迁移策略

  1. Ant 用户(Anthropic 内部员工):获得插件安装指引,告诉他们去 marketplace 安装
  2. 其他用户(外部用户):获得原始的 prompt 逻辑,体验完全不变

使用此模式的命令

命令 插件名 插件命令 原始逻辑
/security-review security-review security-review 196 行安全审查提示词
/pr-comments pr-comments pr-comments PR 评论获取逻辑

这个模式的巧妙之处在于:对用户完全透明。无论命令是内置还是插件,用户输入 /security-review 的体验是一样的。内部员工提前体验插件版本,外部用户继续使用内置版本,直到 marketplace 公开后统一切换。

迁移状态在代码中的体现是 getPromptWhileMarketplaceIsPrivate 这个参数名 —— 它明确告诉未来的维护者:“这个回退逻辑只在 marketplace 是私有的时候需要,公开后可以删除。”


八、设计亮点总结

设计决策 价值
三种命令类型 职责分离:prompt 走 AI,local 走本地,jsx 走 UI
延迟加载 load() 命令代码按需加载,/insights 的 113KB 不影响启动速度
别名系统 /reset/clear/continue/resume,降低记忆负担
条件别名 /fork 别名在 FORK_SUBAGENT 开启时自动移除,避免冲突
插件迁移工厂 内置命令无缝迁移到插件,内外用户体验一致
Feature Flag 门控 15+ 个实验性命令渐进发布,编译时死代码消除
环境变量禁用 企业环境可禁用 10+ 个敏感命令
availability 访问控制 按认证状态过滤命令(claude-ai vs console)
安全审查误报过滤 17+ 条硬排除规则 + 12 条先例规则,大幅降低噪声
/init 8 阶段设置 交互式引导,只写 Claude 会犯错的东西
/compact 多层压缩 会话记忆 → 标准 → 微 → 响应式,四层压缩策略
undercover 模式 Anthropic 内部特殊指令,自动移除 reviewer/Slack 等敏感步骤

下篇预告

第五篇:35 个内置工具的瑞士军刀

命令是面向用户的入口,工具才是 AI 真正的"手脚"。Claude Code 内置了 35+ 工具,从文件读写到 Shell 执行,从网页搜索到 Agent 调度。所有工具都通过一个统一的 buildTool() 工厂函数构建,支持输入验证、权限检查、并发安全标记和 UI 渲染。

下一篇,我们将深入工具系统的架构,看看 AI 是如何通过这些"瑞士军刀"操作你的电脑的。


标签: Claude Code 斜杠命令 Command接口 prompt命令 插件系统 TypeScript 源码分析 Feature Flag 安全审查 insights

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐