Salta ai contenuti

Plugin

Scrivere plugin personalizzati per estendere OpenCode.

I plugin ti permettono di estendere OpenCode agganciandoti a vari eventi e personalizzandone il comportamento. Puoi creare plugin per aggiungere funzionalità, integrarti con servizi esterni o modificare il comportamento predefinito.

Per esempi, vedi i plugin della community.


Utilizzare un plugin

Ci sono due modi principali per caricare i plugin.


Da file locali

Metti file JavaScript o TypeScript nella directory dei plugin:

  • .opencode/plugin/ – plugin a livello di progetto
  • ~/.config/opencode/plugin/ – plugin globali

I file in queste directory vengono caricati automaticamente all’avvio.


Da npm

Dichiarali nella configurazione:

opencode.json
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["opencode-helicone-session", "opencode-wakatime", "@my-org/custom-plugin"]
}

Sono supportati sia pacchetti normali sia con scope.

Puoi esplorare i plugin disponibili nella sezione ecosistema.


Come vengono installati i plugin

  • I plugin npm vengono installati automaticamente tramite Bun all’avvio. Pacchetti e dipendenze sono memorizzati in cache in ~/.cache/opencode/node_modules/.
  • I plugin locali vengono caricati direttamente dalla directory dei plugin. Se hanno bisogno di dipendenze esterne, crea un package.json nella directory di configurazione (vedi Dipendenze) oppure pubblicali su npm e aggiungili alla config.

Ordine di caricamento

I plugin vengono caricati da tutte le sorgenti e i loro hook vengono eseguiti in sequenza. L’ordine è:

  1. Config globale (~/.config/opencode/opencode.json)
  2. Config del progetto (opencode.json)
  3. Directory globale dei plugin (~/.config/opencode/plugin/)
  4. Directory dei plugin del progetto (.opencode/plugin/)

I pacchetti npm con stesso nome e versione vengono caricati una sola volta. Un plugin locale e uno npm con nomi simili invece vengono caricati separatamente.


Creare un plugin

Un plugin è un modulo JavaScript/TypeScript che esporta una o più funzioni di plugin. Ogni funzione riceve un oggetto contesto e restituisce un oggetto di hook.


Dipendenze

I plugin locali e i tools personalizzati possono usare dipendenze npm esterne. Aggiungi un package.json alla directory di configurazione:

.opencode/package.json
{
"dependencies": {
"shescape": "^2.1.0"
}
}

OpenCode eseguirà bun install all’avvio per installarle. A quel punto potrai importarle nei tuoi plugin o tool.

.opencode/plugin/my-plugin.ts
import { escape } from "shescape"
export const MyPlugin = async (ctx) => {
return {
"tool.execute.before": async (input, output) => {
if (input.tool === "bash") {
output.args.command = escape(output.args.command)
}
},
}
}

Struttura di base

.opencode/plugin/example.js
export const MyPlugin = async ({ project, client, $, directory, worktree }) => {
console.log("Plugin initialized!")
return {
// Implementazioni degli hook qui
}
}

Il plugin riceve:

  • project: informazioni sul progetto corrente
  • directory: directory di lavoro corrente
  • worktree: path del worktree Git
  • client: client SDK di OpenCode per interagire con il server
  • $: API di shell di Bun (shell API) per eseguire comandi

Supporto TypeScript

Per plugin in TypeScript puoi importare i tipi dal pacchetto dei plugin:

my-plugin.ts
import type { Plugin } from "@opencode-ai/plugin"
export const MyPlugin: Plugin = async ({ project, client, $, directory, worktree }) => {
return {
// Implementazioni di hook type-safe
}
}

Eventi

I plugin possono iscriversi a eventi (vedi gli esempi più sotto). Ecco l’elenco degli eventi disponibili.

Eventi di comando

  • command.executed

Eventi di file

  • file.edited
  • file.watcher.updated

Eventi di installazione

  • installation.updated

Eventi LSP

  • lsp.client.diagnostics
  • lsp.updated

Eventi di messaggio

  • message.part.removed
  • message.part.updated
  • message.removed
  • message.updated

Eventi di permesso

  • permission.replied
  • permission.updated

Eventi di server

  • server.connected

Eventi di sessione

  • session.created
  • session.compacted
  • session.deleted
  • session.diff
  • session.error
  • session.idle
  • session.status
  • session.updated

Eventi TODO

  • todo.updated

Eventi di tool

  • tool.execute.after
  • tool.execute.before

Eventi TUI

  • tui.prompt.append
  • tui.command.execute
  • tui.toast.show

Esempi

Alcuni esempi di plugin per estendere OpenCode.


Notifiche

Inviare notifiche quando si verificano determinati eventi:

.opencode/plugin/notification.js
export const NotificationPlugin = async ({ project, client, $, directory, worktree }) => {
return {
event: async ({ event }) => {
// Notifica al termine di una sessione
if (event.type === "session.idle") {
await $`osascript -e 'display notification "Session completed!" with title "opencode"'`
}
},
}
}

Qui usiamo osascript per eseguire AppleScript su macOS e mostrare notifiche.


Protezione .env

Impedire a OpenCode di leggere i file .env:

.opencode/plugin/env-protection.js
export const EnvProtection = async ({ project, client, $, directory, worktree }) => {
return {
"tool.execute.before": async (input, output) => {
if (input.tool === "read" && output.args.filePath.includes(".env")) {
throw new Error("Do not read .env files")
}
},
}
}

Tools personalizzati

I plugin possono anche registrare strumenti personalizzati:

.opencode/plugin/custom-tools.ts
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}!`
},
}),
},
}
}

L’helper tool crea uno strumento che OpenCode può invocare. Prende uno schema Zod e restituisce una definizione con:

  • description: che cosa fa lo strumento;
  • args: schema degli argomenti;
  • execute: funzione eseguita quando lo strumento viene chiamato.

I tuoi strumenti personalizzati saranno disponibili insieme a quelli integrati.


Logging strutturato

Usa client.app.log() al posto di console.log per log strutturati:

.opencode/plugin/my-plugin.ts
export const MyPlugin = async ({ client }) => {
await client.app.log({
service: "my-plugin",
level: "info",
message: "Plugin initialized",
extra: { foo: "bar" },
})
}

Livelli: debug, info, warn, error. Vedi la documentazione SDK per maggiori dettagli.


Hook di compattazione

Personalizzare il contesto incluso quando una sessione viene compattata:

.opencode/plugin/compaction.ts
import type { Plugin } from "@opencode-ai/plugin"
export const CompactionPlugin: Plugin = async (ctx) => {
return {
"experimental.session.compacting": async (input, output) => {
// Iniettare contesto aggiuntivo nel prompt di compattazione
output.context.push(`
## Custom Context
Include any state that should persist across compaction:
- Current task status
- Important decisions made
- Files being actively worked on
`)
},
}
}

L’hook experimental.session.compacting viene eseguito prima che il modello generi il riassunto di continuazione. Usalo per iniettare contesto di dominio che il prompt di default non catturerebbe.

Puoi anche sostituire completamente il prompt di compattazione impostando output.prompt:

.opencode/plugin/custom-compaction.ts
import type { Plugin } from "@opencode-ai/plugin"
export const CustomCompactionPlugin: Plugin = async (ctx) => {
return {
"experimental.session.compacting": async (input, output) => {
// Sostituire interamente il prompt di compattazione
output.prompt = `
You are generating a continuation prompt for a multi-agent swarm session.
Summarize:
1. The current task and its status
2. Which files are being modified and by whom
3. Any blockers or dependencies between agents
4. The next steps to complete the work
Format as a structured prompt that a new agent can use to resume work.
`
},
}
}

Se output.prompt è impostato, output.context viene ignorato e viene utilizzato solo il prompt personalizzato.