Skip to main content
工具与扩展

Plugins

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

加载本地 plugin

import { query } from '@qodercn-ai/qodercn-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.skills);

const plugins = await q.listPlugins();
console.log(plugins);
可以同时传多个本地 plugin,会按顺序写出多次 --plugin-dir:
const q = query({
  options: {
    plugins: [
      { type: 'local', path: '/path/to/plugin-a' },
      { type: 'local', path: '/path/to/plugin-b' },
    ],
  },
});
💡 Python 中 query() 是一次性的消息流,无法在握手后查询 init 响应。要读取插件贡献的命令 / agent / skill,请用 QoderSDKClient 并在 connect() 之后调用 get_server_info(),或在消息流里捕获 SystemMessage(subtype='init') 自行读取 message.data。要读取完整 plugin inventory,请调用 client.list_plugins()。

插件目录布局

一个本地 plugin 通常可以包含:
my-plugin/
  .qoder-plugin/plugin.json
  commands/
  agents/
  skills/
  .mcp.json
.qoder-plugin/plugin.json 用来声明插件名、版本、描述。其余目录按文件类型自动被 CLI 扫描。 SDK 不会校验路径是否存在 / 是否合法:
  • 不存在的 --plugin-dir 路径在 SDK 模式里会被静默忽略,会话仍正常初始化。
  • 损坏的 frontmatter / .mcp.json 不阻断 init,损坏的命令不会出现在 init 响应中。
  • 想显式诊断 plugin 加载失败,目前只能依赖 reload 后的 error_count 兜底。

插件贡献 slash commands

插件里的 commands/*.md 会出现在初始化结果中,名称以 <plugin>:<cmd> 限定名形式出现:
const commands = await q.supportedCommands();
console.log(commands.map((cmd) => cmd.name));

插件贡献 agents

插件里的 agents/*.md 会出现在初始化结果中,SDK 提供便捷方法直接拿到这份列表:
const agents = await q.supportedAgents();
console.log(agents.map((agent) => agent.name));

插件贡献 skills

插件里的 skills/<name>/SKILL.md 会以插件限定名(plugin:skill)注册。可通过 options.skills 控制它在主会话中的上下文可见性与调用策略:传插件限定名启用指定 skill,传 'all' 启用全部已发现 skills;不传则使用 CLI 默认策略。见 Skills 文档。

插件贡献 MCP servers

插件里的 .mcp.json 会由 CLI 启动并纳入 MCP 状态:
const servers = await q.mcpServerStatus();
console.log(servers);

临时覆盖已安装同名插件

通过 options.plugins 加载的本地 plugin 是 session-scoped。当前会话中,如果它和已安装插件同名,本地 plugin 会优先参与本次会话能力发现。这个能力适合做 plugin 开发、调试和灰度验证。
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' }],
  },
});

运行中重新加载 Plugins

如果 plugin 目录发生变化,可以在同一个会话里调用 reloadPlugins() / reload_plugins(),让 CLI 重新扫描 plugin 资源。
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 状态。
注意:Python 中 reload_plugins() 只在 QoderSDKClient(streaming)模式下有意义;一次性的 query() 流没有运行时控制 channel。

管理已安装插件(TypeScript)

TypeScript SDK 提供一组不依赖活动会话的顶层函数,用于校验、列出、安装、卸载、启用和禁用插件:
import {
  disablePlugin,
  enablePlugin,
  installPlugin,
  listPlugins,
  uninstallPlugin,
  validatePlugin,
} from '@qoder-ai/qoder-agent-sdk';

const cwd = '/path/to/project';
const pluginPath = '/path/to/project/my-plugin';
const report = await validatePlugin(pluginPath);
const plugins = await listPlugins({ cwd });

if (report.valid) {
  const installed = await installPlugin(pluginPath, {
    scope: 'project',
    cwd,
  });

  await disablePlugin(installed.pluginId, { scope: 'project', cwd });
  await enablePlugin(installed.pluginId, { scope: 'project', cwd });

  await uninstallPlugin(installed.pluginId, {
    scope: 'project',
    cwd,
    keepData: true,
  });
}
installPlugin() 和 uninstallPlugin() 支持 user、project、local 三种 scope,默认值为 user。使用 project 或 local 时应传入 cwd,用来确定要修改的项目:
Scope行为
user对当前用户的所有项目生效;默认值
project写入 cwd 下的项目级 settings.json,可以提交到版本控制
local写入 cwd 下的 settings.local.json,仅供本机使用
installPlugin() 返回 { pluginId, version, path }。uninstallPlugin() 返回 { pluginId, fullyRemoved, reverseDependents };keepData: true 会保留插件数据目录。 顶层 listPlugins() 返回配套 qodercli 报告的所有安装项。CLI 提供项目路径时,仅 project 和 local 安装行填充 projectPath;user 及其他非项目安装行省略该字段。enabled 表示插件在 cwd 下的有效状态;未传 cwd 时使用 SDK 进程的当前工作目录。会话方法 q.listPlugins() 返回当前会话实际加载的插件。 这些函数通过配套 qodercli 执行操作,失败时抛出的 Error 包含稳定的 code 字段。 如果已有会话正在运行,完成安装、卸载、启用或禁用后,调用 q.reloadPlugins() 让变更在该会话中生效。

Options 速查

字段(TypeScript / Python)说明
plugins / plugins加载本地 plugin 目录,目前常用 { type: 'local', path }
settings / settings透传给 CLI 的 settings,可以包含 enabledPlugins、pluginConfigs 等字段
settingSources / setting_sources控制 CLI 读取哪些 settings 来源
使用 settings.enabledPlugins 控制插件启用状态,使用 settings.pluginConfigs 为插件提供 MCP server 替换等配置。

返回值参考

初始化结果

initializationResult()(TypeScript)/ client.get_server_info()(Python)返回当前会话发现到的 commands、agents、skills 等初始化资源。它不包含稳定的 plugin inventory 字段;完整返回类型见 SDK References。
{
    "commands": [
        {"name": "plugin-a:greet", "description": "...", "argumentHint": "..."},
        ...
    ],
    "agents": [
        {"name": "plugin-a:helper", "description": "...", "model": "sonnet"},
        ...
    ],
    "skills": [
        {"name": "plugin-a:echo", "description": "...", "source": "plugin"},
        ...
    ],
    # Also includes models / account / output_style and other fields
}

列出当前会话中的插件

q.listPlugins(): Promise<PluginDetails[]>;
读取当前会话实际加载的 plugin 清单和每个 plugin 的资源摘要。宿主 UI 要展示当前会话的 plugin inventory 时应使用这个方法,而不是读取初始化结果里的 plugins 字段。要在不创建会话的情况下列出已安装插件,使用顶层 listPlugins()。 每一项是 PluginDetails,包含 id、name、source、path、version、scope、enabled、canDisable,以及按 skills、agents、mcpServers、commands、hooks 分类的 resources。

重新加载插件

reloadPlugins() / reload_plugins() 返回:
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;  // Number of plugins that failed to load in this reload
};

最佳实践

  • 区分初始化资源和 plugin 清单:使用初始化结果展示已发现 commands、agents、skills;使用 q.listPlugins() / client.list_plugins() 展示当前会话的 plugin inventory,使用顶层 listPlugins() 展示已安装插件。其中初始化结果里的 skills 是发现清单,不代表主会话当前全部可调用。
  • 开发 plugin 时使用 options.plugins:它只影响当前会话,不需要修改用户全局安装状态。
  • reload 之前先准备好用户提示:reload 会触发 CLI 重新扫描磁盘,可能短暂改变可用资源列表,UI 上最好同步更新。
  • 错误诊断看 error_count:reload 后 error_count > 0 表示有 plugin 资源加载失败,应该把它的来源展示给用户。

当前限制

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