cmd/sgai/skel/.sgai/skills/opencode-plugin-development/SKILL.md
Guide for creating and implementing plugins to extend OpenCode functionality, including hooks, custom tools, and event handling. When you need to add custom functionality to OpenCode, such as notifications, custom tools, or modifying behavior.
npx skillsauth add sandgardenhq/sgai opencode-plugin-developmentInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Plugins allow you to extend OpenCode by hooking into various events, adding custom tools, and customizing behavior. This skill guides you through creating plugins using JavaScript/TypeScript modules that export plugin functions.
A plugin is a JavaScript/TypeScript module that exports one or more plugin functions. Each function receives a context object and returns a hooks object.
export const MyPlugin = async ({ project, client, $, directory, worktree }) => {
console.log("Plugin initialized!")
return {
// Hook implementations go here
}
}
project: Current project informationdirectory: Current working directoryworktree: Git worktree pathclient: OpenCode SDK client for AI interactions$: Bun's shell API for executing commandsimport type { Plugin } from "@opencode-ai/plugin"
export const MyPlugin: Plugin = async ({ project, client, $, directory, worktree }) => {
return {
// Type-safe hook implementations
}
}
Plugins are loaded from:
.sgai/plugin directory in your project~/.config/opencode/pluginListen for OpenCode events:
return {
event: async ({ event }) => {
if (event.type === "session.idle") {
await $`osascript -e 'display notification "Session completed!" with title "opencode"'`
}
}
}
Add custom tools:
import { type Plugin, tool } from "@opencode-ai/plugin"
export const CustomToolsPlugin: Plugin = async (ctx) => {
return {
tool: {
mytool: tool({
description: "This is a custom tool",
args: {
foo: tool.schema.string(),
},
async execute(args, ctx) {
return `Hello ${args.foo}!`
},
}),
},
}
}
Intercept tool execution:
return {
"tool.execute.before": async (input, output) => {
if (input.tool === "read" && output.args.filePath.includes(".env")) {
throw new Error("Do not read .env files")
}
}
}
.sgai/plugin/Send notifications on events:
export const NotificationPlugin = async ({ $ }) => {
return {
event: async ({ event }) => {
if (event.type === "session.idle") {
await $`notify-send "OpenCode" "Session completed"`
}
}
}
}
Prevent access to sensitive files:
export const FileProtection = async () => {
return {
"tool.execute.before": async (input) => {
const protectedPatterns = [/\.env$/, /secrets\//, /private\//]
if (input.tool === "read" && protectedPatterns.some(p => p.test(input.args.filePath))) {
throw new Error("Access denied to protected file")
}
}
}
}
Add domain-specific tools:
export const DomainTools: Plugin = async () => {
return {
tool: {
analyzeCode: tool({
description: "Analyze code for specific patterns",
args: {
filePath: tool.schema.string(),
pattern: tool.schema.string()
},
execute: async (args) => {
// Implementation
return "Analysis complete"
}
})
}
}
}
documentation
Start, stop, and steer agentic sessions in sgai workspaces. Use when you need to launch AI agent sessions, halt running sessions, or inject steering instructions to guide the agent mid-execution without stopping it.
development
Monitor sgai workspace status, events, progress, diffs, and workflow diagrams. Use when you need to observe what agents are doing, track progress, get the current state of all workspaces, subscribe to real-time updates via SSE, or inspect code changes.
development
Access agents, skills, and code snippets available in sgai workspaces. Use when you need to discover what agents are defined in a workspace, browse available skills, get skill instructions, find code snippets by language, or retrieve snippet content for a specific task.
data-ai
Handle agent questions and work gates in sgai workspaces. Use when an agent is blocked waiting for human input, when you need to respond to multi-choice questions, approve work gates, or provide free-text answers to agent queries.