使用 OpenCode 一段时间后,很多开发者会发现,有些提示词几乎每天都要敲上好几遍。比如"跑一下测试用例并给出覆盖率报告"或者"帮我审查最近几次提交的代码"。每次都要重新输入,既啰嗦又容易打错字。
OpenCode 的设计者显然也遇到过这个问题。于是就有了今天要介绍的功能------自定义命令(Custom Commands)。简单说,就是把那些常用的长段提示词存起来,以后用简短的命令名就能一键调用。

自定义命令是什么
在 OpenCode 的交互界面(TUI)里,本来就自带一些内置命令,比如 /init、/undo、/redo、/share、/help。自定义命令相当于让用户自己往这个列表里加新成员。
举个例子,可以创建一个 /test 命令。当用户在 TUI 里敲下 /test 并回车,OpenCode 就会自动把预先写好的那段关于"运行测试并关注失败用例"的提示词发送给大模型。省去了每次手动输入的麻烦。
两种创建方式
OpenCode 提供了两种方式来定义自定义命令:一种是通过项目配置文件 opencode.jsonc,另一种是通过创建 Markdown 文件。两者效果一样,看个人习惯选择。
方式一:在配置文件中定义
打开项目根目录下的 opencode.jsonc(没有就新建一个),添加 command 字段。下面是一个测试命令的示例:
json
{
"$schema": "https://opencode.ai/config.json",
"command": {
"test": {
"template": "运行完整的测试套件并显示覆盖率报告,指出任何失败的测试,并给出修复建议。",
"description": "运行测试并显示覆盖率",
"agent": "build",
"model": "anthropic/claude-3-5-sonnet-20241022"
}
}
}
这里 test 就是命令的名字。template 是真正发给大模型的提示词,description 会在 TUI 里显示帮助信息,agent 和 model 则是可选的高级配置。
方式二:用 Markdown 文件定义
另一种方法更直观------创建 .opencode/commands/ 目录,然后在里面放 Markdown 文件。文件名就是命令名,比如 test.md。
这个文件的内容分为两部分:文件头部用 --- 包裹的 YAML 格式元信息(frontmatter),以及下面正文部分的提示词模板。
markdown
---
description: 运行测试并显示覆盖率
agent: build
model: anthropic/claude-3-5-sonnet-20241022
---
运行完整的测试套件并显示覆盖率报告,指出任何失败的测试,并给出修复建议。
这两个位置------项目里的 .opencode/commands/ 和用户全局目录 ~/.config/opencode/commands/------都是 OpenCode 会去扫描的地方。全局目录里的命令在所有项目中都可用,项目目录里的则只对当前项目生效。
让命令更灵活:参数、Shell 输出和文件引用
如果自定义命令只能写死一段话,那它的用处就有限了。OpenCode 支持三种方式让命令变得动态可配置。
参数传递
在提示词模板里放上 $ARGUMENTS 这个占位符,用户执行命令时后面跟着的内容就会自动替换进去。
比如创建一个 component.md:
markdown
---
description: 创建一个新组件
---
创建一个名为 $ARGUMENTS 的 React 组件,支持 TypeScript,包含合适的类型定义和基本结构。
用户在执行 /component Button 时,$ARGUMENTS 就会被替换成 Button。
还可以用 $1、$2、$3 这种位置参数来分别获取每个参数。例如一个 create-file.md:
markdown
---
description: 创建包含指定内容的文件
---
在 $2 目录下创建名为 $1 的文件,内容如下:
$3
执行 /create-file config.json src "{ \"key\": \"value\" }",那么 $1 就是 config.json,$2 是 src,$3 是 { "key": "value" }。
注入 Shell 命令的输出
有时候需要在提示词里附带一些实时信息,比如当前的 Git 日志、测试结果、系统时间等。用 !命令 的写法就能把命令执行结果直接嵌入进来。
看看这个 analyze-coverage.md 的例子:
markdown
---
description: 分析测试覆盖率
---
以下是当前的测试结果:
!`npm test`
根据这些结果,建议如何提高覆盖率。
还有审查最近代码改动的命令:
markdown
---
description: 审查最近的代码变更
---
最近的 Git 提交记录:
!`git log --oneline -10`
请审查这些变更,提出任何改进建议。
这些 Shell 命令会在项目根目录下执行,它们的标准输出会成为提示词的一部分。
引用文件内容
用 @文件名 的语法,可以把文件的内容直接包含到提示词中。这在审查代码或分析配置文件时特别有用。
例如 review-component.md:
markdown
---
description: 审查组件代码
---
请审查 @src/components/Button.tsx 这个组件,检查性能问题并提出改进建议。
OpenCode 会自动读取文件内容并拼接到提示词里,用户不需要手动复制粘贴。
命令的配置选项详解
自定义命令的元信息里有几个可选字段,每个字段都有它的用途。
template(模板)
这是唯一必填的字段。它就是实际发送给大模型的提示词。可以是简单的几句话,也可以是很长的详细指令。
description(描述)
一段简短的说明文字,当用户在 TUI 里输入 / 时,会自动显示在命令旁边,帮助用户记住每条命令是干什么的。
agent(代理)
默认情况下,自定义命令会由当前会话里正在使用的代理来执行。如果想让某个命令固定由特定的代理(比如专门负责构建任务的 build 代理)来处理,就可以指定这个字段。如果指定的代理是一个子代理,命令会默认触发子代理调用。
subtask(子任务)
这是一个布尔值(true/false)。如果设为 true,命令会强制以子代理的方式来执行。这样做的目的是避免主对话的上下文被大量无关内容撑爆。即使代理配置里写的是 mode: primary,设了 subtask: true 也会把它当成子代理来调用。
model(模型)
有时候某个命令需要特别强的推理能力,或者反过来只需要一个轻量级模型来快速回答,就可以用这个字段覆盖当前的默认模型。例如指定 anthropic/claude-3-5-sonnet-20241022。
内置命令与覆盖规则
OpenCode 本身自带几个内置命令:/init、/undo、/redo、/share、/help。关于这些命令的更多细节,可以查阅官方文档。
有一点值得注意:如果用户自定义了一个同名的命令,比如写了一个 /help,那么它会把内置的 /help 覆盖掉。这个设计给了用户完全的控制权------当然,覆盖之前最好先想清楚是不是真的需要。
小结
自定义命令看起来只是一个小功能,但它能实实在在地提升日常使用 OpenCode 的效率。把那些反复敲的提示词变成几个字母的命令,把动态参数、Shell 输出和文件引用组合起来,几乎可以应对各种自动化需求。无论是代码审查、测试运行、项目初始化还是文档生成,花几分钟写一个命令文件,以后每次使用都能省下十几秒------积少成多,体验的提升是实实在在的。