玩转 OpenCode 自定义命令:让重复工作一键完成
使用 OpenCode 一段时间后很多开发者会发现有些提示词几乎每天都要敲上好几遍。比如“跑一下测试用例并给出覆盖率报告”或者“帮我审查最近几次提交的代码”。每次都要重新输入既啰嗦又容易打错字。OpenCode 的设计者显然也遇到过这个问题。于是就有了今天要介绍的功能——自定义命令Custom Commands。简单说就是把那些常用的长段提示词存起来以后用简短的命令名就能一键调用。自定义命令是什么在 OpenCode 的交互界面TUI里本来就自带一些内置命令比如/init、/undo、/redo、/share、/help。自定义命令相当于让用户自己往这个列表里加新成员。举个例子可以创建一个/test命令。当用户在 TUI 里敲下/test并回车OpenCode 就会自动把预先写好的那段关于“运行测试并关注失败用例”的提示词发送给大模型。省去了每次手动输入的麻烦。两种创建方式OpenCode 提供了两种方式来定义自定义命令一种是通过项目配置文件opencode.jsonc另一种是通过创建 Markdown 文件。两者效果一样看个人习惯选择。方式一在配置文件中定义打开项目根目录下的opencode.jsonc没有就新建一个添加command字段。下面是一个测试命令的示例{$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以及下面正文部分的提示词模板。--- description: 运行测试并显示覆盖率 agent: build model: anthropic/claude-3-5-sonnet-20241022 --- 运行完整的测试套件并显示覆盖率报告指出任何失败的测试并给出修复建议。这两个位置——项目里的.opencode/commands/和用户全局目录~/.config/opencode/commands/——都是 OpenCode 会去扫描的地方。全局目录里的命令在所有项目中都可用项目目录里的则只对当前项目生效。让命令更灵活参数、Shell 输出和文件引用如果自定义命令只能写死一段话那它的用处就有限了。OpenCode 支持三种方式让命令变得动态可配置。参数传递在提示词模板里放上$ARGUMENTS这个占位符用户执行命令时后面跟着的内容就会自动替换进去。比如创建一个component.md--- description: 创建一个新组件 --- 创建一个名为 $ARGUMENTS 的 React 组件支持 TypeScript包含合适的类型定义和基本结构。用户在执行/component Button时$ARGUMENTS就会被替换成Button。还可以用$1、$2、$3这种位置参数来分别获取每个参数。例如一个create-file.md--- description: 创建包含指定内容的文件 --- 在 $2 目录下创建名为 $1 的文件内容如下 $3执行/create-file config.json src { \key\: \value\ }那么$1就是config.json$2是src$3是{ key: value }。注入 Shell 命令的输出有时候需要在提示词里附带一些实时信息比如当前的 Git 日志、测试结果、系统时间等。用!命令的写法就能把命令执行结果直接嵌入进来。看看这个analyze-coverage.md的例子--- description: 分析测试覆盖率 --- 以下是当前的测试结果 !npm test 根据这些结果建议如何提高覆盖率。还有审查最近代码改动的命令--- description: 审查最近的代码变更 --- 最近的 Git 提交记录 !git log --oneline -10 请审查这些变更提出任何改进建议。这些 Shell 命令会在项目根目录下执行它们的标准输出会成为提示词的一部分。引用文件内容用文件名的语法可以把文件的内容直接包含到提示词中。这在审查代码或分析配置文件时特别有用。例如review-component.md--- 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 输出和文件引用组合起来几乎可以应对各种自动化需求。无论是代码审查、测试运行、项目初始化还是文档生成花几分钟写一个命令文件以后每次使用都能省下十几秒——积少成多体验的提升是实实在在的。