OpenCode Skills

在 OpenCode 中,代理技能(Skills)是一种用于封装可复用行为的机制,通过 SKILL.md 文件定义,使 LLM 能够按需加载、按需执行特定能力。

相比普通提示词,技能更接近模块化能力单元,可以在多个项目或团队中复用。

Skills 是 OpenCode 的能力插件系统,它将 AI 行为从单次提示升级为可复用能力模块,使开发流程更加标准化、可组合,并适用于复杂工程体系。

更多 Skills 可以参考:

核心机制

Skills 通过内置的 skill 工具进行管理,工作流程如下:

  1. 扫描本地和全局技能目录
  2. 在上下文中暴露可用技能列表
  3. 代理根据任务自动选择技能
  4. 按需加载 SKILL.md 内容

这种机制避免了将所有规则一次性加载,提高了性能和上下文利用率。


文件放置位置

每个技能需要一个独立的文件夹,文件夹内放置 SKILL.md 文件(注意:文件名必须全部大写)。OpenCode 会自动搜索以下六个位置:

类型 路径 适用范围
项目配置 .opencode/skills/<name>/SKILL.md 仅当前项目
全局配置 ~/.config/opencode/skills/<name>/SKILL.md 所有项目
项目 Claude 兼容 .claude/skills/<name>/SKILL.md 仅当前项目
全局 Claude 兼容 ~/.claude/skills/<name>/SKILL.md 所有项目
项目代理兼容 .agents/skills/<name>/SKILL.md 仅当前项目
全局代理兼容 ~/.agents/skills/<name>/SKILL.md 所有项目

典型的项目目录结构如下:

your-repo/
├── .opencode/
│   └── skills/
│       ├── git-release/
│       │   └── SKILL.md      ← 发版流程技能
│       ├── code-review/
│       │   └── SKILL.md      ← 代码审查技能
│       └── api-doc/
│           └── SKILL.md      ← API 文档编写技能
├── src/
└── package.json

发现机制

OpenCode 的技能发现分为两个层级:

项目本地技能:OpenCode 从当前工作目录开始,向上逐层遍历目录树,直到到达 Git 工作树的根目录为止。在此过程中,它会收集沿途每一层目录下 .opencode/skills/*/SKILL.md.claude/skills/*/SKILL.md.agents/skills/*/SKILL.md 中所有匹配的技能文件。

全局技能:同时从 ~/.config/opencode/skills/*/SKILL.md~/.claude/skills/*/SKILL.md~/.agents/skills/*/SKILL.md 中加载所有已定义的全局技能。

两个层级的技能会合并后一起提供给代理使用。如果项目本地技能与全局技能同名,项目本地技能优先


编写 SKILL.md

1、Frontmatter 字段

每个 SKILL.md 文件必须以 YAML frontmatter 开头(即 --- 包裹的部分)。OpenCode 只识别以下字段,未知字段会被自动忽略:

字段 是否必填 类型 说明
name 必填 字符串 技能的唯一标识名,必须与所在文件夹名称一致,且符合命名规则
description 必填 字符串 技能的描述,代理依据此内容决定是否调用,1–1024 个字符
license 可选 字符串 技能内容的许可证类型,如 MITApache-2.0
compatibility 可选 字符串 标注与哪个工具兼容,如 opencodeclaude
metadata 可选 对象(字符串到字符串的映射) 自定义的附加元数据,如目标受众、工作流类型等,键值均为字符串

2、命名规则

name 字段的值必须同时满足以下所有条件,否则技能将无法被加载:

  • 长度为 1–64 个字符
  • 只能包含小写字母数字,单词之间可以用单个连字符(-)分隔
  • 不能以 - 开头或结尾
  • 不能包含连续的 --
  • 必须与包含该 SKILL.md文件夹名称完全一致

等效的正则表达式:

^[a-z0-9]+(-[a-z0-9]+)*$

合法命名示例:git-releaseapi-doccode-reviewdeploy2prod

非法命名示例:Git-Release(含大写)、-release(以 - 开头)、git--release(连续 --

3、编写描述

description 字段的内容直接影响代理是否能正确选择和调用该技能。建议描述要具体明确,说明该技能做什么、在什么场景下使用,避免过于笼统:

  • ❌ 过于笼统:帮助完成发版任务
  • ✅ 具体明确:从合并的 PR 中起草发版说明、提出版本号建议,并生成可直接使用的 gh release create 命令

4、完整示例

在项目中创建 .opencode/skills/git-release/SKILL.md,内容如下:

实例

---
name: git-release
description: Create consistent releases and changelogs
license: MIT
compatibility: opencode
metadata:
  audience: maintainers    # 自定义元数据:目标受众
  workflow: github         # 自定义元数据:工作流类型
---
 
## What I do
- Draft release notes from merged PRs
- Propose a version bump
- Provide a copy-pasteable `gh release create` command
 
## When to use me
Use this when you are preparing a tagged release.
Ask clarifying questions if the target versioning scheme is unclear.

Frontmatter 中的 name 值必须与文件夹名称一致。本例中文件夹名为 git-release,因此 name 也必须写 git-release,否则技能无法被识别。


代理如何发现和加载技能

OpenCode 启动后,会将当前所有可用技能以 XML 格式注入到 skill 工具的描述中。代理可以通过查看工具描述来了解有哪些技能可用:

<available_skills>
  <skill>
    <name>git-release</name>
    <description>Create consistent releases and changelogs</description>
  </skill>
  <skill>
    <name>code-review</name>
    <description>Perform structured code reviews with consistent criteria</description>
  </skill>
</available_skills>

当代理判断某个技能与当前任务相关时,会主动调用 skill 工具来加载该技能的完整 SKILL.md 内容:

skill({ name: "git-release" })

加载完成后,技能中定义的指令和上下文信息会进入代理的工作记忆,从而影响后续的行为和输出。技能本身不会自动执行任何操作,只是为代理提供额外的上下文和行为规范。


配置技能权限

opencode.json 中,使用 permission.skill 字段控制代理可以访问哪些技能,支持精确名称和 Glob 通配符两种匹配方式:

实例

{
  "$schema": "https://opencode.ai/config.json",
  "permission": {
    "skill": {
      "*": "allow",               // 兜底规则:默认允许加载所有技能
      "pr-review": "allow",       // 精确匹配:允许加载 pr-review 技能
      "internal-*": "deny",       // Glob 匹配:拒绝加载所有 internal- 开头的技能(对代理完全隐藏)
      "experimental-*": "ask"     // Glob 匹配:加载 experimental- 开头的技能前需用户确认
    }
  }
}

三种权限动作对技能的具体效果如下:

权限值 效果
"allow" 技能立即加载,代理无需任何确认
"deny" 技能对代理完全隐藏,<available_skills> 列表中不会出现该技能,代理无法感知其存在
"ask" 代理尝试加载该技能时弹出确认提示,由用户决定是否允许

按代理覆盖权限

不同代理可能需要访问不同的技能集,可以为每个代理单独配置权限,覆盖全局默认值。

1、在自定义代理的 Frontmatter 中配置

实例

# 文件路径:~/.config/opencode/agents/my-agent.md
---
permission
:
  skill
:
    "documents-*"
: "allow"    # 该代理可以加载所有 documents- 开头的技能
                               # 其他技能遵循全局权限配置
---
 
You are a documentation assistant.

2、在 opencode.json 中为内置代理配置

实例

{
  "$schema": "https://opencode.ai/config.json",
  "agent": {
    "plan": {                          // 内置代理名称
      "permission": {
        "skill": {
          "internal-*": "allow"        // plan 代理可以加载 internal- 开头的技能,
                                       // 即使全局配置中对其设置了 deny
        }
      }
    }
  }
}

禁用技能工具

对于完全不需要使用技能的代理,可以直接禁用 skill 工具。禁用后,<available_skills> 列表将从代理的上下文中完全移除,既节省 Token 消耗,又避免代理尝试加载任何技能。

1、在自定义代理的 Frontmatter 中禁用

实例

---
tools
:
  skill
: false    # 对该代理完全禁用技能功能,available_skills 列表不会出现在上下文中
---
 
You are a quick answer assistant. Just answer questions directly.

2、在 opencode.json 中为内置代理禁用

实例

{
  "$schema": "https://opencode.ai/config.json",
  "agent": {
    "plan": {
      "tools": {
        "skill": false    // plan 代理不使用任何技能
      }
    }
  }
}

排查技能加载问题

如果某个技能没有出现在可用列表中,请按以下顺序逐项检查:

  1. 确认文件名大小写

    SKILL.md 的文件名必须全部大写,写成 skill.mdSkill.md 都不会被识别。

  2. 检查 Frontmatter 完整性

    确保 SKILL.md 开头有正确的 YAML frontmatter,且包含 namedescription 两个必填字段。缺少任意一个,技能都不会被加载。

  3. 确认技能名称唯一且格式正确

    如果不同路径下存在同名技能,可能产生冲突。同时检查 name 字段是否符合命名规则(仅小写字母和数字,以连字符分隔),且与文件夹名称完全一致。

  4. 检查权限配置

    opencode.jsonpermission.skill 中,权限为 "deny" 的技能会对代理完全隐藏,不会出现在 <available_skills> 列表中。检查是否有通配符规则(如 "*": "deny")意外匹配到了该技能。