diff options
| author | Dax Raad <[email protected]> | 2025-08-03 21:42:45 -0400 |
|---|---|---|
| committer | Dax Raad <[email protected]> | 2025-08-03 21:43:58 -0400 |
| commit | f85d30c484f26c0656dd91ad5f9c5ed26c0a2fce (patch) | |
| tree | ff8cc896fa4eee9da0c83ccbf0a49343c5590472 /packages/web/src/content/docs | |
| parent | 1bac46612cef3b383af2ce411ca2ad313d5c5ce0 (diff) | |
| download | opencode-f85d30c484f26c0656dd91ad5f9c5ed26c0a2fce.tar.gz opencode-f85d30c484f26c0656dd91ad5f9c5ed26c0a2fce.zip | |
wip: plugins
Diffstat (limited to 'packages/web/src/content/docs')
| -rw-r--r-- | packages/web/src/content/docs/docs/plugins.mdx | 252 |
1 files changed, 17 insertions, 235 deletions
diff --git a/packages/web/src/content/docs/docs/plugins.mdx b/packages/web/src/content/docs/docs/plugins.mdx index a9b849fc6..bee2785f0 100644 --- a/packages/web/src/content/docs/docs/plugins.mdx +++ b/packages/web/src/content/docs/docs/plugins.mdx @@ -7,31 +7,16 @@ Plugins allow you to extend opencode's functionality by hooking into various eve --- -## Configuration - -Plugins are configured in your `opencode.json` file using the `plugin` array. Each entry should be a path to a plugin module. - -```json title="opencode.json" -{ - "$schema": "https://opencode.ai/config.json", - "plugin": ["./my-plugin.js", "../shared/company-plugin.js", "/absolute/path/to/plugin.js"] -} -``` - -Paths can be: - -- **Relative paths** - Resolved from the directory containing the config file -- **Absolute paths** - Used as-is - ---- - ## Creating a Plugin -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. +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. +They are loaded from the `.opencode/plugin` directory either in your proejct or +globally in `~/.config/opencode/plugin`. ### Basic Structure -```typescript title="my-plugin.js" +```typescript title=".opencode/plugin/example.js" export const MyPlugin = async ({ app, client, $ }) => { console.log("Plugin initialized!") @@ -63,52 +48,18 @@ export const MyPlugin: Plugin = async ({ app, client, $ }) => { --- -## Available Hooks - -Plugins can implement various hooks to respond to opencode events: - -### permission - -Control permissions for various operations: - -```javascript -export const SecurityPlugin = async ({ client }) => { - return { - permission: { - // Add permission logic here - }, - } -} -``` - -### event - -Listen to all events in the opencode system: - -```javascript -export const LoggingPlugin = async ({ client }) => { - return { - event: ({ event }) => { - console.log("Event occurred:", event) - }, - } -} -``` - ---- - ## Examples ### Notification Plugin Send notifications when certain events occur: -```javascript title="notification-plugin.js" +```javascript title=".opencode/plugin/notification.js" export const NotificationPlugin = async ({ client, $ }) => { return { event: async ({ event }) => { // Send notification on session completion - if (event.type === "session.completed") { + if (event.type === "session.idle") { await $`osascript -e 'display notification "Session completed!" with title "opencode"'` } }, @@ -116,191 +67,22 @@ export const NotificationPlugin = async ({ client, $ }) => { } ``` -### Custom Commands Plugin - -Add custom functionality that can be triggered by the AI: - -```javascript title="custom-commands.js" -export const CustomCommands = async ({ client }) => { - return { - event: async ({ event }) => { - if (event.type === "message" && event.content.includes("/deploy")) { - // Trigger deployment logic - console.log("Deploying application...") - } - }, - } -} -``` - -### Integration Plugin +### .env Protection Integrate with external services: -```javascript title="slack-integration.js" -export const SlackIntegration = async ({ client, $ }) => { - const webhookUrl = process.env.SLACK_WEBHOOK_URL - +```javascript title=".opencode/plugin/slack.js" +export const EnvProtection = async ({ client, $ }) => { return { - event: async ({ event }) => { - if (event.type === "error") { - // Send error to Slack - await fetch(webhookUrl, { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ - text: `opencode error: ${event.message}`, - }), - }) - } - }, - } -} -``` - ---- - -## Plugin Development Tips - -1. **Error Handling**: Always handle errors gracefully to avoid crashing opencode - - ```javascript - event: async ({ event }) => { - try { - // Your logic here - } catch (error) { - console.error("Plugin error:", error) - } - } - ``` - -2. **Performance**: Keep plugin operations lightweight and async where possible - - ```javascript - event: async ({ event }) => { - // Don't block - use async operations - setImmediate(() => { - // Heavy processing here - }) - } - ``` - -3. **Environment Variables**: Use environment variables for configuration - - ```javascript - const apiKey = process.env.MY_PLUGIN_API_KEY - if (!apiKey) { - console.warn("MY_PLUGIN_API_KEY not set") - return {} - } - ``` - -4. **Multiple Exports**: You can export multiple plugins from one file - ```javascript - export const PluginOne = async (context) => { - /* ... */ - } - export const PluginTwo = async (context) => { - /* ... */ - } - ``` - ---- - -## Advanced Usage - -### Using the SDK Client - -The `client` parameter is a full opencode SDK client that can interact with the AI: - -```javascript -export const AIAssistantPlugin = async ({ client }) => { - return { - event: async ({ event }) => { - if (event.type === "file.created") { - // Ask AI to review the new file - const response = await client.messages.create({ - messages: [ - { - role: "user", - content: `Review this new file: ${event.path}`, - }, - ], - }) - console.log("AI Review:", response) - } - }, - } -} -``` - -### Accessing Application State - -The `app` parameter provides access to the opencode application instance: - -```javascript -export const StatePlugin = async ({ app }) => { - return { - event: async ({ event }) => { - // Access application state and configuration - const currentPath = app.path.cwd - console.log("Working directory:", currentPath) - }, - } -} -``` - ---- - -## Debugging Plugins - -To debug your plugins: - -1. **Console Logging**: Use `console.log()` to output debug information -2. **Error Boundaries**: Wrap hook implementations in try-catch blocks -3. **Development Mode**: Test plugins in a separate opencode instance first - -```javascript -export const DebugPlugin = async (context) => { - console.log("Plugin loaded with context:", Object.keys(context)) - - return { - event: ({ event }) => { - console.log(`[${new Date().toISOString()}] Event:`, event.type) - }, - } -} -``` - ---- - -## Best Practices - -1. **Namespace Your Plugins**: Use descriptive names to avoid conflicts -2. **Document Your Hooks**: Add comments explaining what each hook does -3. **Version Control**: Keep plugins in version control with your project -4. **Test Thoroughly**: Test plugins with various opencode operations -5. **Handle Cleanup**: Clean up resources when appropriate - -```javascript -// Good example with best practices -export const CompanyStandardsPlugin = async ({ client, $ }) => { - // Initialize resources - const config = await loadConfig() - - return { - event: async ({ event }) => { - try { - // Well-documented hook logic - if (event.type === "code.generated") { - // Enforce company coding standards - await enforceStandards(event.code) + tool: { + execute: { + before: async (input, output) => { + if (input.tool === "read" && output.args.filePath.includes(".env")) { + throw new Error("Do not read .env files") + } } - } catch (error) { - // Graceful error handling - console.error("Standards check failed:", error) } - }, + } } } ``` |
