主权个人必看的 OpenCode 教程之第四课(2026版)
-
主权个人必看的 OpenCode 教程之第四课(2026版)
目录- 一、Plugin 系统深度解析
- 1.1 什么是 Plugin?为什么需要它?
- 1.2 架构原理与设计哲学
- 1.3 Context API 完全指南
- 1.4 事件系统详解
- 1.5 工具执行钩子详解
- 1.6 自定义工具开发
- 1.7 实战示例
- 第二章:Skills 工程化开发
- 2.1 什么是 Skills?
- 2.2 Skills 的工作机制
- 2.3 Skills 存放位置
- 2.4 SKILL.md 规范详解
- 2.5 Skills 权限配置
- 2.6 Prompt Engineering 最佳实践
- 2.7 常见问题排查
- 第三章:Oh My OpenCode 多智能体协作
- 3.1 什么是 Oh My OpenCode?
- 3.2 Sisyphus 编排器
- 3.3 专业 Agent 矩阵
- 3.4 后台任务与并行执行
- 📎 附录
- A. 常用命令速查
- B. 配置文件位置汇总
🎯 课程定位:本节课开始我们进入进阶课程,面向希望掌握 OpenCode 扩展开发的开发者,涵盖 Plugin 系统架构、Skills 工程化实践以及 Oh My OpenCode 多智能体协作的完整技术细节。
一、Plugin 系统深度解析
1.1 什么是 Plugin?为什么需要它?
在开始技术细节之前,让我们先理解 Plugin 的核心价值。OpenCode 是一个强大的 AI 编码助手,但每个团队和项目都有其独特的需求——安全策略、工作流程、工具链集成等。Plugin 系统正是为了解决这个问题而设计的:它让你能够在不修改 OpenCode 核心代码的情况下,扩展和定制其行为。
想象这些场景:
- 🔐 安全需求:你的公司禁止 AI 读取
.env文件 - 🔔 通知需求:任务完成时发送 Slack 或桌面通知
- 📊 审计需求:记录所有 AI 操作用于合规审查
- 🛠️ 工具集成:让 AI 能够查询你的内部数据库
所有这些都可以通过 Plugin 来实现,而无需等待官方支持。
1.2 架构原理与设计哲学
OpenCode 的 Plugin 系统采用 TypeScript-first 设计理念——插件不是 YAML 配置或 JSON 文件,而是真正的 TypeScript 模块。这意味着你可以获得:
特性 说明 完整的类型安全 通过 @opencode-ai/plugin包获得 IntelliSense 支持Shell API 访问 通过 Bun 的 $模板字符串执行系统命令Agent 生命周期钩子 多个事件分类让你可以介入 AI 工作流的关键阶段 🏗️ 插件加载流程
OpenCode 在启动时会按照特定顺序加载插件。理解这个顺序对于避免插件冲突非常重要:
┌─────────────────────────────────────────────────────────┐ │ 插件加载顺序 │ ├─────────────────────────────────────────────────────────┤ │ 1️⃣ 全局配置插件 (~/.config/opencode/opencode.json) │ │ ↓ │ │ 2️⃣ 项目配置插件 (./opencode.json) │ │ ↓ │ │ 3️⃣ 全局目录插件 (~/.config/opencode/plugins/) │ │ ↓ │ │ 4️⃣ 项目目录插件 (.opencode/plugins/) │ └─────────────────────────────────────────────────────────┘💡 提示:同名同版本的 NPM 包只会加载一次,但本地插件和 NPM 插件即使名称相似也会分别加载。
两种插件加载方式
1. 本地文件加载(适合开发和项目特定插件)
将
.ts或.js文件放置在以下目录:- 项目级:
.opencode/plugins/(注意是 plugins 而非 plugin) - 全局级:
~/.config/opencode/plugins/
2. NPM 包加载(适合共享和分发)
在
opencode.json中配置:{ "$schema": "https://opencode.ai/config.json", "plugin": ["oh-my-opencode", "@your-org/custom-plugin"] }NPM 插件会在启动时通过 Bun 自动安装,依赖缓存在
~/.cache/opencode/node_modules/。1.3 Context API 完全指南
⚠️ 初学者常见错误:Plugin 函数接收的是一个 Context 对象,而非独立参数。很多新手会直接调用
ctx.send(),但这是错误的用法。Context 结构详解
interface PluginContext { /** * OpenCode SDK 客户端 * 用于与 AI 核心交互 */ client: OpenCodeClient; /** * 项目信息 */ project: { /** 项目标识符 */ id: string; }; /** * Bun Shell API * 用于执行系统命令 */ $: BunShell; /** * 当前工作目录 */ directory: string; /** * Git worktree 路径 */ worktree: string; }✅ 正确用法 vs ❌ 错误用法
// ❌ 错误:将 context 当作 client 使用 export const MyPlugin = async (ctx) => { await ctx.send("Hello"); // TypeError: ctx.send is not a function } // ✅ 正确:解构 context 对象 export const MyPlugin = async ({ client, project, $, directory, worktree }) => { // 使用 client 进行 AI 交互 await client.app.log({ service: "my-plugin", level: "info", message: `Working in: ${directory}` }); }Client API 详解
client对象是你与 OpenCode 核心交互的主要接口:// 结构化日志(推荐替代 console.log) await client.app.log({ service: "my-plugin", // 插件名称 level: "info", // debug | info | warn | error message: "操作完成", extra: { key: "value" } // 可选的额外数据 });Shell API 使用技巧
$是 Bun 的 Shell API,支持模板字符串语法,让命令执行变得优雅:export const MyPlugin = async ({ $ }) => { // 基本命令执行 const result = await $`git status`.text(); // 静默执行(不输出到控制台) await $`npm install`.quiet(); // 获取退出码 const { exitCode } = await $`cargo test`; // 管道操作 const files = await $`find . -name "*.ts" | head -10`.lines(); }1.4 事件系统详解
OpenCode 提供了丰富的生命周期事件,让你可以在 AI 工作流的关键节点介入。以下是根据官方最新文档整理的完整事件列表:
📋 完整事件分类表
类别 事件名 触发时机 典型用途 Command command.executed命令执行后 命令审计、快捷键记录 File file.edited文件被编辑 自动格式化、备份 file.watcher.updated文件监听更新 热重载触发 Installation installation.updated安装更新 版本检查 LSP lsp.client.diagnosticsLSP 诊断信息 错误高亮、问题面板 lsp.updatedLSP 状态更新 语言服务监控 Message message.updated消息更新 内容过滤、翻译 message.removed消息删除 日志记录 message.part.updated消息片段更新 流式处理 message.part.removed消息片段删除 清理 Permission permission.replied权限请求响应 权限审计 permission.updated权限更新 缓存刷新 Server server.connected服务器连接 连接状态监控 Session session.created新会话创建 初始化状态 session.updated会话更新 同步状态 session.compacted会话压缩完成 统计、日志 session.deleted会话删除 清理资源 session.idle会话空闲 自动保存、通知 session.status状态变化 UI 更新 session.error会话错误 错误处理、重试 session.diff会话差异 变更追踪 Todo todo.updated待办更新 任务追踪 Tool tool.execute.before工具执行前 参数验证、安全检查 tool.execute.after工具执行后 结果处理、审计 TUI tui.prompt.append提示追加 自定义提示 tui.command.executeTUI命令执行 命令拦截 tui.toast.show显示提示 自定义通知 1.5 工具执行钩子详解
tool.execute.before和tool.execute.after是最常用的两个钩子,让我们深入了解它们的用法:tool.execute.before:执行前拦截
export const SecurityPlugin = async ({ client }) => { return { "tool.execute.before": async (input, output) => { // input 包含工具调用信息 console.log(`Tool: ${input.tool}`); // 通过 output.args 修改参数 if (input.tool === "bash") { // 将危险的 rm -rf 替换为更安全的 rm -i output.args.command = output.args.command.replace(/rm -rf/g, "rm -i"); } // 通过 throw 中止执行 if (input.tool === "read" && output.args.filePath.includes(".env")) { throw new Error("Security: Cannot read environment files"); } } } }tool.execute.after:执行后处理
export const FormatterPlugin = async ({ $ }) => { return { "tool.execute.after": async (input, output) => { // 自动格式化编辑后的文件 if (input.tool === "edit" || input.tool === "write") { const filePath = output.args.filePath; const ext = filePath.split('.').pop(); if (["ts", "tsx", "js", "jsx"].includes(ext)) { await $`prettier --write ${filePath}`.quiet(); } } } } }1.6 自定义工具开发
Plugin 最强大的能力之一是注册自定义工具,让 AI Agent 获得全新能力。
💡 重要理解:自定义工具让你可以将公司内部系统、数据库、API 等暴露给 AI,使其能够执行原本无法完成的操作。
工具定义基本结构
import { tool } from "@opencode-ai/plugin" export default tool({ // 工具描述(供 LLM 理解何时使用此工具) description: "Query the project database", // 参数定义(使用 Zod schema) args: { query: tool.schema.string().describe("SQL query to execute"), }, // 执行函数 async execute(args) { // 实现你的逻辑 return `Executed: ${args.query}`; } });文件名即工具名:将上述代码保存为
.opencode/tools/database.ts,就会创建一个名为database的工具。单文件多工具模式
你也可以在一个文件中导出多个工具:
// .opencode/tools/math.ts import { tool } from "@opencode-ai/plugin" export const add = tool({ description: "Add two numbers", args: { a: tool.schema.number().describe("First number"), b: tool.schema.number().describe("Second number"), }, async execute(args) { return args.a + args.b; } }); export const multiply = tool({ description: "Multiply two numbers", args: { a: tool.schema.number().describe("First number"), b: tool.schema.number().describe("Second number"), }, async execute(args) { return args.a * args.b; } });这会创建两个工具:
math_add和math_multiply(格式为文件名_导出名)。跨语言工具开发
工具定义必须用 TypeScript/JavaScript,但实际逻辑可以用任何语言实现:
// .opencode/tools/python-analyzer.ts import { tool } from "@opencode-ai/plugin" export default tool({ description: "Analyze code using Python script", args: { filePath: tool.schema.string().describe("File to analyze"), }, async execute(args) { // 调用 Python 脚本 const result = await Bun.$`python3 .opencode/scripts/analyze.py ${args.filePath}`.text(); return result.trim(); } });1.7 实战示例
示例一:会话完成通知(macOS)
// .opencode/plugins/notification.js export const NotificationPlugin = async ({ $ }) => { return { event: async ({ event }) => { if (event.type === "session.idle") { await $`osascript -e 'display notification "Session completed!" with title "OpenCode"'`; } } }; }💡 提示:如果你使用 OpenCode 桌面应用,它可以自动发送系统通知,无需额外插件。
示例二:敏感文件保护
// .opencode/plugins/env-protection.js export const EnvProtection = async () => { return { "tool.execute.before": async (input, output) => { if (input.tool === "read" && output.args.filePath.includes(".env")) { throw new Error("Do not read .env files"); } } }; }示例三:自定义压缩上下文
当会话过长需要压缩时,你可以注入自定义上下文:
// .opencode/plugins/compaction.ts import type { Plugin } from "@opencode-ai/plugin" export const CompactionPlugin: Plugin = async () => { return { "experimental.session.compacting": async (input, output) => { // 注入额外上下文到压缩提示 output.context.push(` ## 项目特定上下文 请在压缩时保留以下信息: - 当前任务状态 - 重要的设计决策 - 正在修改的文件列表 `); } }; }第二章:Skills 工程化开发
2.1 什么是 Skills?
Skills 是 OpenCode 的按需加载指令系统。与 Plugin 不同,Skills 不是代码,而是 Markdown 文档——它们定义了 AI 在特定场景下应该如何行动。
形象比喻:如果把 AI Agent 比作一个员工,那么 Skills 就像是工作手册或 SOP(标准操作程序)。当员工需要处理特定任务时,就会查阅相应的手册。
特性 Plugin Skills 本质 TypeScript 代码 Markdown 文档 加载时机 启动时全部加载 按需动态加载 作用 扩展系统能力 指导 AI 行为 典型用途 集成外部服务 定义工作流程 2.2 Skills 的工作机制
用户输入: "帮我做一次代码审查" │ ▼ ┌─────────────────┐ │ Agent 分析意图 │ └────────┬────────┘ │ ▼ ┌─────────────────┐ │ 调用 skill 工具 │ ← 查看可用的 Skills 列表 └────────┬────────┘ │ ▼ ┌─────────────────┐ │ 发现匹配 Skill │ ← 找到 "code-review" Skill │ "code-review" │ └────────┬────────┘ │ ▼ ┌─────────────────┐ │ 加载 SKILL.md │ ← 将内容注入到 System Prompt └────────┬────────┘ │ ▼ ┌─────────────────┐ │ 按照指导执行任务 │ ← AI 遵循 SKILL.md 中的指导 └─────────────────┘2.3 Skills 存放位置
OpenCode 会扫描以下位置的 Skills(按优先级排序):
优先级 位置 作用域 1 .opencode/skills/<name>/SKILL.md项目级 2 ~/.config/opencode/skills/<name>/SKILL.md全局(用户级) 3 .claude/skills/<name>/SKILL.md项目级(兼容 Claude Code) 4 ~/.claude/skills/<name>/SKILL.md全局(兼容 Claude Code) 💡 重要:对于项目本地路径,OpenCode 会从当前工作目录向上遍历到 git worktree 根目录,加载沿途发现的所有匹配 Skills。
2.4 SKILL.md 规范详解
Frontmatter 字段(YAML 格式)
每个 SKILL.md 必须以 YAML frontmatter 开头,包含以下字段:
字段 必填 说明 name✅ 技能标识符,1-64 字符,小写字母数字和连字符 description✅ 技能描述,1-1024 字符 license❌ 许可证信息 compatibility❌ 兼容性说明 metadata❌ 字符串到字符串的映射 name命名规则:- 必须是 1-64 个字符
- 只能包含小写字母、数字和单个连字符作为分隔符
- 不能以
-开头或结尾 - 不能包含连续的
-- - 必须与包含 SKILL.md 的目录名匹配
正则表达式:
^[a-z0-9]+(-[a-z0-9]+)*$完整示例
.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.2.5 Skills 权限配置
你可以通过配置控制哪些 Skills 可以被 Agent 访问:
{ "permission": { "skill": { "*": "allow", "pr-review": "allow", "internal-*": "deny", "experimental-*": "ask" } } }权限值 行为 allowSkill 可以立即加载 denySkill 对 Agent 隐藏,访问被拒绝 ask加载前需要用户确认 💡 模式支持通配符:
internal-*会匹配internal-docs、internal-tools等。按 Agent 配置权限
对于自定义 Agent(在 Agent frontmatter 中):
--- permission: skill: "documents-*": "allow" ---对于内置 Agent(在 opencode.json 中):
{ "agent": { "plan": { "permission": { "skill": { "internal-*": "allow" } } } } }2.6 Prompt Engineering 最佳实践
编写高质量的 SKILL.md 是一门艺术。以下是经过验证的最佳实践:
原则一:结构化指令
使用清晰的层级结构,让 LLM 能够准确理解:
## 执行流程 ### Phase 1: 信息收集 1. 读取目标文件内容 2. 分析文件类型和语言 3. 识别相关依赖 ### Phase 2: 分析 1. 检查语法错误 2. 识别代码异味 3. 评估复杂度 ### Phase 3: 报告 1. 汇总发现 2. 优先级排序 3. 生成建议原则二:提供具体示例
Few-shot 示例帮助 LLM 理解预期输出格式:
## 输出示例 ### 发现严重问题时 **位置**: `src/api/users.ts:45` **问题**: SQL 注入漏洞 **风险**: 攻击者可获取数据库内容 **修复建议**: \```typescript // 使用参数化查询 const result = await db.query('SELECT * FROM users WHERE id = $1', [userId]); \```原则三:明确边界和限制
告诉 LLM 什么不应该做:
## ⛔ 禁止行为 1. **不要自动修改代码** - 只提供建议,除非用户明确要求修复 2. **不要审查以下内容**: - `node_modules/` 目录 - 自动生成的文件(*.generated.*) 3. **不要给出模糊建议**: - ❌ "代码可以更简洁" - ✅ "将第 45-52 行的 for 循环替换为 Array.map()"2.7 常见问题排查
如果你的 Skill 没有显示:
- ✅ 确认
SKILL.md是全大写 - ✅ 确认 frontmatter 包含
name和description - ✅ 确认 Skill 名称在所有位置中是唯一的
- ✅ 检查权限配置——
deny的 Skills 会对 Agent 隐藏 - ✅ 确认目录名与 frontmatter 中的
name一致
第三章:Oh My OpenCode 多智能体协作
3.1 什么是 Oh My OpenCode?
Oh My OpenCode (OMO) 是 OpenCode 的社区推荐插件,它将单一 AI Agent 升级为多智能体协作系统。
核心理念:模拟真实开发团队的协作方式——有人负责规划、有人负责执行、有人负责审查。每个 Agent 专注于自己擅长的领域,通过协作完成复杂任务。
设计理念 说明 团队协作 模拟真实开发团队,每个 Agent 扮演不同角色 成本优化 智能路由到成本最优的模型 并行执行 后台 Agent 异步运行,提高效率 专业分工 每个 Agent 专注特定领域,提高质量 安装方式
# 方式 1: 使用 bunx(推荐) bunx oh-my-opencode install # 方式 2: 手动配置 # 在 opencode.json 中添加 { "plugin": ["oh-my-opencode"] }3.2 Sisyphus 编排器
Sisyphus(西西弗斯)是 OMO 的核心编排器。它以希腊神话中那位不断推石上山的人物命名,象征着 Agent 不断迭代解决问题的工作方式。
核心职责
- 任务分析:理解用户意图,分解为子任务
- 智能路由:将任务委派给最合适的专家 Agent
- 进度跟踪:通过 TodoList 管理任务状态
- 结果整合:汇总各 Agent 输出,生成最终响应
委派策略优先级
优先级 1: Skills ↓ 如果有匹配的 Skill,直接加载使用 优先级 2: Direct Tools ↓ 范围明确的简单任务,使用内置工具 优先级 3: Background Agents ↓ 可并行执行的任务,异步返回结果 优先级 4: Blocking Agents ↓ 需要即时结果的复杂任务3.3 专业 Agent 矩阵
规划三人组 (Planning Triad)
Agent 角色 核心能力 Prometheus 规划者 战略规划、任务分解、架构设计 Metis 顾问 计划审查、风险识别、隐性需求挖掘 Momus 批评者 代码审查、质量把关、改进建议 Prometheus 的工作哲学:
"我是纯粹的战略家,从不直接写代码。我的工作是通过访谈和分析建立完美计划。"
Metis 的强制介入:
"在 Prometheus 制定任何计划之前,必须先咨询我。我会强制外化那些隐性知识。"
执行专家 (Execution Specialists)
Agent 专长 使用场景 Librarian 文档搜索 搜索文档、GitHub、知识库 Explore 代码搜索 快速代码搜索、定位 Oracle 技术咨询 技术咨询、调试帮助、方案评估 Frontend 前端开发 React/Vue/UI 组件开发 Backend 后端开发 API/数据库/服务开发 QA 测试 测试编写、Bug 验证 3.4 后台任务与并行执行
OMO 的核心优势之一是后台并行执行——多个 Agent 可以同时工作:
用户: 调研主流的状态管理方案 Sisyphus 执行计划: ├── 后台任务 1: @librarian → 搜索 Redux 文档 ├── 后台任务 2: @librarian → 搜索 Zustand 文档 ├── 后台任务 3: @librarian → 搜索 Jotai 文档 ├── 后台任务 4: @explore → 搜索项目现有状态管理 └── 主线程: Sisyphus 继续规划后续步骤 (所有后台任务并行执行,2-5秒后) ↓ 汇总所有结果,生成对比分析报告任务调用方式
显式调用(通过 @ 提及):
@librarian 搜索一下 JWT 认证的最佳实践 @explore 找一下项目中现有的认证代码 @oracle 帮我分析一下这两个方案哪个更好隐式调用(Sisyphus 自动委派):
用户: 帮我重构这个模块 Sisyphus: (自动分析后调用) → @explore 搜索相关代码 → @prometheus 制定重构计划 → @momus 审查方案📎 附录
A. 常用命令速查
命令 说明 /init初始化项目配置 /connect配置 LLM Provider /models选择模型 /undo撤销上一步 /redo重做 /share分享会话 B. 配置文件位置汇总
类型 路径 全局配置 ~/.config/opencode/opencode.json项目配置 ./opencode.json全局插件 ~/.config/opencode/plugins/项目插件 .opencode/plugins/全局技能 ~/.config/opencode/skills/项目技能 .opencode/skills/全局工具 ~/.config/opencode/tools/项目工具 .opencode/tools/
歡迎留言回复交流。
Log in to reply.