Skip to main content

Plug-In-Verzeichnisse

Ein Plug-In ist ein Verzeichnis, das SDK-Erweiterungen – Fähigkeiten, Hooks, MCP-Server, benutzerdefinierte Agents und LSP-Konfiguration – hinter einem einzigen Manifest gebündelt. Wenn Sie auf das SDK in einem Plug-In-Verzeichnis verweisen, wird alles geladen, was das Plug-In beiträgt, sodass Sie wiederverwendbare Funktionspakete versenden können, ohne die Kabel pro Erweiterung in jeder Hostanwendung zu schreiben.

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 preToolUse Hook, 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.

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

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-dir beim Starten an den langlebigen CLI-Server; das SDK leitet --plugin-dir nicht 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:

SDKStartoption
Node.js / TypeScriptbuiltinPluginDirectories: string[]
Pythonbuiltin_plugin_directories=[...]
GoBuiltinPluginDirectories: []string{...}
.NETBuiltinPluginDirectories = [...]
Java.setBuiltinPluginDirectories(List.of(Path.of(...)))
Rust.with_builtin_plugin_directories([...])

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 BeitragFü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 /plugin oder die zugrunde liegende Nutzereinstellung installedPlugins installiert. 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-dir Plugins 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.json Manifest im Stammverzeichnis (oder unter .github/) hinzu, oder fügen Sie eine oberste Ebene SKILL.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 auf session.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-dir verwiesen wird. Wenn zwei verschiedene Verzeichnisse dasselbe Plug-In enthalten, werden beide geladen. Entfernen Sie eine oder verwenden Sie COPILOT_PLUGIN_DIR_ONLY=true.
  • --plugin-dir wird 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-dir in der Befehlszeile, mit der der Laufzeitserver gestartet wird.