mcpField
W
writing-opencode-plugins

writing-opencode-plugins

github.com/sveltejs开发33561 次安装2 天前更新
代码仓库

关于 writing-opencode-plugins

用于实现 OpenCode 服务端和 TUI 插件的技能,面向插件开发者。它指导如何选择运行时、核对 API 类型、组织模块,并测试行为与生命周期。

主要功能

  1. 01选择服务端或 TUI 目标
  2. 02核对权威插件类型
  3. 03模块结构与配置指导
  4. 04测试和生命周期检查清单

适用场景

  1. 01实现服务端或 TUI 插件
  2. 02编码前核对插件 API 用法
  3. 03测试插件加载与清理

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/sveltejs/ai-tools --skill writing-opencode-plugins

安装后在 Claude Code 中输入/writing-opencode-plugins确认已加载。

详细介绍

编写 OpenCode 插件

使用此技能实现可用于生产环境的 OpenCode 插件。请以仓库导出的类型和运行时为准,因为插件 API 仍在演进,公开文档可能滞后。

从这里开始

  1. 确定哪个运行时负责此功能。
  2. 编写代码前,先阅读相关的公开类型。
  3. 查找一个在仓库中使用相同 API 的精简示例。
  4. 实现最小化的目标专用模块。
  5. 在所属软件包中测试加载、行为、故障和清理。
需求插件目标导入配置
钩子、工具、身份验证、提供方、模型参数、Shell 环境服务端@opencode-ai/pluginopencode.json 或自动发现的 .opencode/plugins/*.{ts,js}
命令、键绑定、路由、对话框、插槽、主题、通知TUI@opencode-ai/plugin/tui显式的 tui.json plugin 条目
两者两个目标专用入口点分别在不同文件中导入软件包导出 ./server 和 ./tui

切勿从同一模块导出 server 和 tui。不要用服务端事件钩子替代交互式 TUI API。

验证当前约定

实现不熟悉的行为前,请先阅读以下文件:

  • packages/plugin/src/index.ts:权威的服务端插件和钩子类型。
  • packages/plugin/src/tool.ts:自定义工具的架构、上下文、权限、元数据、附件和结果类型。
  • packages/plugin/src/tui.ts:权威的 TUI API 和模块类型。
  • packages/opencode/specs/tui-plugins.md:TUI 加载、打包、生命周期和 API 语义。
  • packages/opencode/src/plugin/shared.ts:目标验证、ID 和入口点解析。
  • packages/opencode/src/plugin/loader.ts:安装、兼容性和导入行为。

如果这些内容与示例或网站文档不一致,请遵循导出的类型和运行时行为,并酌情更新过时的文档。

选择模块形态

对于新的服务端插件,优先使用显式模块对象:

import type { Plugin, PluginModule } from '@opencode-ai/plugin';

const server: Plugin = async ({ client, directory }, options) => ({
	dispose: async () => {},
});

export default {
	id: 'acme.example',
	server,
} satisfies PluginModule & { id: string };

旧式的服务端本地插件可以直接导出插件函数。在旧式模块中,每个不同的命名导出都会被视为一个插件,因此不要导出无关常量。新代码优先使用默认模块对象。

TUI 插件始终使用默认模块对象:

/** @jsxImportSource @opentui/solid */
import type { TuiPlugin, TuiPluginModule } from '@opencode-ai/plugin/tui';

const tui: TuiPlugin = async (api) => {
	api.ui.toast({ message: 'Plugin loaded' });
};

export default {
	id: 'acme.example-tui',
	tui,
} satisfies TuiPluginModule & { id: string };

文件插件必须有稳定且非空的 id。npm 插件可以从软件包名称推导 ID,但明确指定带命名空间的 ID,可让状态、诊断和冲突处理更加清晰。

工程规范

  • 使用 TypeScript,并针对公开插件类型使用 satisfies。
  • 解析并验证 options;它们以未经验证的 Record<string, unknown> 形式传入。
  • 为插件 ID、命令 ID、路由名称、模式、插槽名称和共享 KV 键添加命名空间。
  • 使用插件或工具上下文提供的目录,而非 process.cwd()。
  • 对长时间运行或可取消的工作遵循 AbortSignal。
  • 使用 client.app.log() 进行结构化服务端日志记录,而不是使用 console.log。
  • 在执行敏感或可能产生重大影响的自定义工具工作前,请求权限。
  • 确保通知不会泄露隐私;不要暴露提示词、机密、路径、命令或原始错误。
  • 只注册必要的钩子和 UI 资源。如果存在特定钩子,避免订阅范围过广的事件。
  • 确保清理操作有界、幂等,并且在仅完成部分初始化后也能安全执行。
  • 不要依赖未记录的加载顺序来解决所有权冲突。

测试工作流

服务端插件测试应放在 packages/opencode/test/plugin/ 或最接近的所属子系统下。TUI 运行时测试应放在 packages/opencode/test/cli/tui/;组件级 TUI 测试可以放在 packages/tui。

至少测试以下内容:

  • 加载有效性以及目标/入口点选择;
  • 配置选项和格式错误的选项;
  • 可观察到的行为,而不是重复实现逻辑;
  • 中止、失败和部分初始化行为;
  • 清理或释放;
  • 相关情况下的重复 ID 或注册;
  • 发布时本地文件和 npm 打包行为。

请从软件包目录运行测试,切勿从仓库根目录运行。类型检查请在所属软件包中使用 bun typecheck。

审查清单

  • 功能位于正确的服务端或 TUI 运行时中。
  • 模块结构和导入路径与目标匹配。
  • 服务端和 TUI 入口点彼此独立。
  • ID 和持久化键稳定且带命名空间。
  • 已验证选项和外部数据。
  • Hook 输出变更保留其他插件所做的更改。
  • 工具正确使用上下文目录、权限、元数据和中止机制。
  • 除非有意设为全局,否则 TUI 按键绑定受模式限制。
  • TUI 资源和自定义副作用均已释放。
  • 软件包导出、engines.opencode 和配置目标正确。
  • 测试覆盖行为和生命周期。

参考资料

  • 服务端插件:Hook、自定义工具、生命周期和示例。
  • TUI 插件:键位映射、路由、对话框、插槽、状态和生命周期。
  • 打包与测试:配置、软件包导出、兼容性和测试位置。

评论

支持 Markdown