Yoda
参考Agent 设计指南扩展

Slash / 自定义命令

CC 已把自定义命令并入 skills(.claude/commands 与 SKILL.md 等价,同一 Command 类型);Codex 的 slash 命令是纯内建枚举,用户自定义入口完全让位给 skills 的 $mention——"自定义命令"作为独立概念正在消亡

Slash / 自定义命令

结论

"自定义 slash 命令"作为独立扩展点正在消亡,两家殊途同归:CC 在源码层面把 commands 和 skills 合并成同一个 Command 类型——.claude/commands/deploy.md.claude/skills/deploy/SKILL.md 都产出 /deploy,文档明言 "Custom commands have been merged into skills";Codex 更彻底,本快照源码中已不存在用户自定义 prompts 目录的加载逻辑(grep "prompts" 目录常量为零命中),slash 命令是写死的 Rust 枚举(约 60 个内建命令),用户自定义的可调用单元只有 skills($name mention)。harness 不应再为"命令"单独建一类资产,把 .claude/commands 当 skills 的 legacy 入口处理即可。

研究问题

  • CC 自定义命令(md + frontmatter + $ARGUMENTS)的现状与 skills 的关系?
  • Codex 是否还有 ~/.codex/prompts 自定义命令?
  • 内建命令面的差异?

各 Agent 设计与实现

Claude Code

内建命令:注册表模式,100+ 模块。 [一手源码] src_2026-03-31/commands.ts 顶部 import 了 add-dir/compact/config/cost/doctor/… 100 余个命令模块,导出 getCommands()。每个命令同时支持 /commit 与 CLI claude commit 两种调用。

自定义命令 = skills 的 legacy 形态。 [一手源码] skills/loadSkillsDir.ts:626-634 注释原文:"Loads all skills from both /skills/ and legacy /commands/ directories";/commands/ 支持单 .md 文件和 SKILL.md 目录两种格式,/skills/ 只支持目录格式。两者最终都经 createSkillCommand 产出 type:'prompt'CommandloadSkillsDir.ts:316)——类型系统层面没有"命令"这个独立概念。[一手文档] docs/skills.md:16:"Custom commands have been merged into skills... Your existing .claude/commands/ files keep working.";同名冲突时 skill 优先于 command(skills.md:110)。

一个用满扩展位的命令文件长这样(字段语义见 skills 章,二者同集):

---
description: Commit staged changes with a conventional message
argument-hint: "<scope> <message>"
arguments: [scope, message]
allowed-tools: [Bash]
model: inherit
context: fork          # 在 fork 出的子上下文里执行
disable-model-invocation: true   # 只许用户手动 /commit-msg
---
Current diff:
!`git diff --cached --stat`

Write a conventional commit for scope $scope: $message

参数与动态内容。 [一手文档+一手源码] 正文支持:

  • $ARGUMENTS / $ARGUMENTS[N](0 基索引,docs/skills.md:256)、frontmatter arguments 声明命名参数(substituteArgumentsloadSkillsDir.ts:349);
  • !`cmd` bash 预执行注入(executeShellCommandsInPromptloadSkillsDir.ts:375);
  • ${CLAUDE_SKILL_DIR}${CLAUDE_SESSION_ID} 变量(loadSkillsDir.ts:356-369)。 frontmatter 与 skills 完全同集(allowed-tools/model/agent/context: fork/disable-model-invocation 等 17 字段,见 skills 章)——description 缺省回退标签都区分 'Skill' | 'Custom command'loadSkillsDir.ts:189)。

作用域:user ~/.claude/commands、project .claude/commands(随 skills 同一加载管线、同一 realpath 去重)、plugin commands/(命名空间 plugin:dir:nameloadPluginCommands.ts:80)。

策略锁与渐进加载。 [一手源码] 两个容易被忽略的行为:

  • skillsLockedisRestrictedToPluginOnly('skills'))生效时,legacy commands 目录一并被封锁——注释原文 "these ARE skills, regardless of the directory they load from"(loadSkillsDir.ts:709-713)。企业策略想锁 skills 时不会被 commands 目录绕过;
  • 命令/skill 的 token 成本按 frontmatter(name+description+whenToUse)估算,正文只在调用时载入(loadSkillsDir.ts:97-104)——命令列表再长也只付出索引成本。
  • marketplace 条目可为插件命令附加富元数据(CommandMetadataSchemautils/plugins/schemas.ts:385-395),这是命令在分发侧仅有的"描述增强"通道。

Codex CLI

内建命令:封闭枚举。 [一手源码] codex-rs/tui/src/slash_command.rs:12-78 pub enum SlashCommand——model/permissions/skills/hooks/review/new/resume/fork/plan/agent/mcp/apps/plugins/personality 等约 60 个变体,注释明言枚举顺序即弹窗展示顺序。没有任何从文件系统装载用户命令进该弹窗的路径。

自定义 prompts 目录已消失。 [一手源码·缺席证明] 在 commit 2026-06-06 全仓 grep "prompts" 目录字面量(排除 test)零命中;custom_prompts 仅存在于 TUI 的 CustomPromptView——那是 /review 等命令收集一次性自由文本的输入框组件(tui/src/bottom_pane/custom_prompt_view.rs:31 注释:"Minimal multi-line text input view to collect custom review instructions"),与历史上的 ~/.codex/prompts 自定义命令无关。结论:该功能在当前快照中已被 skills 取代。[推断] 官方 codex/docs/slash_commands.md 只剩一行指向网页文档,也旁证本地不再承载该机制。

用户自定义入口 = skills。 用户可调用单元通过 $skill-name mention 进入对话(见 skills 章),/skills 命令只是管理列表。参数化方面 Codex 没有 $ARGUMENTS 等价物——mention 后面跟的自然语言就是参数 [一手源码·缺席](core-skills 中无参数替换逻辑)。

内建命令的产品取向。 [一手源码] slash_command.rs:13-14 注释:"DO NOT ALPHA-SORT! Enum order is presentation order in the popup"——命令顺序是手工运营的高频优先排序(Model/Ide/Permissions 在最前)。枚举里还藏着产品方向信号:PersonalityPetsRealtimeMultiAgents(serialize 为 "subagents")、Memories,以及 DebugConfig/TestApproval 等调试命令。所有命令的 description 也硬编码在同一文件(:82-92),即 Codex 的命令系统是纯产品面,无任何用户扩展点。

差异矩阵

维度Claude CodeCodex CLI
内建命令TS 注册表,100+ 模块,slash 与 CLI 双入口Rust 封闭枚举 ~60 个,仅 TUI
自定义命令文件.claude/commands/*.md(= legacy skill)无(~/.codex/prompts 已不存在于源码)
用户自定义调用语法/name args$name mention
参数替换$ARGUMENTS$ARGUMENTS[N]、命名参数无模板替换,自然语言传参
bash 预执行注入!`cmd`
命令 vs skill 关系同一 Command 类型,skill 同名优先只有 skill,无命令概念
策略封锁skillsLocked 连带封 commands 目录[skills.config] 逐条禁用
命令命名规则文件名/目录名即命令名,插件加 : 命名空间枚举 serialize 名(可多别名,如 stop/clean)
弹窗排序注册表顺序 + 使用频率 [推断]枚举声明顺序(手工运营)
插件分发命令可(plugin:ns:cmd不可(插件只带 skills/mcp/hooks/apps)

最小复现

# CC:命令与 skill 等价性
mkdir -p .claude/commands && echo 'Reply with the word PONG only.' > .claude/commands/ping.md
claude   # 输入 /ping → 输出 PONG;再建 .claude/skills/ping/SKILL.md → /ping 改走 skill(同名 skill 优先,docs/skills.md:110)

# Codex:确认无自定义命令目录
mkdir -p ~/.codex/prompts && echo 'PONG' > ~/.codex/prompts/ping.md
codex    # 输入 / → 弹窗中不会出现 ping(slash_command.rs 枚举封闭;未实测,源码缺席证明)

Harness 接入建议(Yoda 实践)

  1. 资产模型合并:Yoda harness-spec.ts 目前 commandDirs: ['.claude/commands'](claude)/ [](codex)。建议在数据模型上把 command 归并为 skill (legacy-format) 子类型而非独立资产类——与 CC 内部模型一致,避免用户在两个面板看到同一个 /deploy
  2. 迁移助手:检测到 .claude/commands/*.md 时提供一键迁移为 skills/<name>/SKILL.md(CC 官方推荐方向,且迁移后才能跨 runtime 被 Codex 的 .agents/skills 路线复用)。
  3. 校验差异点:CC 命令正文里的 !`cmd` 注入是安全敏感面,harness 应静态提取并展示这些预执行命令(等价于 hooks 的 review 需求);Codex 侧无此风险面。
  4. 调用代理:harness 的"运行"按钮对 CC 生成 /name args,对 Codex 生成 $name <args>——并提示 Codex 不支持位置参数模板。
  5. 命名冲突检测:CC 同名时 skill 压过 command(用户常因此困惑"改了 commands/x.md 没生效");harness 扫描时把 .claude/commands/x.md.claude/skills/x/SKILL.md 的同名对标成 warning,并标明实际生效者。
  6. token 预算:命令列表的常驻成本按 frontmatter 口径估算(与 CC 内部一致,loadSkillsDir.ts:97-104),别把正文长度计入"上下文占用"面板。

失效条件

  • Codex 恢复用户自定义 prompts/commands 加载(出现新的文件系统→slash 弹窗路径时,"封闭枚举"结论过期)
  • CC 移除 .claude/commands 兼容(docs/skills.md "keep working" 表述消失)
  • CC 把 $ARGUMENTS 语法演进为新模板系统
  • Codex skills 增加参数化模板能力

参考资料

  • CC 源码:src_2026-03-31/commands.ts(内建注册表)、skills/loadSkillsDir.ts(commands/skills 统一加载)、utils/plugins/loadPluginCommands.ts
  • Codex 源码:codex/codex-rs/tui/src/slash_command.rstui/src/bottom_pane/custom_prompt_view.rs(仅 review 输入框)
  • 文档:claude-code-docs/docs/skills.md(§Custom commands merged)、docs/cli-reference.mdcodex/docs/slash_commands.md(指向 https://developers.openai.com/codex/cli/slash-commands
  • Yoda:yoda/src/renderer/features/projects/components/harness-view/harness-spec.ts

On this page