# Erstellen von Erweiterungen für GitHub Copilot-CLI

Erstellen Sie Erweiterungen, mit denen Sie Ihre eigenen Tools und Schrägstrichbefehle zu Copilot CLI hinzufügen.

> \[!NOTE]
> GitHub Copilot-CLI Erweiterungen sind derzeit ein experimentelles Feature und können geändert werden.

Mit einer Erweiterung können Sie Copilot CLI eigene Funktionen hinzufügen. Jede Erweiterung ist ein kleines Node.js Modul, das zusammen mit Ihrer interaktiven Sitzung als separater Prozess ausgeführt wird und eine Verbindung damit herstellt. Über diese Verbindung kann eine Erweiterung **Werkzeuge** hinzufügen, die Copilot aufrufen kann, während es in Ihrem Auftrag arbeitet, und **Slash-Befehle**, die Sie selbst ausführen.

In diesem Lernprogramm erstellen Sie zwei einfache Erweiterungen als Beispiele dafür, was Sie tun können:

* Ein Tool namens `tool-time`, das Copilot aufrufen kann, um zu melden, wie lange die bisherigen Toolaufrufe in einer Sitzung gedauert haben.
* Ein Slash-Befehl namens `/tokencount`, der angibt, wie viele Token Sie verwendet haben, seit Sie mit dem Zählen begonnen haben.

Beide Beispiele basieren nur auf dem SDK, das mit dem Copilot CLIPaket gebündelt ist, daher gibt es nichts Zusätzliches zu installieren. Hintergrundinformationen zur Funktionsweise von Erweiterungen finden Sie unter [About extensions for GitHub Copilot-CLI](/de/enterprise-cloud@latest/copilot/concepts/agents/copilot-cli/about-cli-extensions).

> \[!WARNING]
> Erweiterungen werden auf Ihrem Computer mit Ihren Berechtigungen ausgeführt. Laden Sie nur Erweiterungscode, dem Sie vertrauen, auf die gleiche Weise, wie Sie nur ein anderes Skript ausführen würden, das Sie selbst nicht geschrieben haben.

## Prerequisites

* **GitHub Copilot-CLI**: Sie müssen Copilot CLI installiert und eingerichtet haben. Siehe [Erste Schritte mit GitHub Copilot CLI](/de/enterprise-cloud@latest/copilot/how-tos/copilot-cli/cli-getting-started).
* **Experimentelle Features aktiviert**: Erweiterungen sind derzeit ein experimentelles Feature. Mit den Schritten in diesem Lernprogramm werden experimentelle Features bei jedem Start der CLI mithilfe der `--experimental` Befehlszeilenoption aktiviert.
* **JavaScript**: Erweiterungen werden in JavaScript geschrieben, daher müssen Sie mit dieser Sprache vertraut sein, um Ihre eigenen Erweiterungen zu erstellen.
* **Ein Repository**: Im zweiten Beispiel wird eine Erweiterung auf Projektebene hinzugefügt, daher benötigen Sie eine lokale Kopie eines Git-Repositorys, in dem die Erweiterung hinzugefügt werden soll.

## Beispielerweiterung 1: Ein „Werkzeugzeit“-Tool

In diesem Beispiel wird eine Erweiterung **auf Benutzerebene** mit dem Namen `tool-time` hinzugefügt. Es fügt ein neues Tool namens `session_tool_time` hinzu, das Copilot aufrufen kann, um zu berichten, wie lange Toolaufrufe in dieser Sitzung bisher gedauert haben und wie viele Aufrufe dabei berücksichtigt werden.

Um sicherzustellen, dass ein Tool von der CLI verwendet wird, muss das Tool etwas tun, das die CLI nicht alleine ausführen kann. In diesem Fall erfasst das `session_tool_time`-Tool, wie lange Tool-Aufrufe dauern, indem es auf Ereignisse der CLI lauscht, die signalisieren, wann Tool-Aufrufe beginnen und enden, und die Zeitwerte selbst aufzeichnet. Da die CLI diese Zeitangaben nirgends so erfasst, dass Copilot sie lesen kann, besteht die einzige Möglichkeit für Copilot , sie zu erfahren, darin, das Tool aufzurufen. Die Beschreibung des Tools erläutert dies dem Modell, wodurch es dazu veranlasst wird, das Tool zu verwenden, wenn Sie nach Zeitangaben zu Tool-Aufrufen fragen.

### Schritt 1: Erstellen der Erweiterungsdatei

1. Erstellen Sie das folgende Verzeichnis und die folgende Datei in Ihrem Startverzeichnis:

   ```text
   ~/.copilot/extensions/tool-time/extension.mjs
   ```

   Da sich dies unter `~/.copilot/extensions/` befindet, ist die Erweiterung in **allen** Ihren CLI-Sitzungen in jedem Verzeichnis verfügbar – nicht nur in einem Repository.

2. Fügen Sie diesen Code zu `extension.mjs`:

   ```javascript copy
   // Extension: tool-time
   // Adds a session_tool_time tool that reports how long Copilot's tool calls
   // have taken this session. Copilot is never told these timings and they
   // aren't written anywhere, so calling the tool is the only way to find
   // them out.

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

   // The tool's own name, so it can avoid timing its own calls.
   const TOOL_NAME = "session_tool_time";

   // Module-level state persists for the whole session, because the extension
   // runs as a single long-lived process.
   const startTimes = new Map(); // tool call id -> Date.now() when call started
   let totalMs = 0; // total milliseconds spent across finished tool calls
   let callCount = 0; // number of finished tool calls measured

   const session = await joinSession({
       tools: [
           {
               name: TOOL_NAME,
               description:
                   "Report how long your tool calls have taken in total so far " +
                   "in THIS session, and how many calls that covers. You are " +
                   "never told how long your tool calls take and the timings " +
                   "aren't recorded anywhere you can read, so call this tool " +
                   "whenever you are asked about it rather than estimating.",
               // Always keep this tool's description in the model's tool list,
               // even when tool search is active, so Copilot reliably sees it:
               defer: "never",
               // Force a permissions approval prompt once, for this extension,
               // rather than on every call of this tool:
               skipPermission: true,
               parameters: { type: "object", properties: {} },
               handler: async () => {
                   const seconds = (totalMs / 1000).toFixed(1);
                   return `So far this session, Copilot's tool calls have taken ${seconds}s in total across ${callCount} call(s).`;
               },
           },
       ],
   });

   // When a tool starts, record the time, keyed by the tool call id so the
   // matching completion can be found later. The tool's own calls are skipped.
   session.on("tool.execution_start", (event) => {
       const data = event.data ?? {};
       if (data.toolName && data.toolName !== TOOL_NAME) {
           startTimes.set(data.toolCallId, Date.now());
       }
   });

   // When a tool finishes, add the elapsed time to the running total.
   session.on("tool.execution_complete", (event) => {
       const data = event.data ?? {};
       const startedAt = startTimes.get(data.toolCallId);
       if (startedAt === undefined) {
           return;
       }
       startTimes.delete(data.toolCallId);
       totalMs += Date.now() - startedAt;
       callCount += 1;
   });
   ```

> \[!NOTE]
> \*
> `@github/copilot-sdk/extension` ist das Erweiterungs-SDK, das mit der CLI gebündelt ist. Die CLI löst diesen Import automatisch auf, wenn die Erweiterung ausgeführt wird, sodass Sie ihn nicht einem `package.json` Paket-Manager hinzufügen oder ausführen müssen.
>
> * Die Werte `startTimes`, `totalMs` und `callCount` sind auf Modulebene definiert. Da die Erweiterung während der gesamten Sitzung als ein einzelner, langlebiger Prozess ausgeführt wird, häufen sie sich an, solange die Sitzung geöffnet ist.

### Schritt 2: Laden der Erweiterung

1. Starten Sie eine interaktive Sitzung mit aktivierten experimentellen Features:

   ```shell copy
   copilot --experimental
   ```

   Da die Erweiterung unter `~/.copilot/extensions/` installiert ist, können Sie die CLI aus jedem Verzeichnis starten, und die Erweiterung steht zur Verfügung.

   Wenn Sie bereits eine Sitzung geöffnet haben, führen Sie die Ausführung aus `/clear` , um eine neue Sitzung zu starten, die Erweiterungen vom Datenträger neu lädt.

2. Ohne erhöhte Berechtigungen für die neue Erweiterung, alle Erweiterungen oder alle Tools zu gewähren, werden Sie aufgefordert, die neue Erweiterung zum Überspringen von Toolberechtigungsaufforderungen zuzulassen. Wählen Sie " **Ja** " oder **"Ja" aus, und lassen Sie in diesem Verzeichnis immer "user:tool-time" zu**.

   > \[!NOTE]
   > Damit die mindestens erhöhten Berechtigungen verhindern können, dass diese Meldung angezeigt wird, wenn Sie die CLI starten, fügen Sie diese dem CLI-Startbefehl hinzu:
   >
   > ```shell copy
   > --allow-tool='extension-permission-access(user:tool-time)'
   > ```
   >
   > Weitere Informationen findest du unter [Zulassen und Verweigern der Verwendung von Tools](/de/enterprise-cloud@latest/copilot/how-tos/copilot-cli/use-copilot-cli/allowing-tools).

### Schritt 3: Bestätigen, dass die Erweiterung ausgeführt wird

Führen Sie den `/extensions manage` Befehl aus, um den Erweiterungs-Manager zu öffnen. Ihre `tool-time` Erweiterung sollte unter der Gruppe " **Benutzer** " mit dem Status " **Ausführen**" aufgeführt werden. Drücken Sie <kbd>ESC</kbd> , um den Vorgesetzten zu schließen.

### Schritt 4: Ausprobieren

1. Im Gegensatz zu einem Slash-Befehl rufen Sie ein Werkzeug nicht selbst auf — Copilot ruft es auf, wenn es sinnvoll ist. Geben Sie Copilot zuerst eine Aufgabe, bei der einige Toolaufrufe erforderlich sind, zum Beispiel:

   ```copilot copy
   Explore the files in the current directory and give me a short summary of what's here.
   ```

2. Sobald Copilot geantwortet hat, fragen Sie:

   ```copilot copy
   How long have tool calls taken so far this session?
   ```

   Der Agent ruft das `session_tool_time` Tool aus der neuen Erweiterung auf und verwendet es, um Ihre Frage zu beantworten.

   > \[!TIP]
   > Sie können bestätigen, dass der Agent das neue Tool verwendet hat, indem Sie sich den Anfang der Antwort ansehen Copilot. Die Antwort sollte dem Namen des verwendeten Tools vorangestellt werden; in diesem Fall , `session_tool_time`.

### Funktionsweise des Tools

Der Aufruf von `joinSession` macht aus einer einfachen Node.js-Datei eine Copilot CLI-Extension. Er verbindet den laufenden Prozess mit Ihrer Sitzung und registriert alles, was die Erweiterung der CLI hinzufügt – in diesem Fall ein einzelnes Tool.

Ein Tool wird durch diese Felder definiert:

* **`name`**— der Bezeichner Copilot, mit dem das Tool aufgerufen wird.
* **`description`**— Was das Tool tut. Das Modell basiert auf diesem Text, um zu entscheiden, wann das Tool aufgerufen werden soll, daher lohnt es sich, explizit zu sein. Diese Beschreibung teilt dem Modell mit, dass ihm diese Zeitangaben nicht mitgeteilt werden, was es dazu veranlasst, das Tool aufzurufen, anstatt zu versuchen, die Zeitangaben auf andere Weise zu ermitteln.
* **`parameters`**– ein JSON-Schema, das die Argumente des Tools beschreibt. Dieses Tool akzeptiert keine, daher ist das Schema ein Objekt ohne Eigenschaften.
* **`handler`**– eine asynchrone Funktion, die beim Copilot Aufrufen des Tools ausgeführt wird. Die zurückgegebene Zeichenfolge wird zum Ergebnis des Tools, das vom Modell gelesen wird.

Zwei weitere Felder gestalten, wie das Tool dem Modell angeboten wird:

* **`defer: "never"`**– behält die Beschreibung des Tools jederzeit in der Toolliste des Modells bei. Standardmäßig kann die CLI, wenn viele Tools verfügbar sind, selten verwendete Tools zurückstellen und das Modell bei Bedarf danach suchen lassen. Das Setzen von `defer` auf `"never"` schließt dieses Tool von diesem Verhalten aus, sodass Copilot es immer sieht.

  > \[!IMPORTANT]
  > `defer: "never"` macht das Tool einfach *für Copilot verfügbar*. Es \_zwingt\_Copilot nicht, sie aufzurufen. Es gibt keine Möglichkeit, eine Erweiterung zu mandatieren, dass ein bestimmtes Tool immer verwendet werden sollte, wenn es eine alternative Möglichkeit gibt, eine geeignete Antwort auf eine Aufforderung zu generieren. Das Modell entscheidet immer für sich selbst, welches Tool verwendet werden soll. In diesem Beispiel wird das neue Tool zuverlässig verwendet, da es für das Modell keine andere Möglichkeit gibt, die vom Tool bereitgestellten Informationen zu kennen.

* **`skipPermission: true`** ermöglicht die Ausführung des Tools, ohne Sie aufzufordern, jeden Anruf zu genehmigen. Dies ist hier angemessen, da das Tool nur die Gesamtwerte ausliest, die die Erweiterung bereits erfasst hat; es greift nicht auf Ihre Dateien zu und führt keine Befehle aus.

Die Zeitangaben werden durch Beobachten der Sitzung erfasst. Die Erweiterung abonniert zwei Ereignisse, die die CLI vor und nach jedem Toolaufruf ausgibt:

```javascript
session.on("tool.execution_start", (event) => { /* ... */ });
session.on("tool.execution_complete", (event) => { /* ... */ });
```

Ein `tool.execution_start` Ereignis trägt den Namen des Tools (`event.data.toolName`). Ein `tool.execution_complete` Ereignis trägt eine `success` Kennzeichnung. Keines der Ereignisse enthält die Informationen des jeweils anderen, daher korreliert die Erweiterung sie über das `toolCallId`, das in beiden vorkommt: Beim Start eines Tools speichert sie die aktuelle Uhrzeit unter dieser ID. Wenn die entsprechende Completion eintrifft, werden die verstrichenen Millisekunden zur laufenden Gesamtsumme addiert. Das Tool überspringt seine eigenen Aufrufe, sodass der Wert die tatsächliche Arbeit von Copilot widerspiegelt.

Da die Gesamtsummen im langlebigen Erweiterungsprozess leben, decken sie die gesamte Sitzung ab. Genau dafür sind Job-Erweiterungen gut geeignet: zu beobachten, was in der Sitzung passiert, und den Zustand über mehrere Aufrufe hinweg beizubehalten.

> \[!NOTE]
>
> * Die Summen werden im Arbeitsspeicher gespeichert, sodass sie bei jedem erneuten Laden der Erweiterung oder beim Neustart der Sitzung (z. B. nach `/clear`) zurückgesetzt werden.
> * Der angegebene Wert ist die aus Sicht der Erweiterung gemessene Wall-Clock-Zeit – also die Zeitspanne zwischen den Start- und Abschlussereignissen der einzelnen Tool-Aufrufe – und umfasst damit auch die Zeit, die ein Aufruf darauf gewartet hat, dass Sie ihn genehmigen.

## Beispielerweiterung 2: Ein Slash-Befehl zur Token-Nutzung

Dieses Beispiel fügt eine Projekterweiterung mit der Bezeichnung `token-counter` hinzu. Die Erweiterung fügt einen `/tokencount` Schrägstrichbefehl hinzu, mit dem Sie überprüfen können, wie viele Token Sie bei der Interaktion mit Copilot der CLI verwendet haben. Sie führen `/tokencount start` aus, wenn Sie mit der Messung Ihrer Token-Nutzung beginnen möchten, und können dann zu einem späteren Zeitpunkt `/tokencount` ausführen, um zu prüfen, wie viele Token Sie seit Beginn der Zählung verbraucht haben.

Die Erweiterung führt eine fortlaufende Gesamtzahl der in der Sitzung verwendeten Token, indem sie die von der CLI gesendeten Ereignisse abonniert, was ein einmalig ausgeführter Shell-Befehl nicht leisten kann.

### Schritt 1: Erstellen der Erweiterungsdatei

1. Erstellen Sie im Stammverzeichnis des Git-Repositorys für Ihr Projekt die folgenden Verzeichnisse und Dateien:

   ```text
   .github/extensions/token-counter/extension.mjs
   ```

2. Fügen Sie diesen Code zu `extension.mjs`:

   ```javascript copy
   // Extension: token-counter
   // Adds a /tokencount slash command that reports how many tokens you've used
   // since you started counting.

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

   // Module-level state. The extension runs as a single long-lived process for
   // the whole session, so these values persist between command invocations.
   let tokensUsed = 0; // Running total of tokens used so far this session.
   let startedAt = null; // tokensUsed when "/tokencount start" was last run.
   // null = not started.
   // startedAt allows you to count tokens multiple times in a session.

   const session = await joinSession({
       commands: [
           {
               name: "tokencount",
               description: "Report how many tokens you've used since " +
                   "'/tokencount start'.",
               handler: async (ctx) => {
                   const arg = (ctx.args ?? "").trim();

                   if (arg === "start") {
                       // Reset: remember the current total as the new baseline.
                       startedAt = tokensUsed;
                       await session.log(
                           "Token counter started. Run '/tokencount' later to " +
                           "see how many tokens you've used.",
                           { level: "info" },
                       );
                       return;
                   }

                   if (startedAt === null) {
                       await session.log(
                           "The token counter has not been started. Start by " +
                           "entering '/tokencount start'.",
                           { level: "info" },
                       );
                       return;
                   }

                   const used = tokensUsed - startedAt;
                   await session.log(
                       `You have used ${used} tokens since entering ` +
                       "'/tokencount start'.",
                       { level: "info" },
                   );
               },
           },
       ],
   });

   // The CLI emits an "assistant.usage" event after each assistant turn. Add the
   // tokens it reports to a running total kept in the extension's memory.
   session.on("assistant.usage", (event) => {
       const { inputTokens = 0, outputTokens = 0 } = event.data ?? {};
       tokensUsed += inputTokens + outputTokens;
   });
   ```

### Schritt 2: Laden der Erweiterung

Starten Sie eine interaktive Sitzung aus demselben Repository, wobei experimentelle Features aktiviert sind:

```shell copy
copilot --experimental
```

Wenn Sie bereits eine Sitzung geöffnet haben, können Sie ausführen `/clear` , um eine neue Sitzung zu starten, die Erweiterungen vom Datenträger neu lädt.

### Schritt 3: Bestätigen, dass die Erweiterung ausgeführt wird

Führen Sie den `/extensions manage` Befehl aus, um den Erweiterungs-Manager zu öffnen. Ihre `token-counter` Erweiterung sollte unter der Gruppe **Project** mit dem Status **wird ausgeführt** aufgeführt sein. Drücken Sie <kbd>ESC</kbd> , um den Vorgesetzten zu schließen.

Sie können auch ausführen `/env` , um eine Zusammenfassung aller in die Sitzung geladenen Elemente anzuzeigen, einschließlich Erweiterungen.

### Schritt 4: Ausprobieren

Im Gegensatz zu einem Tool rufen Sie selbst einen Slash-Befehl auf. Starten Sie den Zähler:

```copilot copy
/tokencount start
```

Senden Sie Copilot eine Eingabeaufforderung oder zwei, damit sie einige Token verwendet, z. B. bitten Sie sie, eine Datei zu erläutern. Überprüfen Sie dann, wie viele Token Sie verwendet haben:

```copilot copy
/tokencount
```

Wenn Sie `/tokencount start` erneut ausführen, beginnt der Zähler wieder bei null.

### Funktionsweise des Beispiels

Der Aufruf von `joinSession` registriert alles, was die Erweiterung der CLI hinzufügt – in diesem Fall einen einzelnen Slash-Befehl.

Ein Slash-Befehl wird durch drei Felder definiert:

* **`name`**— der Befehlsname ohne den führenden Schrägstrich. Durch das Registrieren von `tokencount` steht `/tokencount` in der Sitzung zur Verfügung.
* **`description`**— der Text neben dem Befehl in der Schrägstrich-Befehlsauswahl.
* **`handler`**– eine asynchrone Funktion, die ausgeführt wird, wenn Sie den Befehl aufrufen. Es empfängt ein Kontextobjekt, dessen `args` Eigenschaft den unformatierten Text enthält, der nach dem Befehlsnamen eingegeben wurde. Für `/tokencount start` ist `ctx.args``"start"`; für ein bloßes `/tokencount` ist es eine leere Zeichenfolge.

Der Handler schreibt seine Ausgabe mit `session.log(message, { level: "info" })` in die Sitzung zurück, wodurch die Nachricht im Transkript ausgegeben wird.

Um zu wissen, wie viele Token verwendet wurden, abonniert die Erweiterung ein Sitzungsereignis:

```javascript
session.on("assistant.usage", (event) => {
    const { inputTokens = 0, outputTokens = 0 } = event.data ?? {};
    tokensUsed += inputTokens + outputTokens;
});
```

Die CLI gibt nach jeder Antwort des Assistenten ein `assistant.usage`-Ereignis aus, das die Anzahl der Eingabe- und Ausgabetokens für diese Antwort enthält. Die Erweiterung fügt sie der laufenden Summe in `tokensUsed` hinzu. Wenn Sie `/tokencount start` ausführen, zeichnet der Handler den aktuellen Gesamtwert in `startedAt` auf. Wenn später in der Sitzung `/tokencount` ohne Argument eingegeben wird, wird die Differenz angezeigt. Da sich beide Variablen im langlebigen Erweiterungsprozess befinden, bleiben sie für die gesamte Sitzung erhalten.

> \[!NOTE]
> Die Summen werden im Arbeitsspeicher gespeichert, sodass sie bei jedem erneuten Laden der Erweiterung oder beim Neustart der Sitzung (z. B. nach `/clear`) zurückgesetzt werden.

## Bearbeiten und Neuladen einer Erweiterung

Während Sie eine Erweiterung entwickeln, werden Sie `extension.mjs` bearbeiten und möchten Ihre Änderungen sehen. Nach dem Speichern der Datei können Sie die neue Version auf eine der folgenden Arten abrufen:

* Fordern Sie Copilot auf, Erweiterungen neu zu laden, z. B. `Reload my extensions`.
* Führen Sie die Ausführung `/clear` aus, um eine neue Sitzung zu starten, die Erweiterungen vom Datenträger neu lädt.
* Starten Sie die CLI neu.

Wenn eine Erweiterung nicht startet oder sich unerwartet verhält, führen Sie `/extensions manage` aus und überprüfen Sie die Erweiterung, um ihren Status und den Pfad zu ihrer Protokolldatei anzuzeigen. Jede Erweiterung schreibt ein Protokoll unter `~/.copilot/logs/extensions/`, das der beste Ort ist, um zu sehen, wenn etwas schief geht.

## Nächste Schritte

* Passen Sie eines dieser Beispiele an Ihre eigenen Bedürfnisse an. Bitten Sie Copilot in der CLI, das Verhalten einer der Beispielerweiterungen zu ändern.
* Teilen Sie eine benutzerspezifische Erweiterung. Verschieben Sie die `tool-time` Erweiterung beispielsweise in das Verzeichnis eines Repositorys `.github/extensions/` , um sie für alle Personen freizugeben, die in diesem Repository arbeiten.
* Bitten Sie Copilot , eine neue Erweiterung für Sie von Grund auf neu zu erstellen.
  Copilot CLI Erweiterungen werden von Copilot SDK unterstützt, sodass eine Erweiterung alles kann, was das SDK ermöglicht, und Sie interaktive Ansichten mit Schaltflächen und Formularen sowie neue Tools und Befehle hinzufügen können. Siehe [Copilot SDK](/de/enterprise-cloud@latest/copilot/how-tos/copilot-sdk).

## Weiterführende Lektüre

* [GitHub Copilot CLI-Befehlsreferenz](/de/enterprise-cloud@latest/copilot/reference/copilot-cli-reference/cli-command-reference)