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에서 보기