Skip to main content
Extensions

Plugins

options.plugins is used to load local plugin directories into the current query session. The SDK converts each local plugin into a --plugin-dir <path> startup argument; commands, agents, skills, and MCP servers included in the plugin are automatically discovered and available for the session.

Loading Local Plugins

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.skills);

const plugins = await q.listPlugins();
console.log(plugins);
You can pass multiple local plugins at once:
const q = query({
  options: {
    plugins: [
      { type: 'local', path: '/path/to/plugin-a' },
      { type: 'local', path: '/path/to/plugin-b' },
    ],
  },
});

Plugin Directory Layout

A local plugin typically contains:
my-plugin/
  .qoder-plugin/plugin.json
  commands/
  agents/
  skills/
  .mcp.json
.qoder-plugin/plugin.json declares the plugin name, version, and description. The other directories are automatically scanned by the CLI based on file type.

Plugin-contributed Slash Commands

commands/*.md files in the plugin will appear in the initialization result and in supportedCommands().
const commands = await q.supportedCommands();
console.log(commands.map((cmd) => cmd.name));

Plugin-contributed Agents

agents/*.md files in the plugin will appear in the initialization result and in supportedAgents().
const agents = await q.supportedAgents();
console.log(agents.map((agent) => agent.name));

Plugin-contributed Skills

skills/*/SKILL.md files in the plugin are registered with a plugin-qualified name (plugin:skill). Use options.skills to control main-session context visibility and invocation policy: pass a plugin-qualified name to enable one skill, pass 'all' to enable every discovered skill, or omit the option to keep the CLI default policy. See Skills documentation.

Plugin-contributed MCP Servers

.mcp.json in the plugin is started by the CLI and included in the MCP status.
const servers = await q.mcpServerStatus();
console.log(servers);

Temporarily Overriding an Installed Plugin with the Same Name

Plugins loaded via options.plugins are session-scoped. During the current session, if a local plugin shares a name with an installed plugin, the local plugin takes priority in capability discovery. This is useful for plugin development, debugging, and canary testing.
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' }],
  },
});

Reloading Plugins at Runtime

If the plugin directory changes, you can call reloadPlugins() within the same query session to have the CLI rescan plugin resources.
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);
Typical use cases:
  • Refreshing after adding or deleting commands/*.md during plugin development.
  • After installing or updating a local plugin without restarting the host application.
  • When the host UI needs to display commands, agents, plugins, and MCP status after a reload.

Options Reference

FieldTypeDescription
pluginsSdkPluginConfig[]Load local plugin directories; currently the common form is { type: 'local', path }
settingsstring | SettingsSettings passed to the CLI, which can include fields like enabledPlugins, pluginConfigs, etc.
settingSources('user' | 'project' | 'local')[]Controls which settings sources the CLI reads
Use settings.enabledPlugins to control plugin enablement and settings.pluginConfigs to provide MCP server substitutions for a plugin.

Return Value Reference

initializationResult()

Returns initialization resources discovered for the current session, including commands, agents, and skills. It does not expose a stable plugin-inventory field. See SDKControlInitializeResponse for the complete return type.

listPlugins()

listPlugins(): Promise<PluginDetails[]>;
Reads the current CLI plugin inventory and the resource summary for each plugin. Host UIs should use this method for plugin inventory instead of reading initializationResult().plugins.

reloadPlugins()

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

Best Practices

  • Separate initialization resources from plugin inventory: Use initializationResult() for discovered commands, agents, and skills, and use listPlugins() for plugin inventory. Skills in the initialization result are a discovery inventory, not every skill currently callable by the main session.
  • Use options.plugins during plugin development: It only affects the current session without modifying the user's global install state.
  • Prepare user prompts before reloading: reloadPlugins() triggers the CLI to rescan disk, which may briefly change the available resource list; synchronize UI updates accordingly.
  • Check error_count for diagnostics: If error_count > 0 after reload, some plugin resources failed to load; display the source to the user.

Current Limitations

  • In some qodercli versions, local plugin commands, agents, and MCP can appear correctly in the initialization result, but plugin skills may not appear in initializationResult().skills — this is a CLI-side discovery pipeline issue.
  • Under the current qodercli implementation, non-existent --plugin-dir paths are silently ignored in SDK mode; to explicitly diagnose plugin loading failures, currently the only option is reloadPlugins().error_count as a fallback.
  • reloadPlugins() is a runtime control API exposed by the SDK; if the current CLI version returns internal errors related to this._plugins, an upgrade to the fixed qodercli is needed.