七、扩展 OpenCode:自定义工具、Skill 与插件
·
一、三种扩展方式
OpenCode 提供了三种扩展方式,适应不同粒度的需求:
| 方式 | 适用场景 | 复杂度 |
|---|---|---|
| 自定义工具 | 让 AI 调用特定函数(如查询数据库、调用 API) | 低 |
| Agent Skill | 封装领域知识供 AI 按需加载 | 中 |
| Plugin | 通过事件钩子扩展 OpenCode 行为 | 高 |
二、自定义工具(Custom Tools)
2.1 创建工具
工具是 TypeScript/JavaScript 文件,放在以下目录:
- 项目级:
.opencode/tools/ - 全局:
~/.config/opencode/tools/
文件名就是工具名。
// .opencode/tools/database.ts
import { tool } from "@opencode-ai/plugin"
export default tool({
description: "Query the project database",
args: {
query: tool.schema.string().describe("SQL query to execute"),
},
async execute(args) {
// 你的数据库查询逻辑
return `Executed query: ${args.query}`
},
})
2.2 参数定义(Zod Schema)
使用 tool.schema(基于 Zod)定义参数:
export default tool({
description: "Search user by ID or email",
args: {
id: tool.schema.number().optional().describe("User ID"),
email: tool.schema.string().optional().describe("User email"),
limit: tool.schema.number().default(10).describe("Max results"),
},
async execute(args) {
// 至少需要一个参数
if (!args.id && !args.email) {
return "Please provide id or email"
}
return `Searching for user: ${args.id || args.email}`
},
})
2.3 多个工具在一个文件
导出多个工具,工具名格式为 文件名_导出名:
// .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).toString()
},
})
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).toString()
},
})
此文件会创建 math_add 和 math_multiply 两个工具。
2.4 工具上下文
工具可以访问当前会话的上下文信息:
export default tool({
description: "Get project information",
args: {},
async execute(args, context) {
const { agent, sessionID, messageID, directory, worktree } = context
return `Agent: ${agent}, Session: ${sessionID}, Dir: ${directory}`
},
})
2.5 用 Python 写工具逻辑
工具定义必须是 TS/JS,但执行逻辑可以是任何语言:
# .opencode/tools/add.py
import sys
a = int(sys.argv[1])
b = int(sys.argv[2])
print(a + b)
// .opencode/tools/python-add.ts
import { tool } from "@opencode-ai/plugin"
import path from "path"
export default tool({
description: "Add two numbers using Python",
args: {
a: tool.schema.number().describe("First number"),
b: tool.schema.number().describe("Second number"),
},
async execute(args) {
const script = path.join(context.worktree, ".opencode/tools/add.py")
const result = await Bun.$`python3 ${script} ${args.a} ${args.b}`.text()
return result.trim()
},
})
2.6 覆盖内置工具
自定义工具与内置工具同名时,自定义工具优先:
// .opencode/tools/bash.ts — 替换内置 bash 工具
import { tool } from "@opencode-ai/plugin"
export default tool({
description: "Restricted bash wrapper",
args: {
command: tool.schema.string(),
},
async execute(args) {
return `blocked: ${args.command}`
},
})
三、Agent Skill
3.1 什么是 Skill?
Skill 是 SKILL.md 文件,封装了特定领域的知识。AI 按需加载,而非预置到上下文中。
3.2 创建 Skill
目录结构:.opencode/skills/<name>/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.
3.3 Skill 发现机制
OpenCode 搜索以下位置:
- 项目:
.opencode/skills/<name>/SKILL.md - 全局:
~/.config/opencode/skills/<name>/SKILL.md - 兼容:
.claude/skills/<name>/SKILL.md - 兼容:
.agents/skills/<name>/SKILL.md
3.4 Skill 的 Frontmatter
| 字段 | 必需 | 说明 |
|---|---|---|
name |
是 | 1-64 字符,小写字母数字和单连字符 |
description |
是 | 1-1024 字符 |
license |
否 | 许可证 |
compatibility |
否 | 兼容性说明 |
metadata |
否 | 字符串键值对 |
3.5 Skill 权限控制
{
"permission": {
"skill": {
"*": "allow",
"pr-review": "allow",
"internal-*": "deny",
"experimental-*": "ask"
}
}
}
四、Plugin(插件)
4.1 加载插件
三种方式:
- 本地文件:
.opencode/plugins/或~/.config/opencode/plugins/ - npm 包:
{
"plugin": ["opencode-helicone-session", "@my-org/custom-plugin"]
}
注意:npm 插件通过 Bun 自动安装和缓存到
~/.cache/opencode/node_modules/。如果使用 npm 插件,需要安装 Bun。
4.2 插件加载顺序
插件按以下顺序加载:
- 全局配置中的 npm 插件(
~/.config/opencode/opencode.json) - 项目配置中的 npm 插件(
opencode.json) - 全局插件目录(
~/.config/opencode/plugins/) - 项目插件目录(
.opencode/plugins/)
所有钩子按此顺序依次执行。
4.3 插件依赖管理
本地插件和自定义工具可以使用外部 npm 包。在配置目录中添加 package.json:
// .opencode/package.json
{
"dependencies": {
"shescape": "^2.1.0"
}
}
OpenCode 启动时会自动运行 bun install 安装依赖。然后插件中可以导入:
// .opencode/plugins/my-plugin.ts
import { escape } from "shescape"
4.4 创建插件
// .opencode/plugins/example.js
export const MyPlugin = async ({ project, client, $, directory, worktree }) => {
console.log("Plugin initialized!")
return {
// 钩子实现
}
}
插件函数接收:
project:当前项目信息directory:工作目录worktree:Git worktree 路径client:OpenCode SDK 客户端$:Bun shell API(仅在有 Bun 时可用)
TypeScript 类型支持:
import type { Plugin } from "@opencode-ai/plugin"
export const MyPlugin: Plugin = async ({ project, client, $, directory, worktree }) => {
return {
// 类型安全的钩子实现
}
}
4.5 事件钩子
插件可以订阅多种事件:
Session 事件:
session.created/session.deleted/session.errorsession.idle/session.updatedsession.compacted
Tool 事件:
tool.execute.before/tool.execute.after
Message 事件:
message.updated/message.removed
Permission 事件:
permission.asked/permission.replied
File 事件:
file.edited/file.watcher.updated
4.6 实用示例
通知插件
// .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"'`
}
},
}
}
.env 保护插件
// .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 (ctx) => {
return {
"experimental.session.compacting": async (input, output) => {
output.context.push(`## Custom Context
- Current task status
- Important decisions made
- Files being actively worked on`)
},
}
}
注入环境变量
// .opencode/plugins/inject-env.js
export const InjectEnvPlugin = async () => {
return {
"shell.env": async (input, output) => {
output.env.MY_API_KEY = "secret"
output.env.PROJECT_ROOT = input.cwd
},
}
}
插件中添加自定义工具
// .opencode/plugins/custom-tools.ts
import { type Plugin, tool } from "@opencode-ai/plugin"
export const CustomToolsPlugin: Plugin = async (ctx) => {
return {
tool: {
mytool: tool({
description: "This is a custom tool",
args: {
foo: tool.schema.string(),
},
async execute(args, context) {
const { directory, worktree } = context
return `Hello ${args.foo} from ${directory} (worktree: ${worktree})`
},
}),
},
}
}
结构化日志
export const MyPlugin = async ({ client }) => {
await client.app.log({
body: {
service: "my-plugin",
level: "info",
message: "Plugin initialized",
extra: { foo: "bar" },
},
})
}
五、扩展方式选择指南
| 需求 | 推荐方式 |
|---|---|
| AI 需要调用特定函数/API | 自定义工具 |
| 封装领域知识供 AI 参考 | Skill |
| 在事件发生时执行操作 | Plugin |
| 修改 OpenCode 默认行为 | Plugin |
| 添加新的交互命令 | Plugin (command 事件) |
六、总结
本文覆盖了 OpenCode 三种扩展方式:
- 自定义工具:让 AI 调用自定义函数,开发成本最低
- Agent Skill:封装领域知识按需加载,适合分享和复用
- Plugin:通过事件钩子深度定制,功能最强大
下一篇文章将介绍 OpenCode 的高阶玩法:CLI 自动化、CI/CD 集成与远程协作。
更多推荐




所有评论(0)