# 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.

<!-- markdownlint-disable GHD046 GHD005 -->

<!-- Suppressed: GHD046 (outdated release terminology), GHD005 (hardcoded data variable) -->

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:

```text
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.

<div class="ghd-codetabs">
<div class="ghd-codetab" data-lang="typescript" data-label="TypeScript"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">TypeScript</div>

```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();
```

</div>

<div class="ghd-codetab" data-lang="python" data-label="Python"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Python</div>

<!-- docs-validate: wrap-async -->

```python
from copilot import CopilotClient, StdioRuntimeConnection

client = CopilotClient(
    connection=StdioRuntimeConnection(
        args=(
            "--plugin-dir", "./plugins/code-reviewer",
            "--plugin-dir", "./plugins/lint-fix",
        ),
    ),
)
await client.start()
```

</div>

<div class="ghd-codetab" data-lang="go" data-label="Go"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Go</div>

```golang
client := copilot.NewClient(&copilot.ClientOptions{
    Connection: copilot.StdioConnection{
        Args: []string{
            "--plugin-dir", "./plugins/code-reviewer",
            "--plugin-dir", "./plugins/lint-fix",
        },
    },
})
if err := client.Start(ctx); err != nil {
    return err
}
```

</div>

<div class="ghd-codetab" data-lang="dotnet" data-label=".NET"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">.NET</div>

```csharp
using GitHub.Copilot;

await using var client = new CopilotClient(new CopilotClientOptions
{
    Connection = RuntimeConnection.ForStdio(args: new[]
    {
        "--plugin-dir", "./plugins/code-reviewer",
        "--plugin-dir", "./plugins/lint-fix",
    }),
});

await client.StartAsync();
```

</div>

<div class="ghd-codetab" data-lang="java" data-label="Java"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Java</div>

```java
var options = new CopilotClientOptions()
    .setCliArgs(new String[] {
        "--plugin-dir", "./plugins/code-reviewer",
        "--plugin-dir", "./plugins/lint-fix",
    });

var client = new CopilotClient(options);
client.start().get();
```

</div>

<div class="ghd-codetab" data-lang="rust" data-label="Rust"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Rust</div>

```rust
use github_copilot_sdk::{Client, ClientOptions};

let client = Client::start(
    ClientOptions::new().with_extra_args([
        "--plugin-dir", "./plugins/code-reviewer",
        "--plugin-dir", "./plugins/lint-fix",
    ]),
)
.await?;
```

</div>

</div>

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

| SDK                | Opção de inicialização                                |
| ------------------ | ----------------------------------------------------- |
| Node.js/TypeScript | `builtinPluginDirectories: string[]`                  |
| Python             | `builtin_plugin_directories=[...]`                    |
| Go                 | `BuiltinPluginDirectories: []string{...}`             |
| .NET               | `BuiltinPluginDirectories = [...]`                    |
| 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 contribui                            | Visí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](/pt/copilot/how-tos/copilot-sdk/features/fleet-mode): 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.

<details open>
<summary>
<strong>Node.js/TypeScript</strong></summary>

```typescript
process.env.COPILOT_PLUGIN_DIR_ONLY = "true";

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

</details>

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:

<details open>
<summary>
<strong>Node.js/TypeScript</strong></summary>

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

</details>

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.md`superior.
* **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.

## Related

* [Agentes personalizados e orquestração de subagentes](/pt/copilot/how-tos/copilot-sdk/features/custom-agents): escreva agentes que são distribuídos na pasta de um plug-in `agents/`.
* [Habilidades personalizadas](/pt/copilot/how-tos/copilot-sdk/features/skills): como `SKILL.md` arquivos são carregados e as regras de ordenação por nível de habilidade.
* [Trabalhando com ganchos](/pt/copilot/how-tos/copilot-sdk/features/hooks): hooks definidos por um plugin são acionados junto com hooks registrados no SDK.
* [Usando servidores MCP com o SDK do GitHub Copilot](/pt/copilot/how-tos/copilot-sdk/features/mcp): os servidores MCP fornecidos pelo plug-in integram-se da mesma maneira que os registros embutidos.
* [Modo de frota](/pt/copilot/how-tos/copilot-sdk/features/fleet-mode): agentes fornecidos por plug-in podem ser despachados como subagentes.