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' 的 Command(loadSkillsDir.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)、frontmatterarguments声明命名参数(substituteArguments,loadSkillsDir.ts:349);!`cmd`bash 预执行注入(executeShellCommandsInPrompt,loadSkillsDir.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:name,loadPluginCommands.ts:80)。
策略锁与渐进加载。 [一手源码] 两个容易被忽略的行为:
skillsLocked(isRestrictedToPluginOnly('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 条目可为插件命令附加富元数据(
CommandMetadataSchema,utils/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 在最前)。枚举里还藏着产品方向信号:Personality、Pets、Realtime、MultiAgents(serialize 为 "subagents")、Memories,以及 DebugConfig/TestApproval 等调试命令。所有命令的 description 也硬编码在同一文件(:82-92),即 Codex 的命令系统是纯产品面,无任何用户扩展点。
差异矩阵
| 维度 | Claude Code | Codex 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 实践)
- 资产模型合并:Yoda
harness-spec.ts目前commandDirs: ['.claude/commands'](claude)/[](codex)。建议在数据模型上把 command 归并为skill (legacy-format)子类型而非独立资产类——与 CC 内部模型一致,避免用户在两个面板看到同一个/deploy。 - 迁移助手:检测到
.claude/commands/*.md时提供一键迁移为skills/<name>/SKILL.md(CC 官方推荐方向,且迁移后才能跨 runtime 被 Codex 的.agents/skills路线复用)。 - 校验差异点:CC 命令正文里的
!`cmd`注入是安全敏感面,harness 应静态提取并展示这些预执行命令(等价于 hooks 的 review 需求);Codex 侧无此风险面。 - 调用代理:harness 的"运行"按钮对 CC 生成
/name args,对 Codex 生成$name <args>——并提示 Codex 不支持位置参数模板。 - 命名冲突检测:CC 同名时 skill 压过 command(用户常因此困惑"改了 commands/x.md 没生效");harness 扫描时把
.claude/commands/x.md与.claude/skills/x/SKILL.md的同名对标成 warning,并标明实际生效者。 - 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.rs、tui/src/bottom_pane/custom_prompt_view.rs(仅 review 输入框) - 文档:
claude-code-docs/docs/skills.md(§Custom commands merged)、docs/cli-reference.md;codex/docs/slash_commands.md(指向 https://developers.openai.com/codex/cli/slash-commands ) - Yoda:
yoda/src/renderer/features/projects/components/harness-view/harness-spec.ts