> ## Documentation Index
> Fetch the complete documentation index at: https://docs.qoder.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Plugins

`options.plugins` を使用して、ローカルプラグインディレクトリを現在のセッションに読み込みます。SDK は各ローカルプラグインを `--plugin-dir <path>` 起動パラメータに変換します。プラグインに含まれる commands、agents、skills、MCP servers はすべて今回のセッションの機能発見の対象になります。

<div id="ローカルプラグインの読み込み" />

## ローカルプラグインの読み込み

```python theme={null}
from qoder_agent_sdk import QoderAgentOptions, QoderSDKClient

options = QoderAgentOptions(
    plugins=[
        {"type": "local", "path": "/path/to/my-plugin"},
    ],
)

async with QoderSDKClient(options) as client:
    info = await client.get_server_info()
    print(info.get("commands"))
    print(info.get("agents"))
    print(info.get("plugins"))
```

複数のローカルプラグインを同時に渡すことができ、その順序で複数回 `--plugin-dir` が出力されます。

```python theme={null}
options = QoderAgentOptions(
    plugins=[
        {"type": "local", "path": "/path/to/plugin-a"},
        {"type": "local", "path": "/path/to/plugin-b"},
    ],
)
```

> 💡 `query()` は使い切りのメッセージストリームのため、ハンドシェイク後に init レスポンスを取得することはできません。プラグインが提供する command / agent / skill を読み取るには、`QoderSDKClient` を使用し、`connect()` の後に `get_server_info()` を呼び出すか、メッセージストリーム内で `SystemMessage(subtype='init')` を捕捉して自分で `message.data` を読み取ってください。

<div id="プラグインディレクトリレイアウト" />

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

ローカルプラグインは通常以下を含むことができます。

```
my-plugin/
  .qoder-plugin/plugin.json
  commands/
  agents/
  skills/
  .mcp.json
```

`.qoder-plugin/plugin.json` はプラグイン名、バージョン、説明を宣言するために使用します。その他のディレクトリはファイルタイプに応じて CLI が自動的にスキャンします。

SDK はパスが存在するか / 妥当かを検証しません。

* 存在しない `--plugin-dir` パスは SDK モードではサイレントに無視され、セッションは正常に初期化されます。
* 破損したフロントマター / `.mcp.json` は init をブロックしません。破損したコマンドは init レスポンスに表示されません。
* プラグインの読み込み失敗を明示的に診断したい場合、現状は [`reload_plugins().error_count`](#実行中のプラグインリロード) でフォールバックするしかありません。

<div id="プラグインが提供する-slash-commands" />

<div id="プラグインが提供するslashcommands" />

## プラグインが提供する slash commands

プラグイン内の `commands/*.md` は `get_server_info()['commands']` に表示され、名前は `<plugin>:<cmd>` の修飾名形式で現れます。

```python theme={null}
async with QoderSDKClient(options) as client:
    info = await client.get_server_info()
    for cmd in info.get("commands", []):
        print(cmd["name"], cmd.get("description"))
```

<div id="プラグインが提供する-agents" />

<div id="プラグインが提供するagents" />

## プラグインが提供する agents

プラグイン内の `agents/*.md` は `get_server_info()['agents']` に表示されます。SDK は同期的な便利メソッドも提供しており、このリストを直接取得できます。

```python theme={null}
async with QoderSDKClient(options) as client:
    for agent in client.supported_agents():
        print(agent["name"], agent.get("description"))
```

<div id="プラグインが提供する-skills" />

<div id="プラグインが提供するskills" />

## プラグインが提供する skills

プラグイン内の `skills/<name>/SKILL.md` はプラグイン修飾名（`plugin:skill`）で登録されます。メインセッションから呼び出せるようにするには、`options.skills` で明示的にリストする必要があります。[Skills ドキュメント](/ja/cli/sdk/python/skills#プラグイン内-skill-の有効化) を参照してください。

<div id="プラグインが提供する-mcp-servers" />

<div id="プラグインが提供するmcpservers" />

## プラグインが提供する MCP servers

プラグイン内の `.mcp.json` は CLI によって起動され、MCP 状態に組み込まれます。`get_mcp_status()` で読み取ることができます。

```python theme={null}
async with QoderSDKClient(options) as client:
    status = await client.get_mcp_status()
    for server in status["mcpServers"]:
        print(server["name"], server["status"])
```

<div id="インストール済み同名プラグインの一時的な上書き" />

## インストール済み同名プラグインの一時的な上書き

`options.plugins` で読み込まれたローカルプラグインはセッションスコープです。現在のセッション内で既にインストールされているプラグインと同名の場合、ローカルプラグインが今回のセッションの機能発見で優先されます。この機能はプラグインの開発、デバッグ、段階的検証に適しています。

```python theme={null}
options = QoderAgentOptions(
    # ローカル版はこの query セッション内でのみ有効で、ユーザーのグローバルインストール状態は変更しません
    plugins=[{"type": "local", "path": "./my-plugin-dev"}],
)
```

<div id="実行中のプラグインリロード" />

## 実行中のプラグインリロード

プラグインディレクトリに変更があった場合、同じ `QoderSDKClient` セッション内で `reload_plugins()` を呼び出すことで、CLI にプラグインリソースを再スキャンさせることができます。

```python theme={null}
async with QoderSDKClient(options) as client:
    refreshed = await client.reload_plugins()

    print(refreshed["commands"])
    print(refreshed["agents"])
    print(refreshed["plugins"])
    print(refreshed["mcpServers"])
    print(refreshed["error_count"])
```

典型的な用途：

* プラグイン開発時に `commands/*.md` を追加・削除した後のリフレッシュ。
* ローカルプラグインのインストールまたは更新後、ホストアプリケーションを再起動せずに反映。
* ホスト UI でリロード後の commands、agents、plugins、MCP 状態を表示する必要がある場合。

> 注意：`reload_plugins()` は `QoderSDKClient`（streaming）モードでのみ意味があります。使い切りの `query()` ストリームにはランタイム制御チャンネルがありません。

<div id="options-クイックリファレンス" />

<div id="optionsクイックリファレンス" />

## Options クイックリファレンス

| フィールド             | 型                                                   | 説明                                                                   |
| ----------------- | --------------------------------------------------- | -------------------------------------------------------------------- |
| `plugins`         | `list[SdkPluginConfig]`                             | ローカルプラグインディレクトリを読み込み。現在は `{"type": "local", "path": ...}` がよく使用されます  |
| `settings`        | `str \| Path \| dict[str, Any] \| None`             | CLI に渡す settings。`enabledPlugins`、`pluginConfigs` などのフィールドを含むことができます |
| `setting_sources` | `list[Literal["user", "project", "local"]] \| None` | CLI がどの settings ソースを読み込むかを制御                                        |

`settings.enabledPlugins`、`settings.pluginConfigs`、`settings.allowedChannelPlugins`、`settings.strictPluginOnlyCustomization` などのエンタープライズポリシーフィールドは SDK 型として透過的に渡されますが、実際のパスは具体的な CLI バージョンに依存します。使用前にご自身の環境で検証してください。

<div id="戻り値リファレンス" />

## 戻り値リファレンス

<div id="clientget_server_info-と-systemmessagesubtypeinitdata" />

<div id="clientget_server_infoとsystemmessagesubtypeinitdata" />

### `client.get_server_info()` と `SystemMessage(subtype='init').data`

```python theme={null}
{
    "commands": [
        {"name": "plugin-a:greet", "description": "...", "argumentHint": "..."},
        ...
    ],
    "agents": [
        {"name": "plugin-a:helper", "description": "...", "model": "sonnet"},
        ...
    ],
    "skills": [
        {"name": "plugin-a:echo", "description": "...", "source": "plugin"},
        ...
    ],
    "plugins": [
        {"name": "plugin-a", "path": "/path/to/plugin-a", "source": "local"},
        ...
    ],
    # models / account / output_style などのフィールドも含まれます
}
```

<div id="clientreload_plugins" />

<div id="client-reload_plugins" />

### `client.reload_plugins()`

`ReloadPluginsResponse` を返します。

```python theme={null}
{
    "commands": list[Any],
    "agents": list[Any],
    "plugins": list[PluginInfo],            # {"name": str, "path": str, "source": str?}
    "mcpServers": list[McpServerStatus],    # mcp.md の McpServerStatus を参照
    "error_count": int,                     # 今回の reload で読み込みに失敗したプラグイン数
}
```

<div id="ベストプラクティス" />

## ベストプラクティス

* **ホスト UI ではまず `get_server_info()` を読み取る**：commands、agents、skills、plugins を表示するための安定したエントリポイントです。使い切りの `query()` でこのデータを取得したい場合は `QoderSDKClient` に切り替えるか、メッセージストリーム内で `SystemMessage(subtype='init').data` を読み取ってください。
* **プラグイン開発時は `options.plugins` を使用**：現在のセッションにのみ影響し、ユーザーのグローバルインストール状態を変更する必要がありません。
* **リロード前にユーザープロンプトを準備**：`reload_plugins()` は CLI にディスクの再スキャンをトリガーし、利用可能なリソースリストが一時的に変わる可能性があるため、UI も同期的に更新することを推奨します。
* **エラー診断には `error_count` を確認**：リロード後に `error_count > 0` の場合はプラグインリソースの読み込みに失敗があることを示しており、そのソースをユーザーに表示すべきです。

<div id="現在の制限事項" />

## 現在の制限事項

* 一部の qodercli バージョンでは、ローカルプラグインの commands、agents、MCP は初期化結果に正常に表示されますが、プラグイン skills が `get_server_info()['skills']` に表示されない場合があります。これは CLI 側の発見パスの問題です。
* 現在の qodercli 実装では、存在しない `--plugin-dir` パスは SDK モードでサイレントに無視されます。プラグイン読み込み失敗を明示的に診断する必要がある場合、現在は `reload_plugins().error_count` でフォールバックするしかありません。
* `reload_plugins()` は `QoderSDKClient` が公開するランタイム制御 API です。現在の CLI バージョンが `this._plugins` 関連の内部エラーを返す場合は、修正済みの qodercli にアップグレードする必要があります。
* `settings.strictPluginOnlyCustomization`、`settings.allowedChannelPlugins`、`settings.pluginConfigs.<pid>.options` のテンプレート置換はすべて dict として透過的に渡されるフィールドであり、SDK は解析しません。実際に効くかどうかは CLI バージョンに完全に依存します。
