深入拆解 Claude Code 源码(四):77 个斜杠命令背后的三种设计模式与插件迁移之路
深入拆解 Claude Code 源码(四):77 个斜杠命令背后的三种设计模式与插件迁移之路
系列:深入拆解 Claude Code 源码 | 第 4 篇 / 共 8 篇
关键词:Claude Code, 斜杠命令, Command 接口, prompt 命令, local 命令, 插件系统
开篇:一个命令,三种命运
在 Claude Code 里输入 /commit,AI 会帮你写一个 commit message 并提交代码。输入 /vim,终端会切换到 Vim 编辑模式。输入 /help,会弹出一个漂亮的 React 帮助面板。
这三个命令看起来都是"斜杠命令",但它们的内部实现完全不同:
/commit是 prompt 类型 —— 它生成一段 AI 提示词,交给对话引擎处理/vim是 local 类型 —— 它直接在本地执行 JavaScript 逻辑/help是 local-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()并行获取defaultBranch和prAttribution。 - 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 命令中最复杂的一个。它不只是"清除历史",而是一套精心设计的对话压缩系统。命令定义很简单:isEnabled 受 DISABLE_COMPACT 环境变量门控,支持非交互模式,支持自定义摘要指令作为参数。
compact.ts 的实现(约 100+ 行)包含多层压缩策略:
- 会话记忆压缩(
trySessionMemoryCompaction):优先尝试,不支持自定义指令 - 标准压缩(
compactConversation):调用 AI 生成对话摘要 - 微压缩(
microcompactMessages):对消息进行细粒度裁剪 - 响应式压缩(
reactiveCompact):Feature FlagREACTIVE_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:bundle 的 feature() 宏进行编译时死代码消除。以下是所有受 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)
},
}
}
这个工厂函数的核心是一个两阶段迁移策略:
- Ant 用户(Anthropic 内部员工):获得插件安装指引,告诉他们去 marketplace 安装
- 其他用户(外部用户):获得原始的 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
更多推荐



所有评论(0)