Agent skill

Creating Opencode Plugins

by pr-pm in pr-pm/prpm

A skill your agent uses when creating OpenCode plugins that hook into command, file, LSP, message, permission, server, session, todo, tool, or TUI events - provides plugin structure, event API…

MITAuto-check: notesBackend & APIs

Install Creating Opencode Plugins

skills CLI
$ npx skills add pr-pm/prpm --skill creating-opencode-plugins -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install pr-pm/prpm creating-opencode-plugins --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/pr-pm/prpm.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.claude/skills/creating-opencode-plugins .claude/skills/creating-opencode-plugins && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
creating-opencode-plugins
GitHub stars
122
Token cost
~2.7k tokens
SKILL.md length
454 words
Files
1
Skills in repo
35
Repo updated
First seen
Licence
MIT

At a glance

A skill your agent uses when creating OpenCode plugins that hook into command, file, LSP, message, permission, server, session, todo, tool, or TUI events - provides plugin structure, event API…

  • Creating OpenCode plugins that hook into command
  • SKILL.md covers Overview, When to Use, Quick Reference and Implementation, plus 8 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md
  • TUI events - provides plugin structure

What it does

Creating Opencode Plugins is an agent skill from pr-pm/prpm. Use when creating OpenCode plugins that hook into command, file, LSP, message, permission, server, session, todo, tool, or TUI events - provides plugin structure, event API specifications, and implementation patterns for JavaScript/TypeScript event-driven modules

Its SKILL.md is about 2.7k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Backend & APIs, covering Hooks and plugins, OpenAPI specifications and Event-driven systems. It works with JavaScript and TypeScript. The repository describes itself as: The universal registry for AI coding tools. The licence is MIT.

When your agent uses it

  • Creating OpenCode plugins that hook into command
  • TUI events - provides plugin structure
  • Event API specifications
  • Implementation patterns for JavaScript/TypeScript event-driven modules

Example prompts

  • “/creating-opencode-plugins”

What it can do on your machine

Read from SKILL.md and the folder at commit 5f993e6. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are javascript, json and typescript).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    Links to these hosts (documentation or services it may open):

    • github.com
    • opencode.ai

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Creating Opencode Plugins loads about 2.7k tokens when it runs. Until then it costs about 72 tokens; SKILL.md has 454 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~72
When it runs · the whole SKILL.md, loaded when a task matches
~2.7k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check: notes

The automated check noted patterns worth knowing about, such as sudo or a known installer.

  • NoteMentions a .env fileSKILL.md:15
    cepting file operations (prevent sharing .env files)
  • NoteMentions a .env fileSKILL.md:74
    "description": "Prevents sharing .env files",
  • NoteMentions a .env fileSKILL.md:303
    data: { path: '.env', content: 'SECRET=123', timestamp: Date.now() }
  • NoteMentions a .env fileSKILL.md:310
    redentials (env-protection plugin blocks .env file reads)

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from pr-pm/prpm at commit 5f993e6, republished under its MIT licence (© pr-pm). 454 words, ~2,705 tokens.

Download SKILL.mdSave it as .claude/skills/creating-opencode-plugins/SKILL.md (or your agent's skills folder).
name
creating-opencode-plugins
description
Use when creating OpenCode plugins that hook into command, file, LSP, message, permission, server, session, todo, tool, or TUI events - provides plugin structure, event API specifications, and implementation patterns for JavaScript/TypeScript event-driven modules

Creating OpenCode Plugins

Overview

OpenCode plugins are JavaScript/TypeScript modules that hook into 25+ events across the OpenCode AI assistant lifecycle. Plugins export an async function receiving context (project, client, $, directory, worktree) and return an event handler.

When to Use

Create an OpenCode plugin when:

  • Intercepting file operations (prevent sharing .env files)
  • Monitoring command execution (notifications, logging)
  • Processing LSP diagnostics (custom error handling)
  • Managing permissions (auto-approve trusted operations)
  • Reacting to session lifecycle (cleanup, initialization)
  • Extending tool capabilities (custom tool registration)
  • Enhancing TUI interactions (custom prompts, toasts)

Don't create for:

  • Simple prompt instructions (use agents instead)
  • One-time scripts (use bash tools)
  • Static configuration (use settings files)

Quick Reference

Plugin Structure
javascript
export const MyPlugin = async (context) => {
  // context: { project, client, $, directory, worktree }

  return {
    event: async ({ event }) => {
      // event: { type: 'event.name', data: {...} }

      switch(event.type) {
        case 'file.edited':
          // Handle file edits
          break;
        case 'tool.execute.before':
          // Pre-process tool execution
          break;
      }
    }
  };
};
Event Categories
CategoryEventsUse Cases
commandcommand.executedTrack command history, notifications
filefile.edited, file.watcher.updatedFile validation, auto-formatting
installationinstallation.updatedDependency tracking
lsplsp.client.diagnostics, lsp.updatedCustom error handling
messagemessage.*.updated/removedMessage filtering, logging
permissionpermission.replied/updatedPermission policies
serverserver.connectedConnection monitoring
sessionsession.created/deleted/error/idle/status/updated/compacted/diffSession management
todotodo.updatedTodo synchronization
tooltool.execute.before/afterTool interception, augmentation
tuitui.prompt.append, tui.command.execute, tui.toast.showUI customization
Plugin Manifest (package.json or separate config)
json
{
  "name": "env-protection",
  "description": "Prevents sharing .env files",
  "version": "1.0.0",
  "author": "Security Team",
  "plugin": {
    "file": "plugin.js",
    "location": "global"
  },
  "hooks": {
    "file": ["file.edited"],
    "permission": ["permission.replied"]
  }
}

Implementation

Complete Example: Environment File Protection
javascript
// .opencode/plugin/env-protection.js

export const EnvProtectionPlugin = async ({ project, client }) => {
  const sensitivePatterns = [
    /\.env$/,
    /\.env\..+$/,
    /credentials\.json$/,
    /\.secret$/,
  ];

  const isSensitiveFile = (filePath) => {
    return sensitivePatterns.some(pattern => pattern.test(filePath));
  };

  return {
    event: async ({ event }) => {
      switch (event.type) {
        case 'file.edited': {
          const { path } = event.data;

          if (isSensitiveFile(path)) {
            console.warn(`⚠️  Sensitive file edited: ${path}`);
            console.warn('This file should not be shared or committed.');
          }
          break;
        }

        case 'permission.replied': {
          const { action, target, decision } = event.data;

          // Block read/share operations on sensitive files
          if ((action === 'read' || action === 'share') &&
              isSensitiveFile(target) &&
              decision === 'allow') {

            console.error(`🚫 Blocked ${action} operation on sensitive file: ${target}`);

            // Override permission decision
            return {
              override: true,
              decision: 'deny',
              reason: 'Sensitive file protection policy'
            };
          }
          break;
        }
      }
    }
  };
};
Example: Command Execution Notifications
javascript
// .opencode/plugin/notify.js

export const NotifyPlugin = async ({ project, $ }) => {
  let commandStartTime = null;

  return {
    event: async ({ event }) => {
      switch (event.type) {
        case 'command.executed': {
          const { command, args, status } = event.data;
          commandStartTime = Date.now();

          console.log(`▶️  Executing: ${command} ${args.join(' ')}`);
          break;
        }

        case 'tool.execute.after': {
          const { tool, duration, success } = event.data;

          if (duration > 5000) {
            // Notify for long-running operations
            await $`osascript -e 'display notification "Completed in ${duration}ms" with title "${tool}"'`;
          }

          console.log(`✅ ${tool} completed in ${duration}ms`);
          break;
        }
      }
    }
  };
};
Example: Custom Tool Registration
javascript
// .opencode/plugin/custom-tools.js

export const CustomToolsPlugin = async ({ client }) => {
  // Register custom tool on initialization
  await client.registerTool({
    name: 'lint',
    description: 'Run linter on current file with auto-fix option',
    parameters: {
      type: 'object',
      properties: {
        fix: {
          type: 'boolean',
          description: 'Auto-fix issues'
        }
      }
    },
    handler: async ({ fix }) => {
      const result = await $`eslint ${fix ? '--fix' : ''} .`;
      return {
        output: result.stdout,
        errors: result.stderr
      };
    }
  });

  return {
    event: async ({ event }) => {
      // Monitor tool usage
      if (event.type === 'tool.execute.before') {
        console.log(`🔧 Tool: ${event.data.tool}`);
      }
    }
  };
};

Installation Locations

LocationPathScopeUse Case
Global~/.config/opencode/plugin/All projectsSecurity policies, global utilities
Project.opencode/plugin/Current projectProject-specific hooks, validators

Common Mistakes

MistakeWhy It FailsFix
Synchronous event handlerBlocks event loopUse async handlers
Missing error handlingPlugin crashes on errorWrap in try/catch
Heavy computation in handlerSlows down operationsDefer to background process
Mutating event data directlyCauses side effectsReturn override object
Not checking event typeHandles wrong eventsUse switch/case on event.type
Forgetting context destructuringMissing key utilitiesDestructure { project, client, $, directory, worktree }
Show full SKILL.md (175 more words)Show less

Event Data Structures

typescript
// File Events
interface FileEditedEvent {
  type: 'file.edited';
  data: {
    path: string;
    content: string;
    timestamp: number;
  };
}

// Tool Events
interface ToolExecuteBeforeEvent {
  type: 'tool.execute.before';
  data: {
    tool: string;
    args: Record<string, any>;
    user: string;
  };
}

interface ToolExecuteAfterEvent {
  type: 'tool.execute.after';
  data: {
    tool: string;
    duration: number;
    success: boolean;
    output?: any;
    error?: string;
  };
}

// Permission Events
interface PermissionRepliedEvent {
  type: 'permission.replied';
  data: {
    action: 'read' | 'write' | 'execute' | 'share';
    target: string;
    decision: 'allow' | 'deny';
  };
}

Testing Plugins

javascript
// Test plugin locally before installation
import { EnvProtectionPlugin } from './env-protection.js';

const mockContext = {
  project: { root: '/test/project' },
  client: {},
  $: async (cmd) => ({ stdout: '', stderr: '' }),
  directory: '/test/project',
  worktree: null
};

const plugin = await EnvProtectionPlugin(mockContext);

// Simulate event
await plugin.event({
  event: {
    type: 'file.edited',
    data: { path: '.env', content: 'SECRET=123', timestamp: Date.now() }
  }
});

Real-World Impact

Security: Prevent accidental sharing of credentials (env-protection plugin blocks .env file reads)

Productivity: Auto-notify on long-running commands (notify plugin sends system notifications)

Quality: Auto-format files on save (file.edited hook runs prettier)

Monitoring: Track tool usage patterns (tool.execute hooks log analytics)

Claude Code Event Mapping

When porting Claude Code hook behavior to OpenCode plugins, use these event mappings:

Claude HookOpenCode EventDescription
PreToolUsetool.execute.beforeRun before tool execution, can block
PostToolUsetool.execute.afterRun after tool execution
UserPromptSubmitmessage.* eventsProcess user prompts
SessionEndsession.idleSession completion
Example: Claude-like Hook Behavior
javascript
export const CompatiblePlugin = async (context) => {
  return {
    // Equivalent to Claude's PreToolUse hook
    'tool.execute.before': async (input, output) => {
      if (shouldBlock(input)) {
        throw new Error('Blocked by policy');
      }
    },

    // Equivalent to Claude's PostToolUse hook
    'tool.execute.after': async (result) => {
      console.log(`Tool completed: ${result.tool}`);
    },

    // Equivalent to Claude's SessionEnd hook
    event: async ({ event }) => {
      if (event.type === 'session.idle') {
        await cleanup();
      }
    }
  };
};

Plugin Composition

Combine multiple plugins using opencode-plugin-compose:

javascript
import { compose } from "opencode-plugin-compose";

const composedPlugin = compose([
  envProtectionPlugin,
  notifyPlugin,
  customToolsPlugin
]);
// Runs all hooks in sequence

Non-Convertibility Note

Important: OpenCode plugins cannot be directly converted from Claude Code hooks due to fundamental differences:

  • Event models differ: Claude has 4 hook events, OpenCode has 32+
  • Formats differ: Claude uses executable scripts, OpenCode uses JS/TS modules
  • Execution context differs: Different context objects and return value semantics

When porting Claude hooks to OpenCode plugins, you'll need to rewrite the logic using the OpenCode plugin API.


Schema Reference: packages/converters/schemas/opencode-plugin.schema.json

Documentation: https://opencode.ai/docs/plugins/

© pr-pm, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in .claude/skills/creating-opencode-plugins of pr-pm/prpm.

Open the folder on GitHubat commit 5f993e6

Compare with similar skills

Creating Opencode Plugins next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Creating Opencode Plugins compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Creating Opencode Plugins this skillpr-pm/prpm122—~2.7kAutomated safety check: NotesMIT
Counterfact Replcounterfact/api-simulator170—~3.2kAutomated safety check: PassMIT
Azure Eventhub TSmicrosoft/skills3.1k6 repos~1.9kAutomated safety check: PassMIT
Azure Storage Queue TSmicrosoft/skills3.1k6 repos~3.5kAutomated safety check: PassMIT
API Breaking Change Detectorgithub/awesome-copilot40k—~1.7kAutomated safety check: PassMIT
Azure Web Pubsub TSmicrosoft/skills3.1k—~2.1kAutomated safety check: PassMIT

Similar skills

  • Counterfact Repl

    counterfact/api-simulator

    Interact with Counterfact mock API server programmatically. An agent skill from counterfact/api-simulator.

    170 GitHub stars~3.2k tokensUpdated yesterday
    Backend & APIsAuto-check passed
  • Azure Eventhub TS

    microsoft/skills

    Official

    Build event streaming applications using Azure Event Hubs SDK for JavaScript (@azure/event-hubs).

    3.1k GitHub starsUsed in 6 repos~1.9k tokens
    Backend & APIsAuto-check passed
  • Azure Storage Queue TS

    microsoft/skills

    Official

    Azure Queue Storage JavaScript/TypeScript SDK (@azure/storage-queue) for message queue operations.

    3.1k GitHub starsUsed in 6 repos~3.5k tokens
    Backend & APIsAuto-check passed
  • API Breaking Change Detector

    github/awesome-copilot

    Official

    Cross-references C Web API controllers/DTOs against their TypeScript/JavaScript consumers (React, Angular, Vue, Svelte, Node.js, or hand-written/auto-generated HTTP clients like Fetch, Axios, NSwag)…

    40k GitHub stars~1.7k tokensUpdated today
    Backend & APIsAuto-check passed
  • Azure Web Pubsub TS

    microsoft/skills

    Official

    Build real-time messaging applications using Azure Web PubSub SDKs for JavaScript (@azure/web-pubsub, @azure/web-pubsub-client).

    3.1k GitHub stars~2.1k tokensUpdated yesterday
    Backend & APIsAuto-check passed
  • Logseq Plugin SDK

    logseq/logseq

    Build, debug, or review Logseq plugins with the @logseq/libs SDK (TypeScript/JavaScript, iframe/shadow sandboxed).

    45k GitHub stars~2.3k tokensUpdated today
    Knowledge ManagementAuto-check passed

More from pr-pm/prpm

All 35 skills in this repo
  • Reference for writing Claude Code agent files: location, frontmatter fields, validation limits, tool and model choices, and the required content format.

    122 GitHub starsUsed in 3 repos~4k tokens
    Auto-check passed
  • Covers how to build, configure and publish Claude Code hooks: event types, exit codes, JSON I/O, and PRPM packaging.

    122 GitHub starsUsed in 2 repos~3.9k tokens
    Auto-check: notes
  • Shows how to write .claude/rules/ files correctly: paths frontmatter instead of globs, quoted glob patterns, global rules and conversion of Cursor rules.

    122 GitHub starsUsed in 2 repos~551 tokens
    Auto-check passed
  • Reference for writing portable Agent Skills packages, covering SKILL.md frontmatter limits, name rules, directory layout and where Codex CLI, GitHub Copilot and Amp look for skills.

    122 GitHub starsUsed in 1 repo~1.5k tokens
    Auto-check passed
  • A skill your agent uses when building custom Kiro AI agents or when user asks for agent configurations - provides JSON structure, tool configuration, prompt patterns, and security best practices for…

    122 GitHub starsUsed in 1 repo~1.9k tokens
    Auto-check passed
  • A skill your agent uses when creating OpenCode agents - provides markdown format with YAML frontmatter, mode/tools/permission configuration, and best practices for specialized AI assistants

    122 GitHub starsUsed in 1 repo~2k tokens
    Auto-check passed

Categories

Questions about Creating Opencode Plugins

What does Creating Opencode Plugins do?

A skill your agent uses when creating OpenCode plugins that hook into command, file, LSP, message, permission, server, session, todo, tool, or TUI events - provides plugin structure, event API…. Creating Opencode Plugins is an agent skill from pr-pm/prpm.

When should I use Creating Opencode Plugins?

Creating Opencode Plugins fits situations like: creating OpenCode plugins that hook into command; TUI events - provides plugin structure; event API specifications; implementation patterns for JavaScript/TypeScript event-driven modules.

How do I install Creating Opencode Plugins in Claude Code?

Run `npx skills add pr-pm/prpm --skill creating-opencode-plugins -a claude-code`. Or copy the skill folder (.claude/skills/creating-opencode-plugins in pr-pm/prpm) into .claude/skills/creating-opencode-plugins in your project. Claude Code loads it when a task matches its description.

How do I install Creating Opencode Plugins in Codex?

Run `npx skills add pr-pm/prpm --skill creating-opencode-plugins -a codex`. Or copy the skill folder (.claude/skills/creating-opencode-plugins in pr-pm/prpm) into .agents/skills/creating-opencode-plugins in your project. Codex loads it when a task matches its description.

Can I use Creating Opencode Plugins in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add pr-pm/prpm --skill creating-opencode-plugins -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/creating-opencode-plugins, .gemini/skills/creating-opencode-plugins, .github/skills/creating-opencode-plugins and .opencode/skills/creating-opencode-plugins in your project.

What does Creating Opencode Plugins need to run?

SKILL.md names no scripts, command-line tools or credentials: Creating Opencode Plugins is instructions for the agent only.

Does Creating Opencode Plugins access the network?

SKILL.md names 2 domains. As links in the text: github.com and opencode.ai. This is read from the text; nothing was executed.

Is Creating Opencode Plugins safe to install?

Our automated static check of SKILL.md found notes only (mentions a .env file), nothing it rates as a warning. It is not a guarantee. Review the folder before installing.

What licence does Creating Opencode Plugins use?

Creating Opencode Plugins is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Creating Opencode Plugins use?

About 2.7k tokens (SKILL.md is roughly 11k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Creating Opencode Plugins?

Skills that share tags, products or a category with Creating Opencode Plugins: Counterfact Repl (counterfact/api-simulator, 170 stars), Azure Eventhub TS (microsoft/skills, 3.1k stars), Azure Storage Queue TS (microsoft/skills, 3.1k stars) and API Breaking Change Detector (github/awesome-copilot, 40k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Creating Opencode Plugins?

pr-pm (a GitHub organization) maintains it in pr-pm/prpm, which has 122 GitHub stars. The repository holds 35 skills in this directory. The repository was last updated on October 6, 2026.

Source: pr-pm/prpm on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.