# Répertoires de plug-in

Un plug-in est un répertoire qui regroupe les extensions du SDK ( compétences, hooks, serveurs MCP, agents personnalisés et configuration LSP) derrière un seul manifeste. En faisant pointer le SDK vers un répertoire de plug-ins, vous chargez tous les éléments fournis par le plug-in, ce qui vous permet de livrer des packs de fonctionnalités réutilisables sans écrire de code d’intégration spécifique à chaque extension dans chaque application hôte.

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

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

Ce guide explique la disposition du dossier de plug-in, la façon de charger un plug-in à partir d’un répertoire, quand utiliser des répertoires de plug-in et comment inscrire des extensions individuelles et comment rendre les ensembles de plug-ins déterministes.

## Quand utiliser des répertoires de plug-in

Utilisez un répertoire de plug-in lorsque vous souhaitez :

* **Distribuez un ensemble de fonctionnalités** en tant qu’unité ( par exemple, un pack « Réviseur TypeScript » avec une compétence, un `preToolUse` hook qui applique le lint et un agent personnalisé qui exécute le réviseur.
* **Placez les lots de fonctionnalités du fournisseur dans un référentiel** afin que chaque clone de l’application hôte charge les mêmes extensions de manière déterministe.
* **Développez un plug-in localement** avant de le publier sur une place de marché.
* **Remplacez ou étendez** un plugin installé depuis le marketplace avec un checkout local pour les tests.

Si vous n’avez besoin d’ajouter qu’un seul serveur MCP, un seul hook ou un seul agent personnalisé, vous pouvez l’inscrire en ligne via la configuration du SDK (`mcpServers`, `hooks`, `customAgents`). Les répertoires de plug-in sont les plus utiles une fois que vous avez trois extensions associées qui sont fournies ensemble.

## Structure du dossier du plugin

L’interface CLI Copilot analyse chaque répertoire de plug-in pour obtenir un manifeste `plugin.json` ou un `SKILL.md` de niveau racine. Un plug-in minimal ressemble à ceci :

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

Le manifeste peut également se trouver à `.github/plugin.json` ou à `.github/plugin/plugin.json`, afin que les plugins puissent se trouver dans un référentiel existant sans modifier l’organisation de sa racine. Chaque sous-système (hooks, MCP, LSP, compétences, agents) possède son propre chargeur et est facultatif , un plug-in a uniquement besoin des parties qu’il contribue.

Pour le schéma complet du manifeste, consultez la documentation de l’environnement d’exécution mentionnée dans la commande slash de votre `/plugin` CLI.

## Chargement d’un répertoire de plug-in à partir du Kit de développement logiciel (SDK)

Les répertoires de plug-ins sont chargés en passant `--plugin-dir <path>` à l’interface CLI Copilot lorsque le SDK le génère. Chaque langage expose cela via l’option extra-args de la connexion runtime. L’indicateur peut être répété pour charger plusieurs plug-ins.

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

> L’exemple ci-dessus utilise une connexion au runtime stdio, qui est l’option par défaut lorsque le SDK inclut l’outil CLI. Si vous vous connectez à un runtime externe via une URL (`forUri` / `ForUri`), passez `--plugin-dir` au serveur CLI de longue durée d’exécution lorsque vous le démarrez ; le SDK ne transmet pas `--plugin-dir` aux runtimes qu’il n’a pas lancés.

## Répertoires de plug-ins de confiance fournis avec l’hôte

Les applications qui expédient leurs propres plug-ins approuvés peuvent les inscrire en tant qu’option de démarrage client. Le SDK envoie l’ensemble ordonné complet après s’être connecté et avoir vérifié le protocole, avant le retour de `start` ou avant qu’une session puisse être créée. Les chemins d’accès doivent être absolus ; laisser l’option non définie ou vide n’entraîne aucun appel RPC.

L’option équivalente dans chaque Kit de développement logiciel (SDK) est la suivante :

| SDK                  | Option de démarrage                                   |
| -------------------- | ----------------------------------------------------- |
| 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([...])`             |

Il s’agit d’une limite d’approbation pour les plug-ins groupés et contrôlés par l’application hôte. Il est distinct de `--plugin-dir`, qui est un argument de lancement de processus CLI pour le chargement explicite des répertoires de plug-in ordinaires. L’option de démarrage fonctionne également lors de la connexion à un runtime existant, car elle est envoyée sur JSON-RPC plutôt que transférée en tant qu’argument de processus.

## Ce qu’un plug-in peut contribuer

Le chargement d’un répertoire de plug-in rend ses extensions visibles pour chaque session créée par le client. Le runtime fusionne les extensions fournies par le plug-in avec tout ce que vous inscrivez inline :

| Le plug-in contribue                          | Visible pour la session en tant que                                      |
| --------------------------------------------- | ------------------------------------------------------------------------ |
| Compétences (`SKILL.md`, `skills/*/SKILL.md`) | Éléments dans `session.skills.list()` ; injectables à partir de leur nom |
| Agents personnalisés (`agents/*.md`)          | Peut être réparti via l’outil `task(agent_type=...)`                     |
| Hooks (`hooks.json`)                          | Déclenché en même temps que les hooks enregistrés via le SDK             |
| Serveurs MCP (`.mcp.json`)                    | Outils et ressources accessibles via `session.mcp.*`                     |
| Serveurs LSP (`.lsp.json`)                    | Initialisé par `session.lsp.initialize(...)`                             |

Les agents plugin sont des sous-agents à part entière dans [Mode flotte](/fr/copilot/how-tos/copilot-sdk/features/fleet-mode) : un agent parent peut les invoquer via `agent_type`, et l’environnement d’exécution déclenche les hooks `subagentStart` / `subagentStop` pour eux comme pour tout autre sous-agent.

## Plugin-dir vs plugins du marketplace

L’environnement d’exécution offre deux façons d’installer des plugins, et toutes deux finissent par apparaître de la même manière pour une session :

* ```
            **Les plug-ins Marketplace /direct-repo** sont installés de manière permanente via la commande de barre oblique de `/plugin` l’interface CLI ou le paramètre utilisateur sous-jacent `installedPlugins` . Elles sont *ambiantes* : chaque session qui s’exécute sur la même configuration utilisateur les voit, et elles participent aux règles de découverte de plug-in.
  ```
* **`--plugin-dir` Les plug-ins** sont *explicites et éphémères* : ils s’appliquent uniquement au processus CLI que vous avez lancé avec cet indicateur. Ils sont prioritaires sur la découverte ambiante et sont dédupliqués par rapport aux entrées de la Place de marché avec le même chemin de cache, de sorte que le même plug-in ne se charge pas deux fois lorsque les deux surfaces le référencent.

Pour les applications pilotées par le SDK, `--plugin-dir` il s’agit généralement du bon choix : il conserve le plug-in défini sous le contrôle de votre application au lieu de dépendre de l’état utilisateur par ordinateur.

## Rendre les ensembles de plug-ins déterministes

Lorsque l’ordinateur hôte peut avoir d’autres plug-ins installés (place de marché ou personnel), définis `COPILOT_PLUGIN_DIR_ONLY=true` dans l’environnement du runtime pour supprimer la découverte automatique des plug-ins. Seuls les répertoires que vous passez par le `--plugin-dir` biais seront chargés.

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

Utilisez-le dans CI, dans les déploiements de serveurs sans tête, et n’importe où vous souhaitez un ensemble de plug-ins reproductible qui ne dépend pas de la configuration utilisateur de l’hôte.

## Inspection des plug-ins chargés

Une fois qu’une session est créée, listez les plug-ins actifs pour confirmer qu’un répertoire a bien été détecté :

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

Les plug-ins chargés via `--plugin-dir` apparaissent dans cette liste, avec leur chemin de cache défini sur le répertoire que vous avez fourni. Les installations Marketplace sont associées à leur source de registre.

## Résolution des problèmes

* **« aucun plugin.json ou SKILL.md trouvé dans \<dir> » :** le répertoire existe, mais ne se qualifie pas comme plug-in. Ajoutez un `plugin.json` manifeste à la racine (ou sous `.github/`) ou incluez un niveau `SKILL.md`supérieur.
* **Plug-in chargé, mais les agents/compétences ne sont pas visibles : assurez-vous** que le manifeste du plug-in déclare les agents/compétences qu’il contribue, ou utilisez la disposition implicite (`agents/*.md`, `skills/*/SKILL.md`). Appelez `session.rpc.skills.reload()` ensuite pour récupérer les modifications sans redémarrer.
* ```
            **Déclenchement de hooks en double** : le runtime déduplique via `cache_path`, mais uniquement lorsque le même répertoire est référencé à la fois comme installation depuis la Place de marché et comme `--plugin-dir`. Si deux répertoires différents contiennent le même plug-in, les deux sont chargés. Supprimez-en un ou utilisez `COPILOT_PLUGIN_DIR_ONLY=true`.
  ```
* **`--plugin-dir` ignoré lors de la connexion à un runtime externe** : le KIT de développement logiciel (SDK) transfère uniquement des arguments supplémentaires lorsqu’il génère l’interface CLI elle-même. Pour les environnements d’exécution externes (`forUri`/`ForUri`), transmettez `--plugin-dir` dans la ligne de commande qui démarre le serveur d’exécution.

## Related

* [Agents personnalisés et orchestration de sous-agents](/fr/copilot/how-tos/copilot-sdk/features/custom-agents) : écrivez des agents intégrés au dossier `agents/` d’un plug-in.
* [Compétences personnalisées](/fr/copilot/how-tos/copilot-sdk/features/skills) : comment les fichiers `SKILL.md` sont chargés et les règles d’ordre des niveaux de compétence.
* [Travailler avec les hooks](/fr/copilot/how-tos/copilot-sdk/features/hooks) : les hooks définis par un plugin s’exécutent parallèlement aux hooks enregistrés par le SDK.
* [Utilisation de serveurs MCP avec le SDK GitHub Copilot](/fr/copilot/how-tos/copilot-sdk/features/mcp) : les serveurs MCP fournis par plug-in s’intègrent de la même façon que les inscriptions inline.
* [Mode flotte](/fr/copilot/how-tos/copilot-sdk/features/fleet-mode) : les agents fournis par le plug-in peuvent être distribués comme sous-agents.