Hooks no coração
do runtime.
Plugins são módulos JS/TS que escutam eventos e interceptam comportamento: bloquear uma leitura, injetar variáveis, adicionar ferramentas, notificar sistemas externos. Carregados por diretório ou por npm.
01Usando
| Fonte | Como |
|---|---|
| Arquivos locais | .maxvision-code/plugins/ (projeto) · ~/.config/<dir>/plugins/ (global) — carregados na inicialização. |
| npm | "plugin": ["opencode-helicone-session", "@my-org/custom"] na config; instalados com Bun e cacheados. |
| CLI | mvcode plugin <módulo> instala e grava na config (-g global). |
Ordem de carga: config global → config do projeto → diretório global → diretório do projeto. Todos os hooks rodam em sequência. O diálogo de plugins do app adiciona e remove specs da config. Implementado Depuração: mvcode --pure roda sem plugins externos.
02Anatomia
import type { Plugin } from "@maxvision/plugin" export const MeuPlugin: Plugin = async ({ project, client, $, directory, worktree }) => { return { // hooks aqui } }
O contexto entrega: project, directory, worktree, client (o SDK conectado à instância) e $ (o shell do Bun). Dependências externas? Um package.json em .maxvision-code/ é instalado na inicialização.
03Eventos
| Família | Eventos |
|---|---|
| Sessão | session.created · idle · error · status · compacted · diff · deleted · updated |
| Mensagens | message.updated · removed · part.updated · part.removed |
| Ferramentas | tool.execute.before · tool.execute.after |
| Permissões | permission.asked · replied |
| Arquivos e LSP | file.edited · file.watcher.updated · lsp.client.diagnostics |
| Shell e TUI | shell.env · tui.prompt.append · tui.command.execute · tui.toast.show |
04Receitas
Proteger .env
export const EnvProtection = async () => ({ "tool.execute.before": async (input, output) => { if (input.tool === "read" && output.args.filePath.includes(".env")) throw new Error("Não leia arquivos .env") } })
Injetar ambiente em todo shell
export const InjectEnv = async () => ({ "shell.env": async (input, output) => { output.env.PROJECT_ROOT = input.cwd } })
Notificar quando a sessão termina
export const Notify = async ({ $ }) => ({ event: async ({ event }) => { if (event.type === "session.idle") await $`osascript -e 'display notification "Sessão concluída" with title "MVCode"'` } })
Adicionar ferramentas
Plugins também registram ferramentas pelo hook tool — mesmo helper tool(), mesma precedência (plugin vence built-in de mesmo nome).
05Boas práticas
- Log estruturado com
client.app.log()em vez deconsole.log— níveis debug/info/warn/error. - Hooks
beforepodem lançar erro para vetar a ação — é o mecanismo de veto, use com mensagens claras. - Nomeie exports de forma única; cada export do módulo é um plugin.
- Config com opts por tuple (
[spec, opts]) está Planejado na UI — por config já funciona.
