你每天在 Claude Code 里敲多少次同样的 Prompt?“Review this code for bugs”“Run the test suite and fix failures”“Generate docs for this module”,每次都要重新打字或者复制粘贴。一开始还能忍,时间一长你就知道这东西不对劲,你明明在用 AI 编程,却还在手动重复固定的文本输入。
slash command 就是解决这个问题的。它本质上是一个 Markdown 文件,定义了 Claude 在交互会话中执行的常用提示词。一次定义,反复调用。Anthropic 专门做了一个 Skill 来教你创建和管理这些命令,这就是 Smithery 上架的 command-development。
一般这种”官方教你用官方功能”的文档很容易写成 API 参考手册,但翻完这个 Skill 之后我发现,它的结构本身就是一个命令系统的最佳实践样本。它不光告诉你有哪些字段可以填,更重要的是它展示了四个维度的经验:
-
命令该长什么样,不是语法上对不对,是”好的命令”长什么样 -
什么时候该加权限,不是加了就行,是不加会出什么问题 -
参数怎么传才有用,不是能用就行,是传什么样的参数结构能让命令真正可复用 -
文件结构怎么组织才能撑到 15 个以上命令而不乱
说白了这篇文章就做一件事:把这个 Skill 里的关键设计思路和实操要点拆出来,让你建完第一个命令之后,能继续建出真正能复用的命令,而不是又一个“打完了才想起有这回事”的死文件。

环境准备
用这个 Skill 的前提是你已经在用 Claude Code。命令系统是 Claude Code 的原生能力,不需要额外安装任何依赖。Skill 本身通过 Smithery 平台分发,获取方式和普通 Skill 一样。
前置条件很简单:
| 条件 | 说明 |
|---|---|
| Claude Code | 已安装并可用 |
| 文件系统 | 能读写 ~/.claude/commands/ 和项目目录下的 .claude/commands/ |
命令文件放在两个位置,各有各的用。项目级命令放在 .claude/commands/,跟着仓库走,团队共享。个人命令放在 ~/.claude/commands/,所有项目通用,适合你自己惯用的工作流。还有一个插件级路径,装了第三方插件时会自动带上,不需要你手动管理。
这套三层隔离设计处理得挺干净:不需要任何全局配置,也没有复杂的注册流程。你创建一个 .md 文件,Claude Code 重启之后自动就能用了。验证也很直接,敲一个 /help 看看你的命令在不在列表里就行。

有一点文档没明说但我实测重要的事:文件编码必须 UTF-8,YAML frontmatter 的缩进必须用空格不能用 Tab。这两个坑会让命令静默加载失败,不会报错,排查起来很折磨。
操作流程
一个完整的命令从创建到上线走四步:
-
写主体内容 -
加 YAML frontmatter -
注入动态参数 -
挂到合适的位置
下面按执行链路拆开看。
第一步:写命令主体。 最简形式就是一个纯 Markdown 文件,不需要任何元数据。比如创建一个 review.md,内容就是一段审查指令:
Review this code for security vulnerabilities including SQL injection, XSS attacks, authentication bypass, and insecure data handling.
敲 /review 就能触发。但这种写法有一个大问题:它只是一个静态文本块,跟直接粘贴 Prompt 没有本质区别。真正发挥命令系统威力的东西在后面三步。
第二步:配 YAML frontmatter。 命令的 frontmatter 有五个字段,但真正影响命令行为的是前四个。
description 决定了你的命令在 /help 里怎么显示。起名要具体,不要写“Code review”,写“Review code for security vulnerabilities”。这跟给函数起名一个逻辑,它要能说明这个命令到底干什么。
allowed-tools 是整个 Skill 里最容易被低估的设计决策。默认情况下,命令继承当前对话的工具权限。这意味着如果你在 GitHub 相关对话里跑 /test,它可能意外触发 gh 命令。显式指定 Bash(npm:*) 不光是为了安全,更是一种自文档化:你一看就知道这个命令的职责边界在哪。
model 字段可以指定执行命令时用的模型。haiku 适合快速命令,sonnet 适合标准工作流,opus 适合复杂分析。这个设计的一个隐含约束是:你每建一个命令,实际上也在定义它的性能预算。一个用 opus 跑“format this file”的命令,本质上是资源浪费。
argument-hint 是参数系统的约定接口,不是强制校验。你写了 [pr-number] [priority] 但传了三个参数,命令不会报错,只会把你多传的东西拼到 $3 上。这个设计确实有点糙,但好处是不会因为参数校验失败就拒绝执行。

第三步:用动态参数让命令活起来。 位置参数 $1、$2、$3 和全量参数 $ARGUMENTS 是一个极简但有效的设计。比如一个 PR 审查命令:
---
description: Review PR with priority and assignee
argument-hint: [pr-number] [priority] [assignee]
allowed-tools: Bash(gh:*), Read
---
PR #$1 Workflow:
1. Fetch PR: !`gh pr view $1`
2. Review changes
3. Run checks
4. Approve or request changes
用法是 /review-pr 123 high alice。注意这里 Bash 执行是内联的,用反引号包起来。它的权限受 allowed-tools 约束,所以 Bash(gh:*) 之外的操作全部被拦截。
第四步:选对组织结构。 5 到 15 个命令用扁平结构就行,直接堆在命令目录根下。超过 15 个或者有明确的类别,用命名空间子目录:
.claude/commands/
├── ci/
│ ├── build.md
│ ├── test.md
│ └── lint.md
├── git/
│ ├── commit.md
│ └── pr.md
└── docs/
├── generate.md
└── publish.md
这个规则本身不复杂,但 Skill 文档里埋了一个容易被忽略的设计选择:命名空间不会被 /help 自动分组显示。你建了 ci/build.md,它在 /help 里显示的是 /build (project:ci)。如果你的团队依赖 /help 查看命令列表,命名空间带来的分组增益其实打了折扣,本质上只是文件系统的组织逻辑,没有映射到用户界面。
关键设计
这个 Skill 最值得聊的设计不是命令怎么写,是它暗中定义了一套“命令设计好坏的评判标准”。整套文档读下来,你会发现它一直在传递同一个信号:一个命令的好坏,不取决于它写了什么 Prompt,而取决于它如何处理边界条件。
权限控制就是最典型的例子。Skill 推荐的做法是把 allowed-tools 压缩到最小权限,比如 Bash 只允许 git:* 或 npm:*,需要读文件时再加 Read。这是一种极端的白名单思维,和大多数 CLI 工具的默认行为(全部放行)完全相反。从安全角度看这当然是正确的,但从开发者体验看,它对命令创建者的要求太高了,你得在写命令的时候就想清楚每一步需要什么权限,而大多数人建第一个命令的时候脑子里想的只是“我要它帮我做什么”。
参数设计也有类似的取舍。argument-hint 只是提示性的,不强制校验。这避免了“传错参数就报错退出”的粗暴体验,但也意味着错误参数的后果可能要等到命令执行到一半才会暴露。Skill 文档里列举了几种验证模式,比如 !echo “$1” | grep -E “^(dev|staging|prod)$”“,但这些本质上是在把校验逻辑回退到 Bash 层面,绕过了框架本身。
文件引用和 Bash 内联的组合是另一个值得一提的设计。@src/old-version.js 可以直接把文件内容拉进 Prompt 上下文,!git diff –name-only“ 可以动态获取仓库状态。这两个机制加在一起,等于给了命令一个极轻量的上下文感知能力,不需要维护复杂的上下文管理逻辑,两个语法糖就能让命令的 Prompt 根据当前环境动态调整。
但我对插件命令的设计持保留态度。${CLAUDE_PLUGIN_ROOT} 变量解决了路径引用的可移植性问题,但它带来的心智负担不小。一个要从插件目录加载脚本的命令,路径会变成 !node ${CLAUDE_PLUGIN_ROOT}/scripts/analyze.js $1“,新接触的人很难一眼看懂这行命令在干嘛。
使用场景
拆两个典型场景,看看这套系统在实际开发中的表现。
场景一:自动化 PR 工作流。 假设你的团队标准 PR 流程是下面这五步:
-
拉代码 -
跑测试 -
跑 lint -
检查覆盖率 -
生成 review 摘要
每个 PR 都要手动执行这五步,中间还有大量重复的交互。用命令系统把整个流程串起来之后,一个 /pr-merge 456 就能自动走完。中间每一步的临时信息都会在对话上下文中,不需要人工介入填写。效果差距不是省了多少次键盘敲击,是整个流程从”边做边想下一步”变成”触发后等结果”,认知负担的降低比时间节省更明显。
场景二:团队新人 onboarding。 新人在 Claude Code 里不知道该敲什么,这是最常见的卡点。把团队的常用命令,代码规范检查、测试框架调用、部署检查清单,做成命令文件放在 .claude/commands/ 下,新人敲 /help 就能看到所有可用操作。命令的 description 要写得像操作手册条目,不只是功能描述,要包含“为什么用这个命令而不是手动操作”的判断依据。一个写得好 description 的 /lint 命令,可以替代三百字的团队文档里的 lint 说明段落。
这两个场景暴露了同一个事实:命令系统最大的价值不在技术层面,而在组织层面。它把隐性的团队工作流外化成可共享、可检查、可迭代的文件。那些写在 Notion 页面里“跑 CI 之前记得先跑 lint”的提醒,可以用一个 /pre-push 命令替换,而且这个命令不会被人遗忘。

洞察与反思
翻完这个 Skill,最让我意外的是它体现出来的设计克制。命令系统的能力边界非常清晰:它不试图变成 Agent 编排工具,不试图定义复杂的任务依赖,甚至不支持命令间调用。这种“少即是多”的设计在 AI 工具生态里越来越少见,现在大家都在往“一个 Agent 能搞定一切”的方向卷。
但克制不等于没问题。权限管理虽然灵活,但配置门槛太高。一个“Bash 只允许 git 相关操作”的权限配置,本质是在要求用户能预判命令执行时的所有可能操作路径。对于简单的命令这没问题,一旦命令开始组合 Bash 内联、文件引用、外部脚本调用,预判所有权限边界的难度会指数增长。
另一个被低估的问题是命令的可维护性。命令文件是 Markdown 文本,没有任何原生支持:
-
版本化管理 -
自动化测试 -
依赖追踪
你建了三十个命令之后,哪个命令依赖哪个外部脚本、哪个命令引用了哪些文件、某个脚本改了之后哪些命令会受影响,这些信息全都不在系统里,只能靠人工维护。插件命令引入了 ${CLAUDE_PLUGIN_ROOT} 变量试图解决可移植性问题,但反而让依赖追踪变得更加隐式。
从更广的视角看,Claude Code 的命令系统和 Cursor 的 Rules 系统做的事情很像,都是一次定义、反复执行的 Prompt 模板。区别在于 Rules 是环境级约束(对整个项目生效),命令是按需调用的操作单元。这种差异不是偶然的,它反映了两个产品对“AI 编程”本质的不同理解:Cursor 认为约束应该作为上下文贯穿全程,Claude Code 认为应该作为工具随时调用。我倾向于后一种理解更符合实际开发节奏,但前一种在减少重复配置上的优势也不容忽视。

资源地址
| 资源 | 地址 |
|---|---|
| Smithery 页面 | smithery.ai/skills/anthropics/command-development |
| Claude Code 文档 | docs.anthropic.com/en/docs/claude-code |
总结
命令开发这个 Skill,本质上是在解决一个很朴素的命题:怎么让 AI 编程工具里的重复操作不再重复。它给的解法是把 Prompt 做成可配置的文件,叠上四层能力:
-
动态传参 -
权限白名单 -
模型选择 -
文件引用
把一个标量操作变成一个状态机器。
回头看那些真正有用的命令,它们的共同特征不是 Prompt 写得多漂亮,而是边界条件处理得足够干净,参数校验到位了没、权限锁紧了吗不需要的放行没、命名空间和 description 能不能让三个月后的你自己一眼看懂这个命令在干嘛。这些才是命令做工扎不扎实的检查点,不是 Prompt 文采好不好。
建第一个命令很简单,五分钟就能跑起来。但从第一个到第十个,从“能跑就行”到“团队能靠它省时间”,这个过程需要的不只是看文档,是养成一种习惯:每次想敲一个重复的 Prompt 之前,问一下自己,这个能不能变成一个命令。

