<!-- title: 自定义斜杠命令：提示词一键化 -->

# 自定义斜杠命令开发实战：把重复提示词固化为一键指令

## 概述

每个 Claude Code 用户都有几段反复输入的提示词——"看一下失败的测试告诉我哪错了""基于 diff 开个 PR""跑 lint，能自动修的修掉，修不了的留着"。这些都是成段的话，每周会被重打、改写或从笔记里复制几十次。**自定义斜杠命令（Custom Slash Commands）就是为消灭这些重复而生**：把一段保存好的提示词写成 Markdown 文件，用 `/名字` 一键调用，让同样的工作每次都以同一种方式发生。本教程适合已跑通过 Claude Code 首个项目的开发者，目标是你读完就能在自己的项目里发布 `/review`、`/pr`、`/release:notes` 等可复用命令，并理解它和 Skill、Subagent、Hook 的边界。

## 前置条件

- 已安装 Claude Code（v2.0 及以上，`/clear` 等 SDK 命令需 v2.1.117+）并能完成一轮对话；
- 一个用于练习的 Git 仓库（哪怕只有一个 `README.md`）；
- 会用任意文本编辑器创建 `.md` 文件；
- 了解基本 YAML 语法（只需会写 `key: value`）。

---

## 一、斜杠命令到底是什么

剥掉营销话术，**一个斜杠命令就是放在特定目录下的一个 Markdown 文件**。文件名去掉 `.md` 后缀就是命令名，文件正文就是被注入会话的提示词。

没有 DSL，没有插件清单，没有编译步骤。如果你能在文本编辑器里写一段话，你就能发布一个斜杠命令。

两个目录决定了一切：

| 作用域 | 路径 | 行为 |
|--------|------|------|
| 项目级 | `.claude/commands/` | 随仓库进入 Git，团队每个克隆者都能用 |
| 个人级 | `~/.claude/commands/` | 存在家目录，跨所有项目跟随你，仅你可见 |

放在 `.claude/commands/ship-it.md` 的文件，在任何打开于该仓库的会话里都会显示为 `/ship-it`；放在 `~/.claude/commands/standup.md` 的文件，则到处都显示为 `/standup`。

子目录会变成命名空间：`.claude/commands/release/notes.md` 会变成 `/release:notes`。当命令超过十个、自动补全开始拥挤时，这一点很关键。

> **趋势提示**：官方推荐的新格式是 `.claude/skills/<name>/SKILL.md`，它既支持 `/名字` 调用，也支持 Claude 自主触发。`.claude/commands/` 是经典格式，CLI 仍完全支持，本文聚焦经典格式因为它最轻量、最适合"一个命令一个动作"的场景。两者并不冲突，可共存。

---

## 二、第一个命令：从一行开始

最小可用的命令只有一行。在你的项目根目录创建 `.claude/commands/recap.md`，内容如下：

```markdown
对照 main 分支总结 diff，写成 3 条要点形式的 PR 描述。不要表情符号，不要营销腔。
```

在任何会话里输入 `/recap`，Claude 会把这段指令当作一条全新的用户消息处理：它运行 `git diff`、读取改动、按你偏好的风格写出 PR 描述。

这就是全部形状。本教程剩下的一切都是对它的变形。

**预期结果**：输入 `/` 后弹出命令选择器，能看到 `recap` 条目；选中或输入 `/recap` 回车，Claude 立即开始分析当前分支与 main 的差异并产出三条要点。

---

## 三、Frontmatter：值得记住的几个旋钮

斜杠命令文件顶部可写一段 YAML frontmatter，用来微调命令行为。真正会用到的字段如下：

```yaml
---
description: 为当前分支开一个带摘要的 PR
argument-hint: [可选的 reviewer 账号]
allowed-tools: Bash(git:*), Bash(gh:*)
model: claude-sonnet-4-6
---
```

逐项说明：

- **`description`**：在斜杠命令选择器里显示的一行说明。**务必写**——若省略，选择器会显示正文第一行，而那往往不是你想要的。
- **`argument-hint`**：在输入框显示的占位提示。纯属外观，但它告诉用户命令需要什么形状的输入。
- **`allowed-tools`**：命令被允许**无需逐次询问**即可调用的工具白名单。请收窄到命令真正需要的范围。`Bash(git:*)` 允许运行任意 git 子命令；`Bash(git status)` 只允许运行那条精确命令。
- **`model`**：为本命令覆盖会话模型。把廉价机械的命令路由到 Haiku，把重活留给 Opus。

对于个人命令你可以全部忽略，对项目命令大多数也用不上。但有两个字段稳定地物有所值：`description`（让团队成员能读懂选择器）和 `allowed-tools`（让命令不必每次运行都弹权限）。

---

## 四、参数化：`$ARGUMENTS` 与位置占位符

一个命令从"便签"升级为"工具"，始于它接受输入。斜杠命令名字之后的任何内容，在命令正文里都可作为 `$ARGUMENTS` 访问：

```markdown
---
description: 开 PR 并指定 reviewer
argument-hint: <github-handle>
---
为当前分支开一个 PR，标题清晰、正文三段摘要，然后请求 @$ARGUMENTS 审查。
```

调用 `/pr alice` 会把 `alice` 替换进提示词，再交给 Claude。`/pr alice bob` 则替换为 `alice bob`。**没有位置解析**——`$ARGUMENTS` 是整个尾部字符串，你把它当成一个整体来处理。

如果命令需要结构化输入，最佳做法是让提示词声明它期望的结构、交给 Claude 去解析，而不是发明一套语法：

> "把 `$ARGUMENTS` 当作以逗号分隔的文件路径列表。对每一个……"

这比硬造一套参数语法更耐久。

需要位置参数时，可用 `$0`、`$1` 编号占位符，并通过 `argument-hint` 声明形状：

```markdown
---
argument-hint: [issue-number] [priority]
description: 修复一个 GitHub issue
---
修复 issue #$0，优先级为 $1。先查 issue 描述，再实现必要的改动。
```

`/fix-issue 123 high` 会让 `$0="123"`、`$1="high"`。

---

## 五、正文里的三种动态注入

除了 `$ARGUMENTS`，命令正文还支持三种让提示词"活起来"的机制，这是把命令写出工程感的关键。

### 1. Bash 命令执行——`!`反引号

用 `!` 加反引号可在提示词里内联执行 bash 并把输出嵌入正文：

```markdown
---
allowed-tools: Bash(git add *), Bash(git status *), Bash(git commit *)
description: 创建一个 git commit
---
## 上下文
- 当前状态：!`git status`
- 当前 diff：!`git diff HEAD`

## 任务
基于上述改动创建一个 message 恰当的 commit。
```

Claude 看到的是已经把 `git status`、`git diff HEAD` 真实输出展开后的文本，等于命令一启动就自带了"现场快照"。

### 2. 文件引用——`@`前缀

用 `@` 前缀可直接把文件内容纳入提示词：

```markdown
---
description: 审查配置文件
---
审查以下配置文件存在的问题：
- 包配置：@package.json
- TS 配置：@tsconfig.json
- 环境配置：@.env

检查安全问题、过期依赖和错误配置。
```

### 3. 工具白名单的"意图声明"

`allowed-tools` 不只是权限便利，更是**意图声明**。一个 `/lint` 命令只列出 `Bash(npm run lint:*)` 就不可能意外编辑文件；一个 `/deploy-check` 只列出 `Bash(gh:*)` 和 `Read` 就不可能推送代码。**表面越窄，命令越安全，用户越不用纠结是否放行每一次调用**。

---

## 六、命令、Skill、Subagent、Hook——四个工具的边界

这是新手最容易混淆的地方。斜杠命令坐落在一个很窄的带状区域里，它擅长一件事，对另几件事很糟。用一张决策表收束：

```text
flowchart TD
    Start[我有一段重复工作] --> Q1{是否每次都是同一段提示词<br/>最多1-2个变量槽?}
    Q1 -->|是| Q2{是否希望用户主动输入才触发?}
    Q1 -->|否,需附带模板/脚本/领域知识| Skill[用 Skill<br/>.claude/skills/SKILL.md]
    Q2 -->|是,希望主动触发| Cmd[✅ 用斜杠命令<br/>.claude/commands/x.md]
    Q2 -->|否,希望Claude自主判断触发| Skill
    Start --> Q3{是否需要独立上下文窗口<br/>和专职人格?}
    Q3 -->|是| Sub[用 Subagent<br/>有独立allowlist、返回报告]
    Start --> Q4{是否应在harness事件上自动触发<br/>如保存文件/会话停止?}
    Q4 -->|是,机械动作无需模型| Hook[用 Hook<br/>settings.json]
    Q4 -->{需要模型在环} --> Q2

    style Cmd fill:#d4edda,stroke:#28a745,stroke-width:2px
```

一句话启发式：

- 如果你会**在聊天里打出同一段话**来启动工作 → 斜杠命令；
- 如果你更希望 Claude **不打招呼就自己知道去做** → Skill 或 Hook；
- 如果这项工作**需要它自己的脑子** → Subagent。

---

## 七、命令存活下来的四个模式

真实团队里被长期保留下来的命令，通常有四个共同点。

### 模式一：一个命令，一个产出

最强的命令在结尾有一个**单一、可观测的产物**。`/pr` 开 PR，`/release-notes` 写发版说明，`/triage` 给 issue 打标签。试图当"万金油"的命令（`/dev`——你想干啥就干啥）会漂移：没人记得它干嘛用，提示词膨胀到想覆盖每种情况，最终沦为比直接打字更差的版本。

### 模式二：提示词即规约

把命令正文当作"成功长什么样"的契约，写清楚：

- 先读什么；
- 做什么；
- 跳过什么；
- 输出什么格式；
- 结果放哪（commit、PR 评论、终端、文件路径）。

"审查这个 PR"会产生十种不同的审查；"只针对安全问题审查此 PR，忽略风格与命名，在发现可利用漏洞处发布行内评论"会产生接近一致的审查结果。

### 模式三：绑定工具，而不只是绑定文字

`/lint` 只允许 `Bash(npm run lint:*)`，`/deploy-check` 只允许 `Bash(gh:*)` 和 `Read`。窄表面 = 安全 = 少打扰。

### 模式四：该钉模型时就钉

机械工作（格式化 commit message、从 git log 生成 changelog、给 issue 分类）在 Haiku 上跑得很好，成本只是 Sonnet/Opus 的零头：

```yaml
---
model: claude-haiku-4-5-20251001
---
```

设计类工作（提议架构、解开棘手 bug、重写 API）则应钉到 Opus，避免用户意外在降级模型上调用而拿到更差的答案。

---

## 八、实战案例：从零搭建一套发版命令族

下面是完整的、可运行的示例。目标：在一个项目里建三个相互配合的命令，覆盖"发版"全流程。最终目录结构如下：

```
.claude/
└── commands/
    └── release/
        ├── notes.md      → /release:notes
        ├── cut.md        → /release:cut
        └── verify.md     → /release:verify
```

### 步骤 1：创建命令文件

依次写入三个文件。

**`.claude/commands/release/notes.md`** —— 生成发版说明：

```markdown
---
description: 为自上次 tag 以来的提交生成发版说明
allowed-tools: Bash(git:*)
model: claude-haiku-4-5-20251001
---
生成覆盖自最近 tag 以来提交的发版说明。
1. 用 `git describe --tags --abbrev=0` 找到最新 tag。
2. 读取该 tag 与 HEAD 之间的 commit log。
3. 把提交归入 ## 新功能、## 修复、## 内部 三组。
4. 每行写成面向用户的句子，而非原始 commit subject。
5. 跳过 merge 提交和依赖版本号 bump。
6. 输出到 stdout。不要写文件。
```

**`.claude/commands/release/cut.md`** —— 切发版 tag：

```markdown
---
description: 基于发版说明切一个新版本 tag
argument-hint: <semver 比如 1.4.0>
allowed-tools: Bash(git:*)
---
## 当前状态
- 最新 tag：!`git describe --tags --abbrev=0`
- 未发布提交数：!`git rev-list --count $(git describe --tags --abbrev=0)..HEAD`

## 任务
为版本 $ARGUMENTS 切 tag。
1. 先运行 /release:notes 确认要发布的内容。
2. 确认工作区干净（`git status` 无未提交改动）。
3. 用 `git tag -a v$ARGUMENTS -m "<发版说明首行>"` 打带注解的 tag。
4. 提示用户用 `git push origin v$ARGUMENTS` 推送。
不要直接 push，把推送决定权留给用户。
```

**`.claude/commands/release/verify.md`** —— 校验发版产物：

```markdown
---
description: 校验发版前置条件是否就绪
allowed-tools: Bash(git:*), Bash(npm:*), Read
---
## 上下文
- package.json 版本：!`node -p "require('./package.json').version"`
- 最新 tag：!`git describe --tags --abbrev=0`
- main 分支状态：!`git status -sb`

## 校验清单
检查发版前置条件：
1. package.json 版本号是否与即将切的 tag 一致；
2. 工作区是否干净；
3. 是否所有改动都已推送到远端 main；
4. 依赖是否有已知高危漏洞（`npm audit`）。
按 ✅/⚠️/❌ 三级逐条汇报，最后给一个 GO / NO-GO 结论。
```

### 步骤 2：验证命令注册

在项目根目录启动 Claude Code 会话，输入 `/`，选择器里应出现 `release:notes`、`release:cut`、`release:verify` 三个条目，描述与你写的 `description` 一致。

### 步骤 3：跑通最小闭环

```text
/release:notes
```

Claude 会调用 Haiku，读 git log，在终端打印三段式发版说明。确认无误后：

```text
/release:cut 1.4.0
```

Claude 先确认工作区干净，再打带注解的 tag，最后**只提示你推送、不替你 push**——这是把"不可逆的外向动作"决定权留给用户的关键设计。

```text
/release:verify
```

Claude 汇总版本号、tag、工作区、依赖审计，给出 GO/NO-GO。

### 预期产出

| 命令 | 模型 | 产出物 | 副作用 |
|------|------|--------|--------|
| `/release:notes` | Haiku | stdout 三段式说明 | 无（只读 git） |
| `/release:cut 1.4.0` | 继承会话模型 | 本地 annotated tag | 不推送，留给用户 |
| `/release:verify` | 继承会话模型 | GO/NO-GO 报告 | 无（只读 + npm audit） |

### 常见问题与解决

- **`/release:notes` 报 "no tags found"**：仓库还没有任何 tag。先手动 `git tag v0.1.0` 打一个基线 tag。
- **命令没在选择器出现**：确认文件确实在 `.claude/commands/release/` 下、扩展名是 `.md`、没有把 `release` 目录建成了文件。用 `find .claude/commands -type f` 复核。
- **每次运行都弹权限**：`allowed-tools` 写成了 `Bash(git)` 而非 `Bash(git:*)`。前者只匹配裸 `git`，后者匹配所有 git 子命令。
- **Haiku 命令输出质量不稳定**：把 `model` 临时换成 `claude-sonnet-4-6` 排查是模型能力问题还是提示词问题。若是提示词问题，补充"先读什么/输出什么格式"。

---

## 九、命名空间与发现

组织命令的成熟做法：相关命令收进同一个子目录。常见命名空间：`release:`、`pr:`、`db:`、`docs:`、`triage:`、`test:`。一旦超过十个命令就该开始分组，让选择器保持清爽、相关命令排在一起。

会话内输入 `/` 即可看到全部可用命令（内置、项目、个人）及其描述——这是你的健全性检查。删除一个命令只需删掉对应 `.md` 文件，或把它移到 `~/.claude/commands/` 之外。

---

## 十、从命令到插件：分发路径

当你想把一组命令分享到仓库之外——比如一套跨十几个服务使用的发版命令——下一步是把它们**打包成插件**。插件是一个包含命令（以及 Skill、Agent、Hook）的目录，任何 Claude Code 用户都能用一条命令安装，更新自动流转。

不必从插件起步。自然的演进路径是：

1. **个人命令**（`~/.claude/commands/`）——一个用户，所有项目；
2. **项目命令**（`.claude/commands/`）——本仓库所有用户；
3. **插件**——所有项目，分发给团队之外。

每一步都等量增加摩擦与耐久度。**别在命令还没"挣到"之前就提前升级它**。

---

## 延伸阅读

- **Claude Code 官方文档 · Slash Commands in the SDK**：命令在 Agent SDK 中的使用、frontmatter 全字段、参数占位符、命名空间规则。
- **Claude Code 官方文档 · Skills**：从 `.claude/commands/` 迁移到 `.claude/skills/<name>/SKILL.md` 的官方推荐路径，支持自主触发。
- **Claude Directory 博客 · Slash Commands (2026) Complete Guide**：命令存活模式、命令 vs Skill vs Subagent vs Hook 的实战取舍。
- **DeepWiki · Custom Commands and Slash Commands**：源码视角的命令系统解析。
- 尝试用 `claude /release:cut 1.4.0` 在 `-p` 无头模式下调用自定义命令，把它接入 CI——这是从"手动一键"走向"自动流水线"的下一站。

---

## 训练营适用性评估

- **适合类型**：开发者生产力训练营、团队工程规范训练营、AI 辅助开发入门营。不适合纯算法/纯后端业务训练营（无重复提示词场景）。
- **难度档位**：入门偏中。无需编程，但要理解 Git、YAML、提示词工程三要素。
- **建议教学时长**：讲授 45 分钟 + 动手 60 分钟。动手环节要求学员当场交付至少一个 `/review` 命令并通过"换一个仓库仍能用"的迁移测试。
- **考核标准**：能独立写出带 `argument-hint`、`allowed-tools`、`model` 三字段的命令；能用子目录命名空间组织 3 个以上命令；能口述命令与 Skill/Hook 的边界。

## 参考来源

1. [Slash Commands in the SDK — Claude Code Docs](https://code.claude.com/docs/en/agent-sdk/slash-commands) — 官方权威文档，覆盖 frontmatter 字段、`$ARGUMENTS`、`!`bash、`@`文件引用、命名空间的完整规范。
2. [Claude Code Slash Commands: A Complete Guide to Custom Commands (2026) — Claude Directory](https://www.claudedirectory.org/blog/claude-code-slash-commands-guide) — 实战导向指南，含命令存活四模式、命令/Skill/Subagent/Hook 决策启发式、可复用的 `/pr` `/triage` `/release:notes` 范例。
3. [Extend Claude with skills — Claude Code Docs](https://docs.claude.com/en/docs/claude-code/slash-commands) — 官方对 `.claude/commands/` 经典格式与 `.claude/skills/` 新格式的迁移说明。
4. [Custom Commands and Slash Commands — DeepWiki](https://deepwiki.com/FlorianBruniaux/claude-code-ultimate-guide/5.3-custom-commands-and-slash-commands) — 源码视角解析命令系统的加载与解析机制。
5. [Create Custom Slash Commands in Claude Code (2026) — MCSA Guru](https://mcsaguru.com/create-custom-slash-commands-claude-code) — 从零搭建自定义命令的分步图文教程，含常见踩坑。

---

> 本文由微信公众号「**51学通信**」原创制作，站长「**爱卫生**」（微信：gprshome201101）。聚焦 5G/6G 核心网协议与 AI 辅助开发的交叉实战，每日一篇可落地的硬核技术拆解。

> [!tip] 51学通信知识星球
> **星主：爱卫生**（微信：gprshome201101）——公众号「51学通信」创办者，19 年通信行业运维与讲师经验，著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书（各大电商平台有售）。
> **星球定位**：深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域，主打运维岗位与信令分析。
> **当前规模**：5200 篇主题 / 990 个回答，198 元/年。
> **加入福利**：加入星球后请加爱卫生微信，拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题，另有群内分享。
> **AI 加持**：51学通信知识星球已作为 skill 接入 WorkBuddy，使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例，做总结、找文档和 PPT 等场景全覆盖。

![51学通信知识星球海报-扫码加入](https://wiki.500nian.com/images/zhixingqiu_qrcode.png)
