我大概是那种"懒到极致反而逼出效率"的人。前一阵子接手了好几个历史遗留仓库的维护任务,每次都要跟AI助手从头解释一遍"先看目录结构、再查依赖、然后排查明显问题"——解释到第三遍的时候实在受不了了。后来我把这套流程在Opencode里固化成了一个技能,之后每次只需要一句话,它就会按照我沉淀的标准作业流程把活干完。这篇分享就围绕一件事:如何使用Opencode高效创建属于自己的技能。
先说明一下背景。Opencode是一个跑在终端里的AI编程代理工具,它不像普通聊天界面那样只能一问一答,而是可以真正参与项目的分析、修改和执行。很多人在用它的时候停留在"当作加强版聊天框"的阶段,每次干活都要重新写一大段提示词,换个场景又得重写一遍。技能(Skill)就是用来终结这种重复劳动的:把一段经过验证的、结构化的指令封装起来,让AI在特定场景下自动按照你的标准执行。这篇文章适合所有刚接触Opencode、以及已经用了一段时间但总觉得"差点意思"的人,我会从概念讲到落地,再讲到我踩过的坑,保证你能直接照着抄。
1. 先搞清楚:Opencode的"技能"到底是什么东西
1.1 技能不是插件,也不是命令别名
很多人第一次听说"技能"这个概念时,会下意识拿它跟插件、扩展程序做类比,其实这是两种完全不同的东西。插件是往工具里加功能,而技能是给工具一份"干活的说明书"。打个比方:插件相当于给你买了一台新的厨房电器,技能则是教你怎么把一道菜做到店里的标准——不涉及新增设备,只涉及做事的方式。
在Opencode里,一个技能本质上是一个包含结构化指令的文件集合。它告诉AI模型:你接下来要面对什么类型的任务、应该按什么顺序思考、使用哪些工具、最终以什么格式输出。AI本身的能力来自模型,技能不赋予它新能力,而是约束它把已有能力用在对的方向上。
这一点非常关键。模型的能力是通用的,但你做事的标准是私有的。两个不同性格的AI加上同一套模型,给它们同一个任务,产出的质量可能天差地别。差别就来自于你喂给它的上下文和约束。技能的价值恰恰在于,把那些"你通过反复调教才得到的有效指令"固定下来,下次不用重新摸索。
1.2 为什么我们需要把"做事方式"封装起来
我见过不少同事用AI助手干活的方式是这样的:今天想让它检查代码,于是写一段详细的提示词,运气不错,结果还行;明天又遇到类似任务,重新写一遍,但昨晚忘了关键约束,结果产出质量明显下滑。这种用法的问题在于经验没有被积累,每次都在用全新的对话去挑战同一个不确定性。
技能解决的就是这个问题。当你把一套流程封装成技能之后,会获得几个实实在在的好处:
- 一致性:团队里不同人触发同一个技能,得到的是同一套流程约束下的结果,而不是十个人写出十种风格的提示词然后得到十种质量参差不齐的输出。
- 可复用:一次性投入的编写时间,换来回无数次稳定的执行。对于我这种经常处理同类型任务的人来说,投资回报率高得惊人。
- 可演进:技能是文件,可以被版本管理。今天发现流程里缺了一步,改一下文件就完成了对所有后续执行的升级,不用通知任何人。
- 可分享:把一个调试好的技能文件发给同事,对方放到自己的配置目录里就能用。这比口头传授经验可靠得多。
说白了,技能就是把你脑子里的"标准作业程序"从隐性知识变成显性文件。项目里新人上手最快的路径,往往不是看文档,而是直接用你封装好的技能跑几遍真实任务。
2. 环境准备:把Opencode装好,并弄懂它的配置目录
2.1 安装与首次运行
Opencode的安装并不复杂,它通常以命令行工具的形式分发。我当时的做法是直接用系统的包管理器全局安装,一个命令搞定,这里就不写具体命令了,因为不同操作系统的安装方式略有差异。装完之后在终端里输入工具名,看到它进入交互式的命令行界面,就说明安装成功。
首次运行时程序会引导你完成基础配置,核心是两件事:选择模型服务商和填入密钥。Opencode本身不内置模型,它只是一个接入了各家大模型服务商的代理层,所以你需要有自己的模型接口密钥。现在主流的大模型服务商基本都提供兼容接口,你把对应的密钥配置进去即可。
这里有一个新手非常容易忽略的点:不要以为装完就直接能用。命令行工具通常不会给你一个漂亮的图形化引导窗口,初始化结束后你大概率会面临一个看起来有点简陋的提示符。别慌,先在任意一个项目目录里让它跑一个最简单的任务,比如"列一下当前目录的结构",确认基本链路通了,再继续做技能相关的配置。
2.2 配置目录与技能存放位置
Opencode的配置遵循命令行工具的主流惯例:全局配置放在用户主目录下的隐藏配置目录里。以我常用的系统为例,就是类似~/.config/opencode/这样的路径。这个目录里通常有一个主配置文件,记录你选了哪个模型服务商、密钥怎么读、默认参数是什么。具体文件名和格式可能因为版本迭代有出入,运行工具内置的帮助命令就能查到。
技能目录则有两种常见的存放位置:
- 全局技能目录:放在上述配置目录下的
skills/子目录里,所有项目都能用。 - 项目级技能目录:放在某个项目根目录下的隐藏目录里,只有在该项目下运行Opencode时才生效。
两种方式各有用途。全局技能放那些与项目无关的通用流程,比如"代码评审""提交信息规范化";项目级技能放跟当前项目技术栈强绑定的流程,比如"为本项目的微服务模块生成新接口模板"。
我第一次配技能目录时就吃了不认真看文档的亏,把技能放错了地方,结果在另一个项目里怎么触发都没反应。后来学乖了:任何时候怀疑技能没生效,第一件事就是确认它到底被放在了全局还是项目级目录。
2.3 模型选择对技能效果的影响
很多人忽略了一个事实:技能是写给模型看的"剧本",但不同的模型对剧本的理解能力是不一样的。同样的技能文件,在指令遵循能力强的模型手里可能执行得分毫不差,换一个模型可能就丢三落四。
这不代表你要为了技能去盲目追求某一个特定模型。我的经验是:在编写技能时,默认假设模型是个"听话但有点笨"的新人。指令要拆得足够细,步骤不要过度依赖模型的推理能力去"脑补"中间环节,关键节点最好明确写出"如果遇到什么情况就做什么动作"。这样即使换了模型,技能依然大概率能跑出可接受的结果。
另外,多提一句API的稳定性问题。如果你像我一样经常连续跑多个任务,建议在配置里把超时和重试参数调一下,避免偶然的网络波动让一个本来很稳的技能突然失败,然后你花半小时排查,最后发现只是请求超时。
3. 创建第一个技能:把"仓库体检"做成标准流程
3.1 技能文件的基本结构
理论讲了半天,该动手了。Opencode里一个技能通常就是一个文件夹,文件夹里至少包含一个核心的说明文件,我习惯叫它SKILL.md,因为Markdown格式既适合人读也适合模型读。
一个标准的技能文件夹长这样:
~/.config/opencode/skills/ └── repo-inspect/ ├── SKILL.md └── checklist.mdSKILL.md是技能的主文件,包含两部分内容:开头是一段元信息,用键值对的形式描述技能的姓名、作用、版本和触发条件;正文则是给模型看的实际操作指令。如果技能特别复杂,你还可以在同一个文件夹里放辅助文件,比如上面例子里的checklist.md,用来存放一份详细的检查清单,主文件里通过指令让模型去读取它。
为什么要把辅助内容拆成独立文件?因为模型对上下文的注意力是有限的。如果你把一份五千字的检查清单全部塞进技能主文件里,执行到后面模型很容易忘记前面的细节。拆成独立文件之后,主文件只负责"引导流程",详细清单按需读取,效果会好很多。
3.2 一个可以直接抄的示例
下面这个示例是我实际在用的一套"仓库体检"技能,用来快速了解一个新接手仓库的整体状况。你可以直接复制,把细节改成自己需要的。
--- name: repo-inspect description: 对代码仓库进行结构体检,输出结构化报告 version: 1.0.0 trigger: 仓库体检 --- # 仓库体检 ## 目标 在尽量短的时间内了解一个仓库的整体状态,发现明显问题,并输出一份结构清晰的体检报告。 ## 执行步骤 第一步:了解仓库基本盘 1. 读取仓库根目录下的项目描述文件,确认项目名称和用途。 2. 遍历根目录,识别主要子目录的职责。 3. 识别当前使用的技术栈和语言。 第二步:检查依赖状态 1. 找到依赖清单文件。 2. 统计依赖总数,标记其中明显过期或存在已知安全隐患的依赖。 3. 检查是否有重复或冗余的依赖声明。 第三步:检查代码健康度 1. 查看最近的提交记录,了解近期活跃度和改动规模。 2. 识别明显的调试残留,例如写死在代码里或日志输出里的调试信息。 3. 找出体积异常庞大的文件,重点关注这些文件是否存在拆分必要。 第四步:输出报告 严格按照以下格式输出: - 仓库概览:名称、用途、技术栈 - 依赖健康度:总数、问题数、风险依赖清单 - 代码健康度:活跃度、调试残留、超大文件清单 - 改进建议:按优先级从高到低排列,每条建议不超过两句话你可以看到,这个技能文件的核心逻辑特别朴素:给目标、给步骤、给输出格式。没有华丽的辞藻,全是干巴巴的指令。之所以这样写,是因为模型在处理长指令时,对"明确动词+明确对象"的遵循程度远高于"建议你考虑看看"这种模糊表达。
3.3 运行与验证
技能文件保存好之后,怎么确认它真的生效?在项目目录下启动Opencode,然后用自然语言触发它。比如我会直接输入一句:"对当前仓库做一次仓库体检。"
这里要注意触发方式。有些版本支持通过配置里的trigger字段做精确匹配,有些版本则更依赖模型根据description自动判断何时该调用技能。我的建议是:不要把触发条件写得过于苛刻,比如要求用户必须输入某个特定短语才触发,否则日常使用中你很快会因为"忘了确切短语"而放弃使用技能。更稳妥的做法是把描述写清楚,让模型在用户意图匹配时自动使用这个技能。
第一次执行的时候,我强烈建议你全程盯着它的输出,观察每个步骤是否符合预期。通常第一版技能跑出来会有一两个地方不对,这很正常。我的经验是:不要急着改技能文件,先把这次执行暴露出的问题记下来,等完整跑完一遍,再根据问题统一修改。这样能避免你陷入"改一下、跑一次、再改一下"的无限循环。
4. 让技能真正"聪明"起来:变量、工具与流程编排
4.1 用变量让技能适配不同场景
你很快会发现,有些技能的内容是高度相似的,只是每次针对的具体对象不同。比如"检查某个目录下的代码规范性"和"检查另一个目录下的代码规范性"——两者的流程几乎一样,唯一区别是目标路径。如果你为每个目录写一个技能,那是蠢办法。
聪明的做法是用变量。Opencode的技能文件通常支持在指令中引用调用时传入的参数,比如用类似{{target_dir}}这样的占位符来代表用户指定的路径。在技能文件里写上"第一步:先进入 {{target_dir}} 目录,读取该目录的结构",然后在调用时告诉它"检查 src/modules 目录的规范性",模型就会自动把占位符替换成你传入的路径。
这看起来只是一个小改进,但实际体验差别巨大。没有变量的时候,一个技能只能解决一个固定场景,你得为 "检查模块A""检查模块B" 各准备一套技能;有了变量之后,一个技能覆盖所有同类场景,这才是"一次封装,到处复用"的真正含义。
4.2 在技能里约定工具的使用
Opencode区别于普通聊天界面的重要一点,就是它能调用真实的工具:读写文件、执行终端命令、搜索项目内容等。技能文件里应该明确约定每个步骤使用哪个工具、允许做哪些操作、禁止做哪些操作。
比如在上面的仓库体检技能里,我会在说明文件中补充一句:所有检查操作只读,不得修改任何文件;执行命令时优先使用只读命令,如列出目录、显示文件内容等,避免无意中触发构建或修改操作。
这个约束极其重要。模型没有你那么强的"分寸感",你让它"检查依赖",它可能顺手就给你执行了依赖更新命令,然后留下一堆你并不想要的变更。在技能里用白名单和黑名单来约束工具行为,相当于给AI上了一道保险。
还有一个细节:工具调用失败时怎么处理。我在技能里通常会让模型先重试一次,如果仍然失败就停止并报告,而不是自行发挥找替代方案。因为很多时候"自行发挥"就是灾难的开始。
4.3 多步骤编排与技能联动
单个技能处理单次任务,这是最基础的使用方式。更进一步的做法是把技能做成流水线:一个技能的输出,成为下一个技能的输入。
举个例子。我有一套"新功能开发"的流水线:第一步用一个技能分析需求并拆解任务清单;第二步用一个技能生成代码框架;第三步用一个技能生成配套测试。这三个技能相互独立,但通过执行顺序形成了编排。你只需要在第一个技能的最后一步写上"将生成的任务清单作为后续功能的输入",整个流水线就能顺畅跑下来。
这种编排方式比把三个技能合并成一个巨型技能要可靠得多。原因在于每个技能保持单一职责,指令简洁,模型执行时不容易混乱;同时你可以在任意环节插入一个中间步骤,灵活度大大提高。
但我要提醒一句:不要过度设计。流水线虽然听起来高级,但每个环节都有失败的可能,环节越多,整体稳定性越差。我的经验是,先让单个技能稳定运行一段时间,确认它真的靠谱之后,再去考虑串联。宁可要一个能跑通的简单流程,也不要一个大概率断裂的复杂编排。
5. 实战沉淀:我日常开发中最常用的一批技能
5.1 技能清单与效果对比
用得多了之后,我沉淀了一批频率极高、收益明显的技能。下表是我的常用清单,列出来给大家做个参考:
| 技能名称 | 核心用途 | 触发场景 | 收益点 |
|---|---|---|---|
| repo-inspect | 仓库结构体检 | 新接手仓库、定期巡检 | 十几分钟摸清仓库全貌 |
| commit-msg | 规范化生成提交信息 | 每次提交代码前 | 提交历史整齐可读 |
| code-review | 代码评审 | 合入主干前 | 提前拦截明显问题 |
| test-gen | 为模块生成测试用例 | 新功能完成时 | 补齐测试覆盖 |
| dep-audit | 依赖安全检查 | 每月例行 | 发现过时和高危依赖 |
| refactor-plan | 重构方案设计 | 遇到代码坏味道时 | 输出可执行的重构步骤 |
这里我想特别强调一下"收益点"这一列。很多人写技能时只盯着"能自动化什么",却忽略了"省下的时间是否值得"。我的判断标准很简单:如果一个任务你手工做需要十分钟以上、并且未来还会重复遇到,就值得为它写技能。像"仓库体检"这种每接手一个新项目都要做的事,投入半小时写技能,长期来看稳赚不赔。
5.2 两个典型技能的完整内容参考
除了上面展示的仓库体检技能,我再拿"commit-msg"这个技能说说,因为它特别能体现"技能如何约束输出质量"。
写提交信息的痛点在于:模型很容易生成那种"修复了一些bug""更新了代码"的废话提交信息。我调教了很多次之后发现,关键在于给足结构约束和反例。技能文件里我明确列出了提交信息的格式模板、允许使用的动词列表,还专门写了一个"反面示例"段落,把那些看起来没毛病但实际上没有任何信息量的写法列出来,让模型知道哪些是不允许的。
这里有个特别有用的技巧:在技能里写反例,比只写正例有效得多。模型对"不该做什么"的指令遵循度往往高于"该做什么"的模糊要求。把常见的烂输出直接示众,它就知道你要的质量底限在哪里了。
另一个值得参考的是"code-review"技能。我在这份技能里除了常规的检查步骤,还专门规定了报告的呈现方式:必须按严重程度给问题分级,每一个问题都要带具体的文件路径和行号,并且给出至少一条修复建议。理由是:评审意见如果只停留在"这里写得不好"这种层面,基本等于没说;把问题定位精确到行、把建议给到可执行,才是真正有价值的评审。
6. 技能维护与避坑:别让技能变成第二套"烂代码"
6.1 技能失效的常见原因
技能写出来不是一劳永逸的。我踩过的坑不少,总结一下最常见的失效原因,你遇到类似情况可以直接对照排查:
- 指令过于抽象。技能文件里全是"优化代码质量""提高可维护性"这类形容词,模型根本不知道该执行什么。解决方案是把动作动词化:"提取重复代码到公共函数""将超过两百行的函数拆分"。
- 上下文过载。一份技能文件塞了几千字,模型执行到中后段已经把前面的关键约束忘了。解决方案是拆分文件,把详细清单放到辅助文件里按需读取。
- 步骤顺序不合理。技能要求模型"先评估影响范围再动手修改",但模型在实际执行中经常跳步。解决方案是在关键节点明确加上"没有完成第X步之前,禁止进入下一步骤"。
- 未定义边界条件。什么情况下应该停止、什么情况下应该向用户确认、什么情况下允许自己决定,这些如果不写清楚,模型就会替你做了让事后头疼的选择。
- 模型本身的差异。之前也提过,不同模型对指令的理解和遵循能力不同。某厂商的模型跑得好好的技能,换个厂商的模型可能输出质量断崖式下跌。如果你经常切换模型,技能文件里要尽量避免依赖单一模型特有的能力。
6.2 排查思路
当某个技能突然不好使了,我的排查链路是固定的,分享给你参考:
第一,先确认是技能问题还是环境问题。重新跑一次最简单的基础任务,如果基础任务正常,说明Opencode本体和模型链路没问题,问题出在技能上。
第二,把技能内容简化到极致。注释掉大部分指令,只保留核心步骤,看能不能跑通。如果能跑通,说明问题出在被注释掉的某段指令里,逐步恢复即可定位。这跟写代码时二分排查问题的思路完全一致。
第三,检查模型的完整输出过程,而不只是看最终结果。很多时候技能"看起来没生效",其实是模型在某一步误解了指令,然后沿着错误方向执行了很久。你需要在输出过程中捕捉到那个最初的偏差点,才能精准修复技能文案。
6.3 技能版本管理与演进
最后说一个很多人都会忽略的点:技能文件也是代码,也要版本管理。我会把你的整个技能目录放进一个独立的代码仓库里,每次修改技能都走提交记录。这样做的好处是,一旦新改的技能表现不佳,你可以快速回退到上一个可用版本。
我还习惯给每个技能文件加上版本号,放在开头的元信息里。版本号不光是给自己看的,也是给模型看的:当它在执行中发现技能文件描述的流程与代码库实际情况不符时,版本号能够帮助它判断是不是该提醒用户更新技能。
技能本身也需要定期"再训练"。我会在每个月例行检查时,专门花一点时间看看哪些技能已经很久没被触发了。长期不用的技能,要么是场景已经不存在了,要么是使用门槛太高导致大家不愿意用。如果是后者,我会想办法降低调用成本,比如优化触发方式、简化不必要的步骤。如果技能已经不适应现状了,该删就删,不要让它躺在目录里给你造成假的"资产感"。
最后分享一个小技巧。我后来发现,在技能文件末尾放一段"自查清单"比在前面写更多详细步骤更管用。所谓自查清单,就是在流程最后让模型逐项检查自己有没有完成关键约束。比如在仓库体检技能的最后加一句:"输出报告前,逐项检查:是否覆盖了依赖检查?是否指出了具体文件路径?建议是否按优先级排序?"模型在执行完任务后对着清单过一遍,很多低级遗漏就会被拦下来。这个技巧几乎可以套用到任何技能上,谁用谁知道。