Counterfact Repl
counterfact/api-simulator
Interact with Counterfact mock API server programmatically. An agent skill from counterfact/api-simulator.
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…
$ npx skills add pr-pm/prpm --skill creating-opencode-plugins -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install pr-pm/prpm creating-opencode-plugins --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ 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-srcUse ~/.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/
Install the "creating-opencode-plugins" agent skill from https://github.com/pr-pm/prpm/tree/main/.claude/skills/creating-opencode-plugins into .claude/skills/creating-opencode-plugins/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "creating-opencode-plugins", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/pr-pm/prpm/tree/main/.claude/skills/creating-opencode-pluginsType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add pr-pm/prpm --skill creating-opencode-plugins -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install pr-pm/prpm creating-opencode-plugins --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/pr-pm/prpm.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.claude/skills/creating-opencode-plugins .agents/skills/creating-opencode-plugins && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "creating-opencode-plugins" agent skill from https://github.com/pr-pm/prpm/tree/main/.claude/skills/creating-opencode-plugins into .agents/skills/creating-opencode-plugins/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "creating-opencode-plugins", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add pr-pm/prpm --skill creating-opencode-plugins -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install pr-pm/prpm creating-opencode-plugins --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/pr-pm/prpm.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.claude/skills/creating-opencode-plugins .cursor/skills/creating-opencode-plugins && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "creating-opencode-plugins" agent skill from https://github.com/pr-pm/prpm/tree/main/.claude/skills/creating-opencode-plugins into .cursor/skills/creating-opencode-plugins/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "creating-opencode-plugins", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/pr-pm/prpm.git --path .claude/skills/creating-opencode-plugins--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add pr-pm/prpm --skill creating-opencode-plugins -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install pr-pm/prpm creating-opencode-plugins --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/pr-pm/prpm.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.claude/skills/creating-opencode-plugins .gemini/skills/creating-opencode-plugins && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "creating-opencode-plugins" agent skill from https://github.com/pr-pm/prpm/tree/main/.claude/skills/creating-opencode-plugins into .gemini/skills/creating-opencode-plugins/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "creating-opencode-plugins", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install pr-pm/prpm creating-opencode-pluginsInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add pr-pm/prpm --skill creating-opencode-plugins -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/pr-pm/prpm.git skills-src && mkdir -p .github/skills && cp -r skills-src/.claude/skills/creating-opencode-plugins .github/skills/creating-opencode-plugins && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "creating-opencode-plugins" agent skill from https://github.com/pr-pm/prpm/tree/main/.claude/skills/creating-opencode-plugins into .github/skills/creating-opencode-plugins/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "creating-opencode-plugins", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add pr-pm/prpm --skill creating-opencode-plugins -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install pr-pm/prpm creating-opencode-plugins --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/pr-pm/prpm.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.claude/skills/creating-opencode-plugins .opencode/skills/creating-opencode-plugins && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "creating-opencode-plugins" agent skill from https://github.com/pr-pm/prpm/tree/main/.claude/skills/creating-opencode-plugins into .opencode/skills/creating-opencode-plugins/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "creating-opencode-plugins", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
creating-opencode-pluginsA 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. 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.
Read from SKILL.md and the folder at commit 5f993e6. It shows what the files ask for, not the result of running them.
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.
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.
Links to these hosts (documentation or services it may open):
github.comopencode.aiFrom URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
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.
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.
The automated check noted patterns worth knowing about, such as sudo or a known installer.
cepting file operations (prevent sharing .env files)"description": "Prevents sharing .env files",data: { path: '.env', content: 'SECRET=123', timestamp: Date.now() }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.
The full file from pr-pm/prpm at commit 5f993e6, republished under its MIT licence (© pr-pm). 454 words, ~2,705 tokens.
.claude/skills/creating-opencode-plugins/SKILL.md (or your agent's skills folder).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.
Create an OpenCode plugin when:
Don't create for:
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;
}
}
};
};| Category | Events | Use Cases |
|---|---|---|
| command | command.executed | Track command history, notifications |
| file | file.edited, file.watcher.updated | File validation, auto-formatting |
| installation | installation.updated | Dependency tracking |
| lsp | lsp.client.diagnostics, lsp.updated | Custom error handling |
| message | message.*.updated/removed | Message filtering, logging |
| permission | permission.replied/updated | Permission policies |
| server | server.connected | Connection monitoring |
| session | session.created/deleted/error/idle/status/updated/compacted/diff | Session management |
| todo | todo.updated | Todo synchronization |
| tool | tool.execute.before/after | Tool interception, augmentation |
| tui | tui.prompt.append, tui.command.execute, tui.toast.show | UI customization |
{
"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"]
}
}// .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;
}
}
}
};
};// .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;
}
}
}
};
};// .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}`);
}
}
};
};| Location | Path | Scope | Use Case |
|---|---|---|---|
| Global | ~/.config/opencode/plugin/ | All projects | Security policies, global utilities |
| Project | .opencode/plugin/ | Current project | Project-specific hooks, validators |
| Mistake | Why It Fails | Fix |
|---|---|---|
| Synchronous event handler | Blocks event loop | Use async handlers |
| Missing error handling | Plugin crashes on error | Wrap in try/catch |
| Heavy computation in handler | Slows down operations | Defer to background process |
| Mutating event data directly | Causes side effects | Return override object |
| Not checking event type | Handles wrong events | Use switch/case on event.type |
| Forgetting context destructuring | Missing key utilities | Destructure { project, client, $, directory, worktree } |
// 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';
};
}// 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() }
}
});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)
When porting Claude Code hook behavior to OpenCode plugins, use these event mappings:
| Claude Hook | OpenCode Event | Description |
|---|---|---|
PreToolUse | tool.execute.before | Run before tool execution, can block |
PostToolUse | tool.execute.after | Run after tool execution |
UserPromptSubmit | message.* events | Process user prompts |
SessionEnd | session.idle | Session completion |
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();
}
}
};
};Combine multiple plugins using opencode-plugin-compose:
import { compose } from "opencode-plugin-compose";
const composedPlugin = compose([
envProtectionPlugin,
notifyPlugin,
customToolsPlugin
]);
// Runs all hooks in sequenceImportant: OpenCode plugins cannot be directly converted from Claude Code hooks due to fundamental differences:
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
Just SKILL.md in .claude/skills/creating-opencode-plugins of pr-pm/prpm.
Open the folder on GitHubat commit 5f993e6
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.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Creating Opencode Plugins this skillpr-pm/prpm | 122 | — | ~2.7k | Automated safety check: Notes | MIT | |
| Counterfact Replcounterfact/api-simulator | 170 | — | ~3.2k | Automated safety check: Pass | MIT | |
| Azure Eventhub TSmicrosoft/skills | 3.1k | 6 repos | ~1.9k | Automated safety check: Pass | MIT | |
| Azure Storage Queue TSmicrosoft/skills | 3.1k | 6 repos | ~3.5k | Automated safety check: Pass | MIT | |
| API Breaking Change Detectorgithub/awesome-copilot | 40k | — | ~1.7k | Automated safety check: Pass | MIT | |
| Azure Web Pubsub TSmicrosoft/skills | 3.1k | — | ~2.1k | Automated safety check: Pass | MIT |
counterfact/api-simulator
Interact with Counterfact mock API server programmatically. An agent skill from counterfact/api-simulator.
microsoft/skills
Build event streaming applications using Azure Event Hubs SDK for JavaScript (@azure/event-hubs).
microsoft/skills
Azure Queue Storage JavaScript/TypeScript SDK (@azure/storage-queue) for message queue operations.
github/awesome-copilot
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)…
microsoft/skills
Build real-time messaging applications using Azure Web PubSub SDKs for JavaScript (@azure/web-pubsub, @azure/web-pubsub-client).
logseq/logseq
Build, debug, or review Logseq plugins with the @logseq/libs SDK (TypeScript/JavaScript, iframe/shadow sandboxed).
pr-pm/prpm
Reference for writing Claude Code agent files: location, frontmatter fields, validation limits, tool and model choices, and the required content format.
pr-pm/prpm
Covers how to build, configure and publish Claude Code hooks: event types, exit codes, JSON I/O, and PRPM packaging.
pr-pm/prpm
Shows how to write .claude/rules/ files correctly: paths frontmatter instead of globs, quoted glob patterns, global rules and conversion of Cursor rules.
pr-pm/prpm
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.
pr-pm/prpm
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…
pr-pm/prpm
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
Works with
Categories
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.
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.
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.
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.
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.
SKILL.md names no scripts, command-line tools or credentials: Creating Opencode Plugins is instructions for the agent only.
SKILL.md names 2 domains. As links in the text: github.com and opencode.ai. This is read from the text; nothing was executed.
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.
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.
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.
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.
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.