Agent Skillsdifferent-ai/openwork › create-plugin

create-plugin

GitHub

用于生成符合 OpenCode/OpenWork 规范的插件脚手架代码,包含工具定义、钩子注册及生命周期管理,支持通过命令或意图触发。

.opencode/skills/create-plugin/SKILL.md different-ai/openwork

Trigger Scenarios

用户要求创建插件 用户要求编写自定义工具

Install

npx skills add different-ai/openwork --skill create-plugin -g -y
More Options

Non-standard path

npx skills add https://github.com/different-ai/openwork/tree/dev/.opencode/skills/create-plugin -g -y

Use without installing

npx skills use different-ai/openwork@create-plugin

指定 Agent (Claude Code)

npx skills add different-ai/openwork --skill create-plugin -a claude-code -g -y

安装 repo 全部 skill

npx skills add different-ai/openwork --all -g -y

预览 repo 内 skill

npx skills add different-ai/openwork --list

SKILL.md

Frontmatter
{
    "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

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

{
  // 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:

{
  "plugin": [
    ".opencode/plugins/my-plugin.ts"
  ]
}

Or install from npm:

{
  "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

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.

Version History

  • ff5d298 Current 2026-08-20 11:35

Same Skill Collection

.opencode/skills/agent-first-screenshots/SKILL.md
.opencode/skills/browser-automation/SKILL.md
.opencode/skills/build-a-witness/SKILL.md
.opencode/skills/cloud-dashboard-walkthrough/SKILL.md
.opencode/skills/daytona-chrome-cdp/SKILL.md
.opencode/skills/daytona-cloud-instance/SKILL.md
.opencode/skills/daytona-cloud-server/SKILL.md
.opencode/skills/daytona-dev/SKILL.md
.opencode/skills/daytona-electron-den/SKILL.md
.opencode/skills/daytona-electron-test/SKILL.md
.opencode/skills/daytona-flow-validator/SKILL.md
.opencode/skills/daytona-recording-artifacts/SKILL.md
.opencode/skills/daytona-secrets-volume/SKILL.md
.opencode/skills/daytona-seeded-cloud-demo/SKILL.md
.opencode/skills/daytona-windows-cert/SKILL.md
.opencode/skills/diagnose-a-red-run/SKILL.md
.opencode/skills/fraimz/SKILL.md
.opencode/skills/get-env-var/SKILL.md
.opencode/skills/openwork-models/SKILL.md
.opencode/skills/product-tutorial-pipeline/SKILL.md
.opencode/skills/prove-a-pr/SKILL.md
.opencode/skills/publish-evidence/SKILL.md
.opencode/skills/run-evals/SKILL.md
.opencode/skills/run-tests/SKILL.md
.opencode/skills/shadcn/SKILL.md
.opencode/skills/upload-photo/SKILL.md
.opencode/skills/write-a-spec/SKILL.md
.warden/skills/desktop-den-sync-review/SKILL.md
.warden/skills/diff-security-review/SKILL.md

Metadata

Files
0
Version
757601b
Hash
2571541e
Indexed
2026-08-20 11:35

inicio - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-09-17 05:32
浙ICP备14020137号-1