> ## 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` 用来把本地 plugin 目录加载进当前 query 会话。SDK 会为每个本地 plugin 转成一个 `--plugin-dir <path>` 启动参数；插件里包含的 commands、agents、skills 和 MCP servers 都会参与本次会话的能力发现。

<div id="加载本地-plugin" />

## 加载本地 plugin

```typescript theme={null}
import { query } from '@qoder-ai/qoder-agent-sdk';

const q = query({
  prompt: 'List the commands and agents contributed by the current plugins',
  options: {
    plugins: [
      { type: 'local', path: '/path/to/my-plugin' },
    ],
  },
});

const init = await q.initializationResult();
console.log(init.commands);
console.log(init.agents);
console.log(init.plugins);
```

可以同时传多个本地 plugin：

```typescript theme={null}
const q = query({
  options: {
    plugins: [
      { type: 'local', path: '/path/to/plugin-a' },
      { type: 'local', path: '/path/to/plugin-b' },
    ],
  },
});
```

***

<div id="插件目录布局" />

## 插件目录布局

一个本地 plugin 通常可以包含：

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

`.qoder-plugin/plugin.json` 用来声明插件名、版本、描述。其余目录按文件类型自动被 CLI 扫描。

***

<div id="插件贡献-slash-commands" />

## 插件贡献 slash commands

插件里的 `commands/*.md` 会出现在初始化结果和 `supportedCommands()` 中。

```typescript theme={null}
const commands = await q.supportedCommands();
console.log(commands.map((cmd) => cmd.name));
```

<div id="插件贡献-agents" />

## 插件贡献 agents

插件里的 `agents/*.md` 会出现在初始化结果和 `supportedAgents()` 中。

```typescript theme={null}
const agents = await q.supportedAgents();
console.log(agents.map((agent) => agent.name));
```

<div id="插件贡献-skills" />

## 插件贡献 skills

插件里的 `skills/*/SKILL.md` 会以插件限定名（`plugin:skill`）注册。要让主会话能调用，需要在 `options.skills` 里显式列出，见 [Skills 文档](/zh/cli/sdk/skills#启用插件内-skill)。

<div id="插件贡献-mcp-servers" />

## 插件贡献 MCP servers

插件里的 `.mcp.json` 会由 CLI 启动并纳入 MCP 状态。

```typescript theme={null}
const servers = await q.mcpServerStatus();
console.log(servers);
```

***

<div id="临时覆盖已安装同名插件" />

## 临时覆盖已安装同名插件

通过 `options.plugins` 加载的本地 plugin 是 session-scoped。当前会话中，如果它和已安装插件同名，本地 plugin 会优先参与本次会话能力发现。这个能力适合做 plugin 开发、调试和灰度验证。

```typescript theme={null}
const q = query({
  options: {
    // The local version only takes effect for this query session and does not
    // touch the user's global install state.
    plugins: [{ type: 'local', path: './my-plugin-dev' }],
  },
});
```

***

<div id="运行中重新加载-plugins" />

## 运行中重新加载 Plugins

如果 plugin 目录发生变化，可以在同一个 query 会话里调用 `reloadPlugins()`，让 CLI 重新扫描 plugin 资源。

```typescript theme={null}
const refreshed = await q.reloadPlugins();

console.log(refreshed.commands);
console.log(refreshed.agents);
console.log(refreshed.plugins);
console.log(refreshed.mcpServers);
console.log(refreshed.error_count);
```

典型用途：

* 开发 plugin 时新增或删除 `commands/*.md` 后刷新。
* 安装或更新本地 plugin 后，不重启宿主应用。
* 宿主 UI 需要展示 reload 后的 commands、agents、plugins 和 MCP 状态。

***

<div id="options-速查" />

## Options 速查

| 字段               | 类型                                   | 说明                                                           |
| ---------------- | ------------------------------------ | ------------------------------------------------------------ |
| `plugins`        | `SdkPluginConfig[]`                  | 加载本地 plugin 目录，目前常用 `{ type: 'local', path }`                |
| `settings`       | `string \| Settings`                 | 透传给 CLI 的 settings，可以包含 `enabledPlugins`、`pluginConfigs` 等字段 |
| `settingSources` | `('user' \| 'project' \| 'local')[]` | 控制 CLI 读取哪些 settings 来源                                      |

`settings.enabledPlugins`、`settings.pluginConfigs`、`settings.allowedChannelPlugins`、`settings.strictPluginOnlyCustomization` 这类企业策略字段 SDK 类型已透传，但实际链路依赖具体 CLI 版本，使用前请结合自己环境验证。

***

<div id="返回值参考" />

## 返回值参考

<div id="initializationresult" />

### `initializationResult()`

```typescript theme={null}
type SDKControlInitializeResponse = {
  commands?: Array<{ name: string; description?: string; argumentHint?: string }>;
  agents?: Array<{ name: string; description?: string; model?: string }>;
  skills?: Array<{ name: string; description?: string; source?: string }>;
  plugins?: Array<{ name: string; path: string; source?: string }>;
  // Also includes models, account, output_style and other fields
};
```

<div id="reloadplugins" />

### `reloadPlugins()`

```typescript theme={null}
type SDKControlReloadPluginsResponse = {
  commands: Array<{ name: string; description?: string; argumentHint?: string }>;
  agents: Array<{ name: string; description?: string }>;
  plugins: Array<{ name: string; path: string; source?: string }>;
  mcpServers: Array<Record<string, unknown>>;
  error_count: number;
};
```

***

<div id="最佳实践" />

## 最佳实践

* **给宿主 UI 先读 `initializationResult()`**：它是展示 commands、agents、skills、plugins 的稳定入口。
* **开发 plugin 时使用 `options.plugins`**：它只影响当前会话，不需要修改用户全局安装状态。
* **reload 之前先准备好用户提示**：`reloadPlugins()` 会触发 CLI 重新扫描磁盘，可能短暂改变可用资源列表，UI 上最好同步更新。
* **错误诊断看 `error_count`**：reload 后 `error_count > 0` 表示有 plugin 资源加载失败，应该把它的来源展示给用户。

***

<div id="当前限制" />

## 当前限制

* 部分 qodercli 版本下，本地 plugin 的 commands、agents、MCP 可以正常出现在初始化结果中，但 plugin skills 可能没有出现在 `initializationResult().skills`，这属于 CLI 侧发现链路问题。
* 当前 qodercli 实现下，不存在的 `--plugin-dir` 路径在 SDK 模式里会被静默忽略；如果需要显式诊断 plugin 加载失败，目前只能通过 `reloadPlugins().error_count` 兜底。
* `reloadPlugins()` 是 SDK 暴露的运行时控制 API；如果当前 CLI 版本返回 `this._plugins` 相关内部错误，需要升级到修复后的 qodercli。
