# プラグイン ディレクトリ

プラグインは、SDK 拡張機能 (スキル、フック、MCP サーバー、カスタム エージェント、LSP 構成) を 1 つのマニフェストの背後にバンドルするディレクトリです。 プラグイン ディレクトリで SDK をポイントすると、プラグインが提供するすべてのものが読み込まれるので、すべてのホスト アプリケーションで拡張機能ごとの配線を記述することなく、再利用可能な機能パックを出荷できます。

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

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

このガイドでは、プラグイン フォルダーのレイアウト、ディレクトリからプラグインを読み込む方法、プラグイン ディレクトリを使用するタイミングと個々の拡張機能を登録する方法、プラグイン セットを決定論的にする方法について説明します。

## プラグイン ディレクトリを使用する場合

次の場合は、プラグイン ディレクトリを使用します。

* **機能のバンドルを** 1 つのユニットとして配布します。たとえば、スキルを持つ "TypeScript レビュー担当者" パック、lint を適用する `preToolUse` フック、レビュー担当者を実行するカスタム エージェントなどです。
* **ベンダー機能はリポジトリにパックされるため、** ホスト アプリケーションのすべての複製で同じ拡張機能が決定論的に読み込まれます。
* **マーケットプレースに** 発行する前に、プラグインをローカルで開発します。
* テスト用のローカル チェックアウトを使用して、Marketplace にインストールされたプラグインを**オーバーライドまたは拡張**します。

1 つの MCP サーバー、1 つのフック、または単一のカスタム エージェントのみを追加する必要がある場合は、SDK 構成 (`mcpServers`、 `hooks`、 `customAgents`) を使用してインラインで登録できます。 プラグイン ディレクトリは、3 つ以上の関連する拡張機能が一緒に付属している場合に最も便利です。

## プラグイン フォルダーのレイアウト

Copilot CLI は、各プラグイン ディレクトリで、`plugin.json` マニフェストまたはルート レベルの `SKILL.md` をスキャンします。 最小限のプラグインは次のようになります。

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

また、マニフェストは `.github/plugin.json` または `.github/plugin/plugin.json` に存在する可能性があるため、プラグインはルート レイアウトを変更せずに既存のリポジトリ内に配置できます。 各サブシステム (フック、MCP、LSP、スキル、エージェント) には独自のローダーがあり、オプションです。プラグインには、それが提供するパーツのみが必要です。

完全なマニフェスト スキーマについては、CLI の `/plugin` スラッシュ コマンドから参照されるランタイム ドキュメントを参照してください。

## SDK からのプラグイン ディレクトリの読み込み

プラグイン ディレクトリは、SDK が生成するときに `--plugin-dir <path>` を Copilot CLI に渡すことによって読み込まれます。 各言語は、ランタイム接続の extra-args オプションを使用してこれを公開します。 フラグを繰り返して複数のプラグインを読み込むことができます。

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

> 上の例では stdio ランタイム接続を使用しています。これは、SDK が CLI をバンドルする場合の既定値です。 URL (`forUri` / `ForUri`) を使用して外部ランタイムに接続する場合は、起動時に実行時間の長い CLI サーバーに `--plugin-dir` を渡します。SDK は、生成されなかったランタイムに `--plugin-dir` を転送しません。

## 信頼されたホストバンドルプラグインディレクトリ

独自の信頼できるプラグインを出荷するアプリケーションは、クライアントのスタートアップ オプションとして登録できます。 SDK は、プロトコルを接続して検証した後、 `start` が返されるか、セッションを作成できるようになる前に、完全な順序付きセットを送信します。 パスは絶対パスにする必要があります。オプションを設定しないか空のままにしても、RPC 呼び出しは行われません。

各 SDK の同等のオプションは次のとおりです。

| SDK                 | スタートアップ オプション                                         |
| ------------------- | ----------------------------------------------------- |
| 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([...])`             |

これは、ホスト アプリケーションによってバンドルおよび制御されるプラグインの信頼境界です。 これは、通常のプラグイン ディレクトリを明示的に読み込むための CLI プロセス起動引数である `--plugin-dir` とは異なります。 スタートアップ オプションは、プロセス引数として転送されるのではなく、JSON-RPC 経由で送信されるため、既存のランタイムに接続するときにも機能します。

## プラグインが提供できる内容

プラグイン ディレクトリを読み込むと、クライアントによって作成されたすべてのセッションに拡張機能が表示されます。 ランタイムは、プラグインが提供する拡張機能を、インラインで登録したものと統合します。

| プラグインが貢献する                                 | セッションには次のように表示されます         |
| ------------------------------------------ | -------------------------- |
| スキル (`SKILL.md`、 `skills/*/SKILL.md`)      |                            |
| `session.skills.list()`内の項目。名前で挿入可能        |                            |
| カスタムエージェント (`agents/*.md`)                 |                            |
| `task(agent_type=...)` ツール経由で配信可能          |                            |
| フック (`hooks.json`)                         | SDK を介して登録されたフックとあわせて発火します |
| MCP サーバー (`.mcp.json`)                     |                            |
| `session.mcp.*` からアクセス可能なツールとリソース          |                            |
| LSP サーバー (`.lsp.json`)                     |                            |
| `session.lsp.initialize(...)` を介して初期化されます。 |                            |

プラグイン エージェントは [フリート モード](/ja/copilot/how-tos/copilot-sdk/features/fleet-mode) の最上位のサブエージェントです。親エージェントは `agent_type`でディスパッチでき、ランタイムは他のサブエージェントと同様に `subagentStart` / `subagentStop` フックを起動します。

## Plugin-dir と Marketplace プラグイン

ランタイムにはプラグインをインストールする 2 つの方法があり、両方ともセッションに対して同じように見えます。

* **Marketplace/ダイレクト リポジトリ プラグイン** は、CLI の `/plugin` スラッシュ コマンドまたは基になる `installedPlugins` ユーザー設定を使用して永続的にインストールされます。 これらは *アンビエント* であり、同じユーザー構成に対して実行されるすべてのセッションで表示され、プラグイン検出ルールに参加します。
* **`--plugin-dir` プラグイン** は *明示的で一時的* なもので、そのフラグを使用して起動した CLI プロセスにのみ適用されます。 これらはアンビエント検出よりも優先され、同じキャッシュ パスを持つマーケットプレース エントリに対して重複除去されるため、両方のサーフェスで参照しても同じプラグインが 2 回読み込まれることはありません。

SDK 駆動型アプリケーションでは、通常、 `--plugin-dir` が適切な選択肢です。プラグインは、マシンごとのユーザーの状態に応じてではなく、アプリケーションの制御下に置かれた状態を維持します。

## プラグインセットの決定論化

ホスト マシンに他のプラグイン (Marketplace または個人用) がインストールされている場合は、ランタイムの環境に `COPILOT_PLUGIN_DIR_ONLY=true` 設定して、プラグインの自動検出を抑制します。
`--plugin-dir`経由で渡したディレクトリのみが読み込まれます。

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

これは、CI、ヘッドレス サーバーのデプロイ、およびホストのユーザー構成に依存しない再現可能なプラグイン セットが必要な場所で使用します。

## どのプラグインが読み込まれたかの確認

セッションが作成されたら、アクティブなプラグインを一覧表示して、ディレクトリが正しく取得されたことを確認します。

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

`--plugin-dir`を介して読み込まれたプラグインは、指定したディレクトリにキャッシュ パスが設定された状態でこの一覧に表示されます。 Marketplace のインストールには、レジストリ ソースのタグが付けられます。

## Troubleshooting

* **"\<dir> に plugin.json または SKILL.md が見つかりません"** — ディレクトリは存在しますが、プラグインの要件を満たしていません。 ルート (または `plugin.json` の下) に`.github/` マニフェストを追加するか、最上位レベルの`SKILL.md`を含めます。
* **プラグインは読み込まれていますが、エージェント/スキルは表示されません** 。プラグイン マニフェストで、それが提供するエージェント/スキルが宣言されていることを確認するか、暗黙的なレイアウト (`agents/*.md`、 `skills/*/SKILL.md`) を使用してください。 次に、 `session.rpc.skills.reload()` を呼び出して、再起動せずに変更を取得します。
* **重複フックの発生** — ランタイムは `cache_path`によって重複を解除しますが、同じディレクトリが Marketplace のインストールと `--plugin-dir`の両方として参照されている場合にのみ発生します。 2 つの異なるディレクトリに同じプラグインが含まれている場合、両方が読み込まれます。 1 つを削除するか、 `COPILOT_PLUGIN_DIR_ONLY=true`を使用します。
* **`--plugin-dir` 外部ランタイムに接続する場合は無視されます** 。SDK は CLI 自体を生成するときにだけ余分な引数を転送します。 外部ランタイム (`forUri`/`ForUri`)は、ランタイム サーバーを起動するコマンド ラインで `--plugin-dir` を渡します。

## Related

* [カスタム エージェントとサブエージェント オーケストレーション](/ja/copilot/how-tos/copilot-sdk/features/custom-agents): プラグインの `agents/` フォルダー内に付属するエージェントを記述します。
* [カスタム スキル](/ja/copilot/how-tos/copilot-sdk/features/skills): `SKILL.md` ファイルの読み込み方法とスキルレベルの順序付け規則。
* [フックを使った作業](/ja/copilot/how-tos/copilot-sdk/features/hooks): プラグインによって定義されたフックは、SDK に登録されたフックと共に起動します。
* [GitHub Copilot SDK での MCP サーバーの使用](/ja/copilot/how-tos/copilot-sdk/features/mcp): プラグインによって提供される MCP サーバーは、インライン登録と同じ方法で統合されます。
* [フリート モード](/ja/copilot/how-tos/copilot-sdk/features/fleet-mode): プラグインによって提供されるエージェントは、サブエージェントとしてディスパッチ可能です。