In diesem Handbuch wird die Struktur des Plug-in-Ordners erläutert, wie Sie ein Plug-in aus einem Verzeichnis laden, wann Plug-in-Verzeichnisse im Vergleich zur Registrierung einzelner Erweiterungen verwendet werden sollten und wie Plug-in-Sets deterministisch gemacht werden.
Wann Plugin-Verzeichnisse verwendet werden sollten
Verwenden Sie ein Plug-In-Verzeichnis, wenn Sie folgendes möchten:
- Verteilen Sie ein Bündel von Fähigkeiten als Einheit — z. B. ein „TypeScript Reviewer“-Paket mit einer Fähigkeit, einem
preToolUseHook, der die Linting-Regeln erzwingt, und einem benutzerdefinierten Agenten, der den Reviewer ausführt. - Anbieterfunktionspakete in ein Repository , sodass jeder Klon der Hostanwendung die gleichen Erweiterungen deterministisch lädt.
- Entwickeln Sie ein Plug-In lokal , bevor Sie es auf einem Marketplace veröffentlichen.
- Überschreiben oder Erweitern eines marketplace-installierten Plug-Ins mit einem lokalen Auschecken zu Testzwecken.
Wenn Sie nur einen einzelnen MCP-Server, einen einzelnen Hook oder einen einzelnen benutzerdefinierten Agent hinzufügen müssen, können Sie ihn inline über die SDK-Konfiguration (mcpServers, , hooks``customAgents) registrieren. Plug-In-Verzeichnisse sind am nützlichsten, sobald Sie drei oder mehr verwandte Erweiterungen haben, die zusammen ausgeliefert werden.
Plugin-Ordnerstruktur
Die Copilot CLI durchsucht jedes Plug-In-Verzeichnis nach einem plugin.json-Manifest oder einer SKILL.md im Stammverzeichnis. Ein minimales Plug-In sieht wie folgt aus:
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
Das Manifest kann sich auch unter .github/plugin.json oder .github/plugin/plugin.json befinden, sodass Plugins in einem vorhandenen Repository liegen können, ohne dessen Stammverzeichnisstruktur zu ändern. Jedes Subsystem (Hooks, MCP, LSP, Skills, Agents) verfügt über einen eigenen Loader und ist optional – ein Plugin benötigt nur die Teile, die es beisteuert.
Das vollständige Manifestschema finden Sie in der Laufzeitdokumentation, auf die im Schrägstrichbefehl /plugin Ihrer CLI verwiesen wird.
Laden eines Plug-In-Verzeichnisses aus dem SDK
Plug-In-Verzeichnisse werden geladen, indem --plugin-dir <path> an die Copilot CLI übergeben werden, wenn das SDK sie spawns. Jede Sprache macht dies über die Extra-Args-Option der Laufzeitverbindung verfügbar. Das Flag kann wiederholt werden, um mehrere Plug-ins zu laden.
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();
from copilot import CopilotClient, StdioRuntimeConnection
client = CopilotClient(
connection=StdioRuntimeConnection(
args=(
"--plugin-dir", "./plugins/code-reviewer",
"--plugin-dir", "./plugins/lint-fix",
),
),
)
await client.start()
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
}
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();
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();
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?;
Im obigen Beispiel wird eine Stdio-Laufzeitverbindung verwendet– der Standardwert, wenn das SDK die CLI bündelt. Wenn Sie über eine URL (
forUri/ForUri) eine Verbindung zu einer externen Laufzeit herstellen, übergeben Sie--plugin-dirbeim Starten an den langlebigen CLI-Server; das SDK leitet--plugin-dirnicht an Laufzeiten weiter, die es nicht selbst gestartet hat.
Vertrauenswürdige Host-gebündelte Plug-In-Verzeichnisse
Anwendungen, die ihre eigenen vertrauenswürdigen Plug-Ins versenden, können sie als Clientstartoption registrieren. Das SDK sendet die vollständige geordnete Menge nach dem Herstellen der Verbindung und der Überprüfung des Protokolls, bevor start zurückkehrt oder eine Sitzung erstellt werden kann. Pfade müssen absolut sein; wenn die Option nicht gesetzt oder leer ist, erfolgt kein RPC-Aufruf.
Die entsprechende Option in jedem SDK lautet:
| SDK | Startoption |
|---|---|
| Node.js / TypeScript | builtin |
| Python | builtin_plugin_ |
| Go | Builtin |
| .NET | Builtin |
| Java | .set |
| Rust | .with_builtin_ |
Dies ist eine Vertrauensgrenze für Plugins, die gebündelt und von der Hostanwendung gesteuert werden. Es unterscheidet sich von --plugin-direinem CLI-Prozessstartargument zum expliziten Laden gewöhnlicher Plug-In-Verzeichnisse. Die Startoption funktioniert auch beim Herstellen einer Verbindung mit einer vorhandenen Laufzeit, da sie über JSON-RPC und nicht als Prozessargument weitergeleitet wird.
Was ein Plug-In beitragen kann
Das Laden eines Plug-In-Verzeichnisses macht seine Erweiterungen für jede vom Client erstellte Sitzung sichtbar. Die Laufzeit führt von Plug-ins bereitgestellte Erweiterungen mit allem zusammen, was Sie inline registrieren:
| Plugin leistet einen Beitrag | Für Sitzung sichtbar als |
|---|---|
Fähigkeiten (SKILL.md, skills/*/SKILL.md) | Elemente in session.skills.list(); injizierbar nach Name |
Benutzerdefinierte Agenten (agents/*.md) | Verteilbar über das task(agent_type=...) Tool |
Hooks (hooks.json) | Wird zusammen mit Hooks ausgelöst, die über das SDK registriert sind |
MCP-Server (.mcp.json) | Werkzeuge und Ressourcen, die über session.mcp.* erreichbar sind |
LSP-Server (.lsp.json) | Initialisiert über session.lsp.initialize(...) |
Plug-in-Agents sind erstklassige Sub-Agents in Flottenmodus: Ein übergeordneter Agent kann sie über agent_type aufrufen, und die Laufzeit löst die Hooks subagentStart / subagentStop für sie wie bei jedem anderen Sub-Agenten aus.
Plugin-Verzeichnis vs. Marketplace-Plugins
Die Laufzeitumgebung bietet zwei Möglichkeiten, Plugins zu installieren, und beide sehen für eine Sitzung gleich aus:
- Marketplace-/Direct-Repo-Plugins werden dauerhaft über den Slash-Befehl der CLI
/pluginoder die zugrunde liegende NutzereinstellunginstalledPluginsinstalliert. Sie sind global verfügbar – jede Sitzung, die mit derselben Benutzerkonfiguration ausgeführt wird, hat Zugriff darauf, und sie werden bei den Regeln zur Plug-in-Erkennung berücksichtigt. --plugin-dirPlugins sind explizit und kurzlebig – sie gelten nur für den CLI-Prozess, den Sie mit dieser Kennzeichnung gestartet haben. Sie haben Vorrang vor ambient discovery und werden gegen Marketplace-Einträge mit demselben Cachepfad dedupliziert, sodass dasselbe Plug-In nicht zweimal geladen wird, wenn beide Oberflächen darauf verweisen.
Für SDK-basierte Anwendungen ist --plugin-dir in der Regel die richtige Wahl: Es hält den Plug-In-Satz unter der Kontrolle Ihrer Anwendung, anstatt vom benutzerspezifischen Zustand des jeweiligen Rechners abzuhängen.
Deterministisches Erstellen von Plug-in-Sets
Wenn auf der Hostmaschine möglicherweise andere Plugins installiert sind (aus dem Marketplace oder eigene), setzen Sie COPILOT_PLUGIN_DIR_ONLY=true in den Umgebungsvariablen der Laufzeitumgebung, um die automatische Erkennung von Plugins zu unterdrücken. Nur die Verzeichnisse, die Sie über --plugin-dir übergeben, werden geladen.
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();
Verwenden Sie dies in CI, in Headless-Serverbereitstellungen und überall, wo Sie einen reproduzierbaren Plug-In-Satz wünschen, der nicht von der Benutzerkonfiguration des Hosts abhängt.
Prüfen, welche Plug-Ins geladen wurden
Sobald eine Sitzung erstellt wurde, führen Sie die aktiven Plug-Ins auf, um zu bestätigen, dass ein Verzeichnis richtig aufgenommen wurde:
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, die über --plugin-dir geladen werden, erscheinen in dieser Liste, wobei ihr Cachepfad auf das von Ihnen angegebene Verzeichnis gesetzt ist. Marketplace-Installationen werden mit ihrer Registrierungsquelle markiert.
Troubleshooting
- "keine plugin.json oder SKILL.md in <dir> gefunden" – das Verzeichnis ist vorhanden, gilt aber nicht als Plugin. Fügen Sie ein
plugin.jsonManifest im Stammverzeichnis (oder unter.github/) hinzu, oder fügen Sie eine oberste EbeneSKILL.mdein. - Plug-In geladen, aber Agents/Fähigkeiten nicht sichtbar - stellen Sie sicher, dass das Plug-In-Manifest die Agents/Fähigkeiten deklariert, die es beiträgt, oder verwenden Sie das implizite Layout (
agents/*.md,skills/*/SKILL.md). Rufen Sie dann aufsession.rpc.skills.reload(), um Änderungen ohne Neustart zu übernehmen. - Doppelte Hooks werden ausgeführt – die Laufzeit dedupliziert anhand von
cache_path, aber nur, wenn auf dasselbe Verzeichnis sowohl als Marketplace-Installation als auch als--plugin-dirverwiesen wird. Wenn zwei verschiedene Verzeichnisse dasselbe Plug-In enthalten, werden beide geladen. Entfernen Sie eine oder verwenden SieCOPILOT_PLUGIN_DIR_ONLY=true. --plugin-dirwird bei der Verbindung mit einer externen Laufzeit ignoriert – das SDK leitet zusätzliche Argumente nur weiter, wenn es die CLI selbst startet. Für externe Laufzeiten (forUri/ForUri) übergeben Sie--plugin-dirin der Befehlszeile, mit der der Laufzeitserver gestartet wird.
Verwandte Themen
- Angepasste Agents und Orchestrierung von Unteragenten: Agenten schreiben, die im
agents/Ordner des Plug-ins enthalten sind. - Benutzerdefinierte Fähigkeiten: Wie
SKILL.mdDateien geladen werden, und die Regeln für die Reihenfolge der Fähigkeiten. - Arbeiten mit Hooks: Von einem Plugin definierte Hooks werden zusammen mit den vom SDK registrierten Hooks ausgelöst.
- Verwenden von MCP-Servern mit dem GitHub Copilot SDK: Von Plugins bereitgestellte MCP-Server werden auf die gleiche Weise wie Inline-Registrierungen integriert.
- Flottenmodus: Von Plugins bereitgestellte Agenten können als Sub-Agenten eingesetzt werden.