Tutoriais · Plugins
Referência do manifesto ade.plugin.json
Todos os campos do ade.plugin.json, com o que é obrigatório, as restrições de cada um e os erros que o instalador devolve.
Nesta página
Visão geral
O ade.plugin.json fica na raiz do plugin e é validado com o schema abaixo antes de qualquer cópia. O menor manifesto válido é:
{
"id": "meu-plugin",
"name": "Meu Plugin",
"version": "0.1.0",
"contributes": {}
}Campos da raiz
| Campo | Tipo | Obrigatório | Regra |
|---|---|---|---|
| id | string | sim | kebab-case: /^[a-z0-9]+(-[a-z0-9]+)*$/ — minúsculas e números separados por um único hífen. Vira o nome da pasta instalada (userData/plugins/<id>) e a identidade do plugin: reimportar o mesmo id substitui o anterior. |
| name | string | sim | Nome exibido. Pelo menos 1 caractere. |
| version | string | sim | semver: major.minor.patch, com pré-release (-beta.1) e build (+sha.5114f85) opcionais. 1.0 é recusado. |
| description | string | não | Texto livre. |
| author | string | não | Texto livre. |
| homepage | string | não | Texto livre — o schema não exige que seja uma URL. |
| license | string | não | Texto livre (ex.: MIT). |
| adeVersion | string | não | Texto livre. Apenas documental na v1: o app não confere a versão. |
| contributes | object | sim | O objeto das contribuições. Obrigatório, mas pode ser {}. |
contributes.agents
Um array; um agente por entrada.
| Campo | Tipo | Obrigatório | Regra |
|---|---|---|---|
| agentId | string | sim | Identificador do agente. |
| name | string | sim | Nome exibido. |
| adapter | "claude" | "codex" | "gemini" | "shell" | "browser" | sim | O mesmo conjunto de adapters que os panes do app já usam. |
| model | string | não | Modelo (ex.: sonnet). |
| effort | "low" | "medium" | "high" | não | Nível de esforço. |
| systemPrompt | string | não | System prompt do agente. |
| bestFor | string[] | não | Quando usar este agente. |
[
{
"agentId": "hello-ade-greeter",
"name": "Hello ADE Greeter",
"adapter": "claude",
"model": "sonnet",
"effort": "medium",
"systemPrompt": "You are the Hello ADE Greeter, a minimal example agent.",
"bestFor": ["Verifying a fresh plugin install"]
}
]contributes.skills
| Campo | Tipo | Obrigatório | Regra |
|---|---|---|---|
| path | string | sim | Caminho relativo à raiz do plugin, para uma pasta com um SKILL.md. O schema só confere que é uma string: garanta você mesmo que a pasta existe. |
[{ "path": "skills/hello-ade-starter" }]contributes.mcpServers
Um objeto (não um array): a chave é o nome do servidor e o valor descreve como iniciá-lo. O instalador só valida o formato — nunca executa o comando.
| Campo | Tipo | Obrigatório | Regra |
|---|---|---|---|
| command | string | sim | Executável do servidor MCP. |
| args | string[] | não | Argumentos. |
| env | Record<string, string> | não | Variáveis de ambiente extras. |
{
"hello-echo": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-everything"],
"env": {}
}
}contributes.themes
| Campo | Tipo | Obrigatório | Regra |
|---|---|---|---|
| id | string | sim | Identificador do tema. |
| name | string | sim | Nome exibido. |
| path | string | sim | Caminho relativo à raiz do plugin, para o arquivo CSS do tema. |
[{ "id": "sunset", "name": "Sunset", "path": "themes/sunset.css" }]contributes.settings
Campos que o usuário preenche na tela do plugin. Os tipos possíveis são somente quatro: não existe select, lista, botão ou ação. O uso, a entrega ao sidecar e o padrão “faça agora” estão em configurações e segredos.
| Campo | Tipo | Obrigatório | Regra |
|---|---|---|---|
| key | string | sim | Identificador: /^[a-zA-Z][a-zA-Z0-9_]*$/ — começa com letra; só letras, números e _. api-key é recusado; use apiKey ou api_key. É a chave no objeto que o sidecar recebe. |
| label | string | sim | Rótulo do campo. Pelo menos 1 caractere. |
| type | "string" | "secret" | "boolean" | "number" | sim | Só escolhe o widget: texto, senha com mostrar/ocultar, checkbox, entrada numérica. |
| required | boolean | não | Se true e o valor (já com o default) estiver vazio, o sidecar não inicia e a integração fica em missing_settings. |
| description | string | não | Ajuda exibida abaixo do rótulo. |
| placeholder | string | não | Exemplo mostrado no campo vazio. |
| default | string | não | Sempre uma string, mesmo para boolean ("false") e number ("30"). |
[
{
"key": "apiKey",
"label": "API key",
"type": "secret",
"required": true,
"description": "Chave de API do serviço.",
"placeholder": "pk_..."
},
{
"key": "workspaceId",
"label": "Workspace",
"type": "string",
"description": "Deixe vazio para detectar automaticamente."
},
{
"key": "verbose",
"label": "Log detalhado",
"type": "boolean",
"default": "false"
},
{
"key": "timeoutSeconds",
"label": "Timeout (segundos)",
"type": "number",
"default": "30"
}
]contributes.integrations
Cada entrada declara um sidecar — um processo filho que o app inicia (nunca código dentro do app).
| Campo | Tipo | Obrigatório | Regra |
|---|---|---|---|
| id | string | sim | kebab-case (mesma regex do id do plugin). Chega ao sidecar como ADE_PLUGIN_INTEGRATION_ID e compõe a pasta de dados. |
| name | string | sim | Nome exibido. Pelo menos 1 caractere. |
| description | string | não | Descrição curta. |
| command | string | sim | Executável (ex.: node). Pelo menos 1 caractere. Iniciado direto, sem shell, com o diretório da pasta instalada como cwd; precisa estar no PATH. |
| args | string[] | não | Argumentos — caminhos relativos à pasta do plugin. |
| env | Record<string, string> | não | Variáveis extras. As variáveis ADE_* do app são aplicadas por cima. |
| events | string[] | não | Filtro de eventos: nome exato (board.card_moved) ou prefixo (board.*). Ausente ou vazio = todos os eventos. |
[
{
"id": "sync-service",
"name": "Sync Service",
"description": "Espelha o kanban em um serviço externo.",
"command": "node",
"args": ["integrations/sync.mjs"],
"env": { "LOG_LEVEL": "info" },
"events": ["board.*", "mission.created"]
}
]| events | Evento | Chega? |
|---|---|---|
| (ausente) ou [] | qualquer | sim |
| ["board.*"] | board.card_moved | sim |
| ["board.*"] | mission.created | não |
| ["mission.created"] | mission.created | sim |
| ["mission.created"] | mission.renamed | não |
hello e shutdown são linhas de ciclo de vida e chegam sempre, com qualquer filtro.
Erros de validação
Um manifesto inválido é recusado com o código PLUGIN_INVALID_MANIFEST e a mensagem manifesto inválido: <primeiro problema>. As regras com mensagem própria:
id fora de kebab-case
{
"id": "Meu_Plugin",
"name": "Meu Plugin",
"version": "0.1.0",
"contributes": {}
}Mensagem: plugin id must be kebab-case
version fora de semver
{
"id": "meu-plugin",
"name": "Meu Plugin",
"version": "1.0",
"contributes": {}
}Mensagem: plugin version must be semver
key de setting que não é um identificador
{
"id": "meu-plugin",
"name": "Meu Plugin",
"version": "0.1.0",
"contributes": {
"settings": [{ "key": "api-key", "label": "API key", "type": "secret" }]
}
}Mensagem: setting key must be an identifier
id de integração fora de kebab-case
{
"id": "meu-plugin",
"name": "Meu Plugin",
"version": "0.1.0",
"contributes": {
"integrations": [{ "id": "Echo", "name": "Echo", "command": "node" }]
}
}Mensagem: integration id must be kebab-case
Tipo de setting inexistente
{
"id": "meu-plugin",
"name": "Meu Plugin",
"version": "0.1.0",
"contributes": {
"settings": [{ "key": "mode", "label": "Modo", "type": "select" }]
}
}select não é um tipo válido — o enum é string | secret | boolean | number. Para “escolher uma opção”, use uma configuração string e valide o valor no sidecar.
- Um arquivo que não é JSON também dá
PLUGIN_INVALID_MANIFEST. - Sem
ade.plugin.jsonna raiz, o erro éPLUGIN_MANIFEST_NOT_FOUND.