Skip to main content

create-plugin

Create an OpenCode plugin for OpenWork. Scaffolds the plugin file with the correct API shape, tool definitions, and hook registration. Use when the user asks to 'create a plugin', 'write a plugin', or 'make a plugin that does X'.

来源信息

仓库
different-ai/openwork
最近来源活动
2026年6月2日 01:26
检测到的 SKILL.md 语言
英语
星标
24,131
分支
2,444

安装方式

默认使用会先检查来源的 Prompt;你也可以切换为直接命令,或下载本地副本。

检查来源文件

决定是否安装前,请先阅读 SKILL.md,以及 SkillsMP 当前展示的配套文件。

正在显示 SKILL.md

SKILL.md
来源说明 · 只读预览
name
create-plugin
description
Create an OpenCode plugin for OpenWork. Scaffolds the plugin file with the correct API shape, tool definitions, and hook registration. Use when the user asks to 'create a plugin', 'write a plugin', or 'make a plugin that does X'.
# Skill: Create an OpenCode Plugin Scaffold a working OpenCode plugin for use in OpenWork. ## When to use - User asks "create a plugin that does X" - User asks "write a plugin" or "make a plugin" - User wants to extend OpenWork/OpenCode with custom tools ## Plugin API An OpenCode plugin is an **async factory function** that returns a **hooks object**. ### File location Plugins can live in: - **Project**: `.opencode/plugins/my-plugin.ts` (auto-discovered) - **Global**: `~/.config/opencode/plugins/my-plugin.ts` - **npm**: published as a package, referenced in `opencode.json` `plugin` array - **URL**: `file:` or `https:` path in the `plugin` array ### Minimal shape ```typescript import { z } from "zod"; export default async () => ({ tool: { my_tool_name: { description: "What this tool does.", args: z.object({ input: z.string().describe("The input parameter."), }).shape, // NOTE: .shape, not the ZodObject itself async execute(args: { input: string }) { // Your logic here. Can use fetch(), fs, child_process, etc. return `Result: ${args.input}`; }, }, }, }); ``` ### Key rules 1. **Export default an async function** that returns the hooks object. 2. **Tool args use `zodSchema.shape`** (a `ZodRawShape`), not the `ZodObject`. 3. **`execute` returns a `string`** or `{ output: string; metadata?: Record<string, unknown> }`. 4. **Tools are declared, not registered imperatively** — return them in the hooks object. 5. **`fetch()` works** — plugins run in-process inside the OpenCode runtime. 6. **`process.env` is accessible** — use env vars for secrets/config. ### Available hooks ```typescript { // Modify the system prompt "experimental.chat.system.transform": async (input, output: { system: string[] }) => { output.system.push("Extra instruction for the agent."); }, // Define tools the agent can call tool: { tool_name: { description, args, execute }, }, // Run code before/after a tool executes "tool.execute.before": async ({ tool, args }) => { /* ... */ }, "tool.execute.after": async ({ tool, args, result }) => { /* ... */ }, // React to lifecycle events event: async ({ event }) => { /* ... */ }, } ``` ### Registering the plugin Add to `opencode.json`: ```json { "plugin": [ ".opencode/plugins/my-plugin.ts" ] } ``` Or install from npm: ```json { "plugin": [ "my-published-plugin" ] } ``` ## Anthropic / Claude plugin compatibility OpenCode plugins are **NOT** the same as Anthropic's plugin format. Key differences: | Aspect | OpenCode Plugin | Anthropic Plugin | |--------|----------------|-----------------| | Entry point | Async factory function | Manifest JSON | | Tool args | Zod schema `.shape` | JSON Schema | | Runtime | In-process (Bun/Node) | Sandboxed container | | Auth | `process.env` | OAuth/API key in manifest | | Distribution | npm / file path / URL | Anthropic marketplace | To adapt an Anthropic plugin for OpenCode: 1. Rewrite the tool definitions using Zod instead of JSON Schema. 2. Move any auth from the manifest to env vars or `opencode.json` provider config. 3. Export the async factory function instead of the manifest. 4. HTTP-based Anthropic plugins can often be wrapped as MCP servers instead. ## Example: plugin with multiple tools ```typescript import { z } from "zod"; export default async () => ({ "experimental.chat.system.transform": async (_input: unknown, output: { system: string[] }) => { output.system.push("You have access to a note-taking system. Use save_note and list_notes."); }, tool: { save_note: { description: "Save a note with a title and body.", args: z.object({ title: z.string().describe("Note title"), body: z.string().describe("Note content"), }).shape, async execute(args: { title: string; body: string }) { const fs = await import("node:fs/promises"); const path = `.opencode/notes/${args.title.replace(/[^a-zA-Z0-9-_]/g, "_")}.md`; await fs.mkdir(".opencode/notes", { recursive: true }); await fs.writeFile(path, `# ${args.title}\n\n${args.body}\n`); return `Saved note: ${path}`; }, }, list_notes: { description: "List all saved notes.", args: {}, async execute() { const fs = await import("node:fs/promises"); try { const files = await fs.readdir(".opencode/notes"); return files.filter(f => f.endsWith(".md")).join("\n") || "No notes yet."; } catch { return "No notes yet."; } }, }, }, }); ``` ## Scaffold workflow When the user describes what they want the plugin to do: 1. Create `.opencode/plugins/<name>.ts` with the plugin code. 2. Add it to `opencode.json` `plugin` array if not already present. 3. Tell the user to restart their session for the plugin to load.
在 GitHub 查看