免费

从 Slash Commands 到 Skills:什么时候迁、怎么迁

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 多出来的四件东西

1. 支持文件:把长文档拆出去

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 行以内,其余放到附属文件里。

2. 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 自动加载,但你手动触发没有意义)。

3. 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 的声明属性。

4. 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/ 更合适的情况:

  • 单 Markdown 就够:没有需要拆出去的 checklist、examples、scripts
  • 不需要 fork 执行:任务和主对话深度耦合,需要看到完整历史
  • 不需要按路径自动激活:就是用户手动触发
  • 不需要访问控制:既可以让 Claude 自动调用也不会出事

简单的 /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/ 的兼容性承诺很明确——这不是"立刻全迁或被淘汰"的变更,而是"新能力给你但不强迫"的扩展。搞清楚差异,按需迁移,别追求形式上的整齐。