Menu
3/9 ManifestoTodas as páginas

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 é:

ade.plugin.json
{
  "id": "meu-plugin",
  "name": "Meu Plugin",
  "version": "0.1.0",
  "contributes": {}
}

Campos da raiz

Campos da raiz do ade.plugin.json
CampoTipoObrigatórioRegra
idstringsimkebab-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.
namestringsimNome exibido. Pelo menos 1 caractere.
versionstringsimsemver: major.minor.patch, com pré-release (-beta.1) e build (+sha.5114f85) opcionais. 1.0 é recusado.
descriptionstringnãoTexto livre.
authorstringnãoTexto livre.
homepagestringnãoTexto livre — o schema não exige que seja uma URL.
licensestringnãoTexto livre (ex.: MIT).
adeVersionstringnãoTexto livre. Apenas documental na v1: o app não confere a versão.
contributesobjectsimO objeto das contribuições. Obrigatório, mas pode ser {}.

contributes.agents

Um array; um agente por entrada.

Campos de contributes.agents[]
CampoTipoObrigatórioRegra
agentIdstringsimIdentificador do agente.
namestringsimNome exibido.
adapter"claude" | "codex" | "gemini" | "shell" | "browser"simO mesmo conjunto de adapters que os panes do app já usam.
modelstringnãoModelo (ex.: sonnet).
effort"low" | "medium" | "high"nãoNível de esforço.
systemPromptstringnãoSystem prompt do agente.
bestForstring[]nãoQuando usar este agente.
contributes.agents
[
  {
    "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

Campos de contributes.skills[]
CampoTipoObrigatórioRegra
pathstringsimCaminho 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.
contributes.skills
[{ "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.

Campos de cada entrada de contributes.mcpServers
CampoTipoObrigatórioRegra
commandstringsimExecutável do servidor MCP.
argsstring[]nãoArgumentos.
envRecord<string, string>nãoVariáveis de ambiente extras.
contributes.mcpServers
{
  "hello-echo": {
    "command": "npx",
    "args": ["-y", "@modelcontextprotocol/server-everything"],
    "env": {}
  }
}

contributes.themes

Campos de contributes.themes[]
CampoTipoObrigatórioRegra
idstringsimIdentificador do tema.
namestringsimNome exibido.
pathstringsimCaminho relativo à raiz do plugin, para o arquivo CSS do tema.
contributes.themes
[{ "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.

Campos de contributes.settings[]
CampoTipoObrigatórioRegra
keystringsimIdentificador: /^[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.
labelstringsimRótulo do campo. Pelo menos 1 caractere.
type"string" | "secret" | "boolean" | "number"simSó escolhe o widget: texto, senha com mostrar/ocultar, checkbox, entrada numérica.
requiredbooleannãoSe true e o valor (já com o default) estiver vazio, o sidecar não inicia e a integração fica em missing_settings.
descriptionstringnãoAjuda exibida abaixo do rótulo.
placeholderstringnãoExemplo mostrado no campo vazio.
defaultstringnãoSempre uma string, mesmo para boolean ("false") e number ("30").
contributes.settings
[
  {
    "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).

Campos de contributes.integrations[]
CampoTipoObrigatórioRegra
idstringsimkebab-case (mesma regex do id do plugin). Chega ao sidecar como ADE_PLUGIN_INTEGRATION_ID e compõe a pasta de dados.
namestringsimNome exibido. Pelo menos 1 caractere.
descriptionstringnãoDescrição curta.
commandstringsimExecutável (ex.: node). Pelo menos 1 caractere. Iniciado direto, sem shell, com o diretório da pasta instalada como cwd; precisa estar no PATH.
argsstring[]nãoArgumentos — caminhos relativos à pasta do plugin.
envRecord<string, string>nãoVariáveis extras. As variáveis ADE_* do app são aplicadas por cima.
eventsstring[]nãoFiltro de eventos: nome exato (board.card_moved) ou prefixo (board.*). Ausente ou vazio = todos os eventos.
contributes.integrations
[
  {
    "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"]
  }
]
Como o filtro events decide
eventsEventoChega?
(ausente) ou []qualquersim
["board.*"]board.card_movedsim
["board.*"]mission.creatednão
["mission.created"]mission.createdsim
["mission.created"]mission.renamednã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

ade.plugin.json (inválido)
{
  "id": "Meu_Plugin",
  "name": "Meu Plugin",
  "version": "0.1.0",
  "contributes": {}
}

Mensagem: plugin id must be kebab-case

version fora de semver

ade.plugin.json (inválido)
{
  "id": "meu-plugin",
  "name": "Meu Plugin",
  "version": "1.0",
  "contributes": {}
}

Mensagem: plugin version must be semver

key de setting que não é um identificador

ade.plugin.json (inválido)
{
  "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

ade.plugin.json (inválido)
{
  "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

ade.plugin.json (inválido)
{
  "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.json na raiz, o erro é PLUGIN_MANIFEST_NOT_FOUND.