custom commands 已并入 Skills:什么时候该迁到 `.claude/skills/`,迁了之后能多做什么
前三篇讲了 slash command 的完整用法:从 Markdown 文件,到 !命令 注入,再到 subagent 和 MCP 编排。这些内容都没过时——但官方在背后做了一次合并:custom commands 已经并入 Skills。
你的 .claude/commands/review.md 仍然能跑,/review 仍然可用,什么都不用改。但如果打算让命令长出更多能力(多文件、fork 执行、按路径自动激活),新路径是 .claude/skills/review/SKILL.md。这篇讲清楚两件事:怎么迁,以及值不值得迁。
官方的兼容性承诺很明确:.claude/commands/deploy.md 和 .claude/skills/deploy/SKILL.md 都会注册成 /deploy,功能完全一样。同名冲突时 skills 优先。
最小迁移步骤:
cd .claude/commands
mkdir -p ../skills/review
mv review.md ../skills/review/SKILL.md
文件内容一行都不用改。YAML frontmatter、!`命令`、@file、$ARGUMENTS——全部兼容。
但光做这一步,读者会问:那迁它干什么?答案在 skill 目录可以装多个文件,而 command 只能一个。
SKILL.md 是入口,同目录可以放任意附属文件。想象一下这样的目录:
.claude/skills/review/
├── SKILL.md # 入口,简短的指令 + 引用
├── checklist.md # 长长的代码审查清单
├── examples/
│ └── good-diff.md # 正例示范
└── scripts/
└── lint.sh # SKILL.md 可以调用的脚本
在 SKILL.md 里用相对路径引用:
审查当前 diff,遵循 [checklist.md](checklist.md) 中的标准。
参考 [examples/good-diff.md](examples/good-diff.md) 理解期望的输出格式。
这些附属文件不会自动进 context——Claude 按需读取。官方建议 SKILL.md 控制在 500 行以内,其余放到附属文件里。
disable-model-invocation:哪些 skill 只能你手动触发默认情况下,Claude 看到合适时机会自主调用任何 skill。这对 /deploy、/commit、/send-email 这种有副作用的命令很危险——你不想让它"看代码顺眼就去部署"。
---
name: deploy
description: 部署到生产环境
disable-model-invocation: true
allowed-tools: Bash(kamal deploy:*), Bash(git push:*)
---
加这一行后,/deploy 只能你手动输入触发,Claude 在对话中不会自作主张调用。
反过来 user-invocable: false 则是"只允许 Claude 自己调用,但不出现在 / 菜单里"——适合背景知识型 skill(比如 legacy-system-context,相关场景下 Claude 自动加载,但你手动触发没有意义)。
context: fork:让 skill 在子代理里跑这是最大的升级。上一篇讲到 command 可以用 allowed-tools: Task 让模型去起子代理——但你要在 prompt 里手动描述"起个 Explore 子代理做...."。
SKILL 直接一行 frontmatter 搞定:
---
name: deep-research
description: 深入调研某个符号
context: fork
agent: Explore
---
调研 $ARGUMENTS 的所有用法:
- 所有调用点
- 业务场景
- 替代实现
返回 ≤300 字总结。
触发 /deep-research SomeClass 时:整个 SKILL.md 变成一个独立子代理的 prompt,用 Explore agent type 执行,跑完只返回结论。主对话的 context 完全干净。
这相当于把"起子代理"这件事从 prompt 里的描述文字变成了 skill 的声明属性。
paths:按文件类型自动激活---
name: rails-conventions
description: Rails 项目的编码规范
paths: ["app/**/*.rb", "config/**/*.rb"]
---
遵循本项目的 Rails 规范:
- 使用 service object 而不是 fat controller
- ActiveRecord scope 必须命名化
...
当你正在编辑 app/models/user.rb 时,这个 skill 会被自动加入 context;编辑 package.json 时不会。比 CLAUDE.md 的全局背景更精准——相当于"按路径分层的 CLAUDE.md"。
/plan 升级为 skill上一篇最后那个 /plan 例子,原来是单文件 command:
.claude/commands/plan.md
升级成 skill:
.claude/skills/plan/
├── SKILL.md
├── research-prompt.md # 子代理 1 的指令
└── risk-prompt.md # 子代理 2 的指令
SKILL.md:
---
name: plan
description: 基于 Linear ticket 产出实施方案
disable-model-invocation: true
allowed-tools: mcp__linear__*, Task, Read, Grep, Bash(git log:*)
---
## 上下文
@.claude/context/architecture.md
## 状态
!`git log --oneline -10`
## 任务
拉取 Linear ticket $ARGUMENTS 的描述和评论。
用 Task 起两个子代理并行调研:
1. 代码调研:prompt 见 [research-prompt.md](research-prompt.md)
2. 风险评估:prompt 见 [risk-prompt.md](risk-prompt.md)
汇总两个结果后输出实施步骤 + 风险清单 + 提交粒度建议。
两个子代理的 prompt 放在单独文件,维护时改一处不用动 SKILL.md。Skill 本身 30 行内清爽,附属文件可以各自几百行详细。
如果不想自己调度子代理,可以更激进——把整个 skill 扔进 fork,让 Explore agent 一口气执行:
---
name: plan
context: fork
agent: Explore
allowed-tools: mcp__linear__*
---
触发 /plan ENG-4213 → 独立 context 里的 Explore agent 接过全部 SKILL.md 内容当作任务执行 → 只返回最终方案。主对话完全不脏。
不是所有 command 都值得升级。留在 .claude/commands/ 更合适的情况:
简单的 /commit、/pr-desc 这类就是一个 frontmatter + 几行 prompt——放 .claude/commands/ 反而更直观。官方明说两种形式并存、都不会被废弃。
现在 .claude/ 里最干净的组织:
.claude/
├── commands/ # 轻量:单文件 + 简单 prompt
│ ├── commit.md
│ └── pr-desc.md
├── skills/ # 重型:多文件 / fork / 权限控制
│ ├── plan/
│ │ ├── SKILL.md
│ │ ├── research-prompt.md
│ │ └── risk-prompt.md
│ ├── deploy/
│ │ └── SKILL.md # disable-model-invocation
│ └── rails-conventions/
│ └── SKILL.md # paths glob 自动激活
└── context/
└── coding-standards.md
别一股脑全迁。迁移的触发条件是"这个 command 已经开始膨胀"——正文超过 200 行、需要拆文档、想让子代理执行。到那一步再改路径,几分钟的事。
| 想要的能力 | commands/ |
skills/ |
|---|---|---|
| 单文件提示词快捷方式 | ✅ | ✅ |
!`命令` / @file / $ARGUMENTS |
✅ | ✅ |
allowed-tools 权限控制 |
✅ | ✅ |
| 附属文件(reference、scripts) | ❌ | ✅ |
disable-model-invocation 防误触发 |
❌ | ✅ |
context: fork + agent: 隔离执行 |
❌ | ✅ |
paths: glob 按路径自动激活 |
❌ | ✅ |
前三项 commands 和 skills 完全等价;后四项是 skills 独有。需要哪个就用哪个,不需要就别折腾。
官方路径正在朝 skills 倾斜,但 commands/ 的兼容性承诺很明确——这不是"立刻全迁或被淘汰"的变更,而是"新能力给你但不强迫"的扩展。搞清楚差异,按需迁移,别追求形式上的整齐。