本章概述
系列目录:Claude Code 源码分析系列索引
本章深入分析 Claude Code 的 Commands 命令系统,这是用户与 AI 交互的主要入口。Claude Code 支持 88+ 个内置命令,通过 /command-name 的方式调用。
你将学到
- ✅ 三种命令类型的区别与应用场景
- ✅ 命令系统的架构设计与延迟加载
- ✅ 如何编写自定义命令
- ✅ Prompt 命令的工作原理
命令系统概览
flowchart TB
subgraph Commands["Commands 系统"]
A[commands.ts] --> B[88+ 命令实现]
B --> C1[PromptCommand]
B --> C2[LocalCommand]
B --> C3[LocalJSXCommand]
end
subgraph Registry["注册中心"]
D[Commander.js] --> E[命令解析]
E --> F[命令匹配]
F --> G[命令执行]
end
subgraph Types["命令类型"]
C1 --> H1[提示词模板]
C2 --> H2[本地函数]
C3 --> H3[React 组件]
end
A --> D
核心文件结构
src/
├── commands.ts # 命令注册中心
├── commands/ # 88+ 命令实现
│ ├── init.ts # /init 命令
│ ├── commit.ts # /commit 命令
│ ├── skills/ # /skills 命令目录
│ ├── tasks/ # /tasks 命令目录
│ └── ... # 其他命令
└── types/command.ts # 命令类型定义
命令类型系统
Claude Code 定义了三种命令类型,位于 src/types/command.ts:
// types/command.ts:205-206
export type Command = CommandBase &
(PromptCommand | LocalCommand | LocalJSXCommand)
1. PromptCommand - 提示词命令
特点:将用户输入转换为 AI 提示词
// types/command.ts:25-57
export type PromptCommand = {
type: 'prompt'
progressMessage: string
contentLength: number
argNames?: string[]
allowedTools?: string[] // 限制可用工具
model?: string // 指定模型
source: SettingSource | 'builtin' | 'mcp' | 'plugin' | 'bundled'
hooks?: HooksSettings // 关联的 hooks
context?: 'inline' | 'fork' // 执行上下文
agent?: string // fork 模式下使用的代理类型
effort?: EffortValue // 工作量级别
paths?: string[] // 适用文件路径
getPromptForCommand(
args: string,
context: ToolUseContext,
): Promise<ContentBlockParam[]>
}
典型示例:/commit 命令
// commands/commit.ts:57-92
const command = {
type: 'prompt',
name: 'commit',
description: 'Create a git commit',
allowedTools: [
'Bash(git add:*)',
'Bash(git status:*)',
'Bash(git commit:*)',
],
contentLength: 0, // 动态内容
progressMessage: 'creating commit',
source: 'builtin',
async getPromptForCommand(_args, context) {
const promptContent = getPromptContent()
const finalContent = await executeShellCommandsInPrompt(
promptContent,
context,
'/commit',
)
return [{ type: 'text', text: finalContent }]
},
} satisfies Command
2. LocalCommand - 本地命令
特点:执行本地 JavaScript/TypeScript 函数
// types/command.ts:62-78
export type LocalCommandCall = (
args: string,
context: LocalJSXCommandContext,
) => Promise<LocalCommandResult>
type LocalCommand = {
type: 'local'
supportsNonInteractive: boolean
load: () => Promise<LocalCommandModule> // 延迟加载
}
export type LocalCommandModule = {
call: LocalCommandCall
}
执行流程:
sequenceDiagram
participant User as 用户
participant CLI as Commander
participant Loader as 延迟加载器
participant Module as 命令模块
User->>CLI: /command args
CLI->>Loader: load()
Loader->>Module: require('./command')
Module-->>Loader: { call }
Loader-->>CLI: LocalCommandModule
CLI->>Module: call(args, context)
Module-->>CLI: LocalCommandResult
CLI-->>User: 显示结果
3. LocalJSXCommand - React 命令
特点:渲染 React 组件到终端 UI
// types/command.ts:131-152
export type LocalJSXCommandCall = (
onDone: LocalJSXCommandOnDone,
context: ToolUseContext & LocalJSXCommandContext,
args: string,
) => Promise<React.ReactNode>
type LocalJSXCommand = {
type: 'local-jsx'
load: () => Promise<LocalJSXCommandModule> // 延迟加载
}
export type LocalJSXCommandModule = {
call: LocalJSXCommandCall
}
应用场景:需要复杂交互的命令,如配置向导、多步骤表单。
命令基础属性
所有命令共享的基础属性(CommandBase):
// types/command.ts:175-203
export type CommandBase = {
availability?: CommandAvailability[] // 可用性限制
description: string // 命令描述
hasUserSpecifiedDescription?: boolean // 用户自定义描述
isEnabled?: () => boolean // 是否启用
isHidden?: boolean // 是否隐藏
name: string // 命令名
aliases?: string[] // 别名
isMcp?: boolean // 是否 MCP 命令
argumentHint?: string // 参数提示
whenToUse?: string // 使用场景说明
version?: string // 版本
disableModelInvocation?: boolean // 禁用模型调用
userInvocable?: boolean // 用户可调用
loadedFrom?: 'commands_DEPRECATED' | 'skills' | 'plugin' | 'managed' | 'bundled' | 'mcp'
kind?: 'workflow' // 工作流类型
immediate?: boolean // 立即执行
isSensitive?: boolean // 敏感命令(参数脱敏)
userFacingName?: () => string // 显示名称
}
命令注册机制
集中式注册
所有命令在 commands.ts 中导入并导出:
// commands.ts
import init from './commands/init.js'
import commit from './commands/commit.js'
import skills from './commands/skills/index.js'
// ... 88+ 个导入
export function getCommands() {
return {
init,
commit,
skills,
// ...
}
}
Commander.js 集成
使用 Commander.js 处理 CLI 参数解析:
// main.tsx 中的命令注册
import { Command as CommanderCommand } from '@commander-js/extra-typings';
const program = new CommanderCommand()
.name('claude')
.description('Claude Code CLI')
.version(version);
// 注册所有命令
const commands = getCommands()
for (const [name, command] of Object.entries(commands)) {
program.addCommand(createCommanderCommand(name, command))
}
延迟加载机制
为什么需要延迟加载?
Claude Code 有 88+ 个命令,如果全部在启动时加载:
- 启动慢 - 需要解析和执行所有命令模块
- 内存占用高 - 加载不必要的依赖
- 循环依赖风险 - 模块间可能相互依赖
延迟加载实现
// 延迟加载模式
const myCommand = {
type: 'local',
name: 'heavy-command',
load: () => import('./heavy-command/index.js'),
// 只有在执行时才调用 load()
}
对比直接导入 vs 延迟加载:
// ❌ 直接导入 - 启动时加载
import heavyCommand from './commands/heavy/index.js'
// ✅ 延迟加载 - 使用时加载
const heavyCommand = {
type: 'local',
load: () => import('./commands/heavy/index.js'),
}
命令可用性控制
基于认证的可用性
// types/command.ts:169-174
export type CommandAvailability =
| 'claude-ai' // claude.ai OAuth 订阅者
| 'console' // Console API key 用户
// 使用示例
const command = {
name: 'premium-feature',
availability: ['claude-ai'], // 仅付费用户可用
// ...
}
动态启用控制
const command = {
name: 'experimental',
isEnabled: () => feature('EXPERIMENTAL_FLAG'),
// ...
}
实战:编写自定义命令
示例 1:简单的 Prompt 命令
// commands/my-command.ts
import type { Command } from '../commands.js'
const command: Command = {
type: 'prompt',
name: 'my-command',
description: 'My custom command',
progressMessage: 'processing',
source: 'builtin',
contentLength: 100,
async getPromptForCommand(args, context) {
return [
{
type: 'text',
text: `Please help me with: ${args}`
}
]
}
}
export default command
示例 2:Local 命令
// commands/my-local-command/index.ts
import type { LocalCommandModule } from '../../types/command.js'
export const call: LocalCommandModule['call'] = async (args, context) => {
// 执行本地逻辑
const result = await doSomething(args)
return {
type: 'text',
value: result
}
}
示例 3:LocalJSX 命令
// commands/my-jsx-command/index.tsx
import React from 'react'
import { Box, Text } from 'ink'
import type { LocalJSXCommandModule } from '../../types/command.js'
export const call: LocalJSXCommandModule['call'] = async (onDone, context, args) => {
const [count, setCount] = React.useState(0)
return (
<Box flexDirection="column">
<Text>Count: {count}</Text>
<Text>Press Enter to continue...</Text>
</Box>
)
}
命令执行上下文
LocalJSXCommandContext
// types/command.ts:80-98
export type LocalJSXCommandContext = ToolUseContext & {
canUseTool?: CanUseToolFn
setMessages: (updater: (prev: Message[]) => Message[]) => void
options: {
dynamicMcpConfig?: Record<string, ScopedMcpServerConfig>
ideInstallationStatus: IDEExtensionInstallationStatus | null
theme: ThemeName
}
onChangeAPIKey: () => void
onChangeDynamicMcpConfig?: (config: Record<string, ScopedMcpServerConfig>) => void
onInstallIDEExtension?: (ide: IdeType) => void
resume?: (sessionId: UUID, log: LogOption, entrypoint: ResumeEntrypoint) => Promise<void>
}
onDone 回调
// types/command.ts:117-126
export type LocalJSXCommandOnDone = (
result?: string,
options?: {
display?: CommandResultDisplay // 'skip' | 'system' | 'user'
shouldQuery?: boolean // 是否发送给模型
metaMessages?: string[] // 元消息
nextInput?: string // 下一个输入
submitNextInput?: boolean // 是否自动提交
},
) => void
命令分类
内置命令分类
| 类别 | 命令示例 | 说明 |
|---|---|---|
| Git 操作 | /commit, /branch |
版本控制相关 |
| 会话管理 | /clear, /compact, /resume |
会话生命周期 |
| 配置 | /config, /theme, /settings |
用户配置 |
| 开发工具 | /review, /test, /debug |
开发辅助 |
| 代理 | /agents, /team |
子代理管理 |
| 技能 | /skills |
技能系统 |
| 插件 | /plugin, /mcp |
扩展管理 |
| 诊断 | /doctor, /cost |
系统诊断 |
最佳实践
1. 命令设计原则
// ✅ 好的命令设计
const goodCommand = {
name: 'clear',
description: 'Clear the conversation', // 清晰简洁
progressMessage: 'clearing', // 进行时状态
isEnabled: () => hasActiveSession(), // 条件启用
// ...
}
// ❌ 避免
const badCommand = {
name: 'do-something-vague',
description: 'This command does something', // 描述不清
// 缺少 progressMessage
// ...
}
2. 延迟加载优先
// ✅ 对于复杂命令,使用延迟加载
const heavyCommand = {
type: 'local',
load: () => import('./heavy/index.js'), // 动态导入
}
// ❌ 避免直接导入重型依赖
import { heavyDependency } from 'heavy-lib' // 启动时加载
3. 工具权限控制
// ✅ 限制命令可用工具
const safeCommand = {
type: 'prompt',
allowedTools: [
'Bash(git add:*)', // 只允许特定 git 命令
'Bash(git status:*)',
],
// ...
}
小结
本章深入分析了 Claude Code 的命令系统:
关键概念
| 概念 | 说明 | 应用场景 |
|---|---|---|
| PromptCommand | 生成提示词给 AI | 需要 AI 处理的任务 |
| LocalCommand | 执行本地函数 | 纯本地操作 |
| LocalJSXCommand | 渲染 React UI | 交互式命令 |
| 延迟加载 | 使用时才加载 | 减少启动时间 |
| 可用性控制 | 基于认证/标志 | 功能灰度发布 |
架构优势
- 类型安全 - TypeScript 类型定义完整
- 可扩展 - 三种命令类型覆盖各种场景
- 高性能 - 延迟加载减少启动时间
- 灵活 - 支持条件启用和权限控制
学习收获
- 🎯 命令模式实践 - 88+ 命令的统一管理
- 🔄 延迟加载策略 - 大型应用的启动优化
- 🎨 类型设计 - TypeScript 高级类型应用
- 🛡️ 权限控制 - 基于认证的可用性管理
系列导航:
- ← 上一篇:第1章:项目架构与入口分析
- → 下一篇:第3章:Tools 工具系统设计解析
- 返回:系列索引