Skip to main content
Skip to 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 plugin por sessão

--plugin-dir é um argumento de inicialização, portanto fixa um conjunto de plugins para o processo da CLI e para cada sessão criada com base nele. Quando as sessões precisarem de conjuntos de plug-ins diferentes, ou quando o SDK estiver conectado a um runtime que ele não iniciou, passe os diretórios na configuração da sessão. Eles trafegam nas session.resumecargas úteissession.create por JSON-RPC, em vez de como argumentos de processo, de modo que cheguem a um runtime externo da mesma forma que a opção de inicialização.

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

const client = new CopilotClient();
await client.start();

const session = await client.createSession({
  pluginDirectories: ["./plugins/code-reviewer"],
});

Caminhos relativos são resolvidos com base em workingDirectory, ou no diretório de trabalho do runtime quando ele não estiver definido, por isso caminhos absolutos são recomendados. As entradas que não podem ser resolvidas são registradas em log e puladas, em vez de fazer com que a criação da sessão falhe. A opção é uma aceitação explícita, o que significa que agentes de plug-in e regras são carregados mesmo quando enableConfigDiscovery é falso. Os ativos carregados dessa forma ficam entre fontes de projeto e fontes pessoais ou domésticas na ordem de precedência de toda a sessão.

A opção equivalente em cada SDK é:

SDKOpção de sessão
Node.js/TypeScriptpluginDirectories: string[]
Pythonplugin_directories=[...]
GoPluginDirectories: []string{...}
.NETPluginDirectories = [...]
Java.setPluginDirectories(List.of(...))
Rust.with_plugin_directories([...])

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.