Skip to main content

Diretórios de plug-in

Um plug-in é um diretório que agrupa extensões do SDK — habilidades, ganchos, servidores MCP, agentes personalizados e configuração de LSP — por trás de um único manifesto. Apontar o SDK para um diretório de plug-ins carrega tudo o que os plug-ins fornecem, para que você possa disponibilizar pacotes reutilizáveis de recursos sem precisar escrever a integração específica de cada extensão em cada aplicação host.

Este guia explica o layout da pasta do plug-in, como carregar um plug-in de um diretório, quando usar diretórios de plug-in versus registrar extensões individuais e como tornar os conjuntos de plug-in determinísticos.

Quando usar diretórios de plug-in

Use um diretório de plug-in quando quiser:

  • Distribua um pacote de capacidades como uma única unidade — por exemplo, um pacote "revisor TypeScript" com uma habilidade, um preToolUse hook que aplica a verificação de lint e um agente personalizado que executa o revisor.
  • A funcionalidade do fornecedor é empacotada em um repositório para que cada clone do aplicativo host carregue as mesmas extensões deterministicamente.
  • Desenvolva um plug-in localmente antes de publicá-lo em um marketplace.
  • Substitua ou estenda um plug-in instalado no marketplace com um check-out local para teste.

Se você precisar adicionar apenas um servidor MCP, um único gancho ou um único agente personalizado, você poderá registrá-lo embutido por meio da configuração do SDK (mcpServers, hooks, customAgents). Os diretórios de plug-in são mais úteis quando você tem três ou mais extensões relacionadas que são enviadas juntas.

Estrutura da pasta do plugin

A CLI do Copilot verifica cada diretório de plug-in para um manifesto plugin.json ou um SKILL.md de nível raiz. Um plug-in mínimo tem esta aparência:

my-plugin/
├── plugin.json              # manifest (required unless using SKILL.md only)
├── SKILL.md                 # optional: top-level skill
├── hooks.json               # optional: hooks config
├── .mcp.json                # optional: MCP server config
├── agents/                  # optional: custom agents (one .md file per agent)
│   └── code-reviewer.md
└── skills/                  # optional: additional skills
    └── lint-fix/
        └── SKILL.md

O manifesto também pode ficar em .github/plugin.json ou .github/plugin/plugin.json, para que os plug-ins possam ficar dentro de um repositório existente sem alterar sua estrutura raiz. Cada subsistema (ganchos, MCP, LSP, habilidades, agentes) tem seu próprio carregador e é opcional – um plug-in só precisa das partes que ele contribui.

Para obter o esquema de manifesto completo, consulte a documentação de runtime referenciada no comando de barra da /plugin CLI.

Carregando um diretório de plug-in do SDK

Os diretórios de plug-in são carregados passando --plugin-dir <path> para a CLI do Copilot quando o SDK o gera. Cada idioma expõe isso por meio da opção extra-args da conexão de runtime. A flag pode ser repetida para carregar vários plugins.

Idiomas de código navigation

TypeScript
import { CopilotClient, RuntimeConnection } from "@github/copilot-sdk";

const client = new CopilotClient({
  connection: RuntimeConnection.forStdio({
    args: [
      "--plugin-dir", "./plugins/code-reviewer",
      "--plugin-dir", "./plugins/lint-fix",
    ],
  }),
});

await client.start();

O exemplo acima usa uma conexão de runtime stdio – o padrão quando o SDK agrupa a CLI. Se você se conectar a um runtime externo via uma URL (forUri / ForUri), passe --plugin-dir para o servidor CLI de longa duração ao iniciá-lo; o SDK não encaminha --plugin-dir para runtimes que ele não iniciou.

Diretórios de plug-in em pacote de host confiáveis

Os aplicativos que enviam seus próprios plug-ins confiáveis podem registrá-los como uma opção de inicialização do cliente. O SDK envia o conjunto ordenado completo após se conectar e verificar o protocolo, antes que start retorne ou que qualquer sessão possa ser criada. Os caminhos devem ser absolutos; deixar a opção não definida ou vazia não realiza nenhuma chamada RPC.

A opção equivalente em cada SDK é:

SDKOpção de inicialização
Node.js/TypeScriptbuiltinPluginDirectories: string[]
Pythonbuiltin_plugin_directories=[...]
GoBuiltinPluginDirectories: []string{...}
.NETBuiltinPluginDirectories = [...]
Java.setBuiltinPluginDirectories(List.of(Path.of(...)))
Rust.with_builtin_plugin_directories([...])

Esse é um limite de confiança para plug-ins agrupados e controlados pelo aplicativo host. É diferente de --plugin-dir, que é um argumento de inicialização de processo da CLI para carregar explicitamente diretórios comuns de plug-ins. A opção de inicialização também funciona ao se conectar a um runtime existente porque é enviada por JSON-RPC em vez de encaminhada como um argumento de processo.

O que um plug-in pode contribuir

Carregar um diretório de plug-in torna suas extensões visíveis para cada sessão criada pelo cliente. O tempo de execução mescla as extensões fornecidas pelo plug-in com tudo o que você registra diretamente no código:

O plugin contribuiVisível para a sessão como
Habilidades (SKILL.md, skills/*/SKILL.md)Itens no session.skills.list(); passíveis de injeção por nome
Agentes personalizados (agents/*.md)Pode ser enviado pela ferramenta task(agent_type=...)
Ganchos (hooks.json)Acionado junto com ganchos registrados por meio do SDK
Servidores MCP (.mcp.json)Ferramentas e recursos acessíveis por meio de session.mcp.*
Servidores LSP (.lsp.json)Inicializado por meio de session.lsp.initialize(...)

Os agentes de plugin são subagentes de primeira classe em Modo de frota: um agente pai pode despachá-los por agent_type, e o ambiente de execução dispara os hooks subagentStart / subagentStop para eles como faz com qualquer outro subagente.

Plug-ins do diretório vs plug-ins do marketplace

O ambiente de execução tem duas maneiras de instalar plug-ins, e ambas acabam parecendo iguais para uma sessão:

  • Os plugins do Marketplace / de repositório direto são instalados de forma persistente por meio do comando de barra da /plugin CLI ou da installedPlugins configuração de usuário subjacente. Eles são globais — toda sessão executada com a mesma configuração de usuário consegue vê-los, e eles participam das regras de descoberta de plug-ins.
  • --plugin-dir os plug-ins são explícitos e efêmeros – eles se aplicam apenas ao processo da CLI que você iniciou com esse sinalizador. Eles têm precedência sobre a descoberta no ambiente e são desduplicados em relação às entradas do marketplace com o mesmo caminho de cache, de modo que o mesmo plug-in não seja carregado duas vezes quando ambas as origens fizerem referência a ele.

Para aplicativos baseados em SDK, --plugin-dir geralmente é a escolha certa: mantém o conjunto de plug-ins sob o controle da sua aplicação, em vez de depender do estado do usuário em cada máquina.

Tornando os conjuntos de plug-in determinísticos

Quando a máquina host puder ter outros plug-ins instalados (do marketplace ou personalizados), defina COPILOT_PLUGIN_DIR_ONLY=true no ambiente de execução para suprimir a descoberta automática de plug-ins. Somente os diretórios que você informar por meio de --plugin-dir serão carregados.

Node.js/TypeScript
process.env.COPILOT_PLUGIN_DIR_ONLY = "true";

const client = new CopilotClient({
  connection: RuntimeConnection.forStdio({
    args: ["--plugin-dir", "./plugins/code-reviewer"],
  }),
});
await client.start();

Use isso em CI, em implantações de servidor sem cabeça e em qualquer lugar que você queira um conjunto de plug-in reproduzível que não dependa da configuração do usuário do host.

Inspecionando quais plug-ins foram carregados

Depois que uma sessão for criada, liste os plug-ins ativos para confirmar se um diretório foi selecionado corretamente:

Node.js/TypeScript
const plugins = await session.rpc.plugins.list();
for (const plugin of plugins.plugins) {
  console.log(`${plugin.name} (${plugin.enabled ? "enabled" : "disabled"})`);
}

Plugins carregados via --plugin-dir aparecem nesta lista com o caminho do cache definido como o diretório que você forneceu. As instalações do Marketplace são marcadas com seu registro de origem.

Troubleshooting

  • "nenhum plugin.json ou SKILL.md encontrado no <dir>" – o diretório existe, mas não se qualifica como um plug-in. Adicione um plugin.json manifesto na raiz (ou abaixo .github/) ou inclua um nível SKILL.mdsuperior.
  • Plugin carregado, mas agentes/habilidades não estão visíveis — verifique se o manifesto do plugin declara os agentes/habilidades que ele fornece ou use o layout implícito (agents/*.md, skills/*/SKILL.md). Em seguida, chame session.rpc.skills.reload() para pegar as alterações sem reiniciar.
  • Hooks executados em duplicidade — o runtime elimina duplicatas por cache_path, mas somente quando o mesmo diretório é referenciado tanto como uma instalação via marketplace quanto como um --plugin-dir. Se dois diretórios diferentes contiverem o mesmo plug-in, ambos serão carregados. Remova um ou use COPILOT_PLUGIN_DIR_ONLY=true.
  • --plugin-dir ignorado ao se conectar a um runtime externo – o SDK só encaminha args extras quando gera a própria CLI. Para runtimes externos (forUri/ForUri), passe --plugin-dir na linha de comando que inicia o servidor de runtime.