English ← MyDocs

文档索引

在此获取完整文档索引:https://code.claude.com/docs/llms.txt 使用此文件发现所有可用页面,然后再进一步探索。

SDK 中的插件

加载自定义插件以通过 Agent SDK 使用 skills、agents、hooks 和 MCP 服务器扩展 Claude Code

插件允许您使用可在项目间共享的自定义功能扩展 Claude Code。通过 Agent SDK,您可以以编程方式从本地目录加载插件,以向智能体会话添加 skills、agents、hooks 和 MCP 服务器。

什么是插件?

插件是 Claude Code 扩展的包,可以包含:

  • Skills:Claude 自主使用的模型调用能力(也可以通过 /skill-name 调用)
  • Agents:用于特定任务的专门子智能体
  • Hooks:响应工具使用和其他事件的事件处理器
  • MCP 服务器:通过模型上下文协议的外部工具集成
Note

commands/ 目录是旧格式。新插件请使用 skills/。Claude Code 继续支持两种格式以保持向后兼容性。

有关插件结构和如何创建插件的完整信息,请参阅插件

加载插件

通过在选项配置中提供插件的本地文件系统路径来加载插件。type 字段必须为 "local",这是 SDK 唯一接受的值。要使用通过市场或远程仓库分发的插件,请先下载并提供本地目录路径。SDK 支持从不同位置加载多个插件。

import { query } from "@anthropic-ai/claude-agent-sdk";

for await (const message of query({
  prompt: "Hello",
  options: {
    plugins: [
      { type: "local", path: "./my-plugin" },
      { type: "local", path: "/absolute/path/to/another-plugin" }
    ]
  }
})) {
  // Plugin commands, agents, and other features are now available
}
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions


async def main():
    async for message in query(
        prompt="Hello",
        options=ClaudeAgentOptions(
            plugins=[
                {"type": "local", "path": "./my-plugin"},
                {"type": "local", "path": "/absolute/path/to/another-plugin"},
            ]
        ),
    ):
        # Plugin commands, agents, and other features are now available
        pass


asyncio.run(main())

路径规范

插件路径可以是:

  • 相对路径:相对于当前工作目录解析(例如,"./plugins/my-plugin"
  • 绝对路径:完整的文件系统路径(例如,"/home/user/plugins/my-plugin"
Note

路径应指向插件的根目录(包含 .claude-plugin/plugin.json 的目录)。

验证插件安装

当插件成功加载时,它们会出现在系统初始化消息中。您可以验证您的插件是否可用:

import { query } from "@anthropic-ai/claude-agent-sdk";

for await (const message of query({
  prompt: "Hello",
  options: {
    plugins: [{ type: "local", path: "./my-plugin" }]
  }
})) {
  if (message.type === "system" && message.subtype === "init") {
    // Check loaded plugins
    console.log("Plugins:", message.plugins);
    // Example: [{ name: "my-plugin", path: "./my-plugin" }]

    // Plugin skills appear with the plugin name as a prefix
    console.log("Skills:", message.skills);
    // Example: ["my-plugin:greet"]

    // Plugin commands use the same prefix, and skills appear here too
    console.log("Commands:", message.slash_commands);
    // Example: ["compact", "context", "my-plugin:custom-command", "my-plugin:greet"]
  }
}
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, SystemMessage


async def main():
    async for message in query(
        prompt="Hello",
        options=ClaudeAgentOptions(
            plugins=[{"type": "local", "path": "./my-plugin"}]
        ),
    ):
        if isinstance(message, SystemMessage) and message.subtype == "init":
            # Check loaded plugins
            print("Plugins:", message.data.get("plugins"))
            # Example: [{"name": "my-plugin", "path": "./my-plugin"}]

            # Plugin skills appear with the plugin name as a prefix
            print("Skills:", message.data.get("skills"))
            # Example: ["my-plugin:greet"]

            # Plugin commands use the same prefix, and skills appear here too
            print("Commands:", message.data.get("slash_commands"))
            # Example: ["compact", "context", "my-plugin:custom-command", "my-plugin:greet"]


asyncio.run(main())

使用插件技能

来自插件的技能会自动以插件名称为命名空间以避免冲突。要直接调用一个,请发送 /plugin-name:skill-name 作为提示。

import { query } from "@anthropic-ai/claude-agent-sdk";

// Load a plugin with a custom /greet skill
for await (const message of query({
  prompt: "/my-plugin:greet", // Use plugin skill with namespace
  options: {
    plugins: [{ type: "local", path: "./my-plugin" }]
  }
})) {
  // Claude executes the custom greeting skill from the plugin
  if (message.type === "assistant") {
    console.log(message.message.content);
  }
}
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, AssistantMessage, TextBlock


async def main():
    # Load a plugin with a custom /greet skill
    async for message in query(
        prompt="/demo-plugin:greet",  # Use plugin skill with namespace
        options=ClaudeAgentOptions(
            plugins=[{"type": "local", "path": "./plugins/demo-plugin"}]
        ),
    ):
        # Claude executes the custom greeting skill from the plugin
        if isinstance(message, AssistantMessage):
            for block in message.content:
                if isinstance(block, TextBlock):
                    print(f"Claude: {block.text}")


asyncio.run(main())
Note

如果您通过 CLI 安装了插件(例如,/plugin install my-plugin@marketplace),您仍然可以通过提供其安装路径在 SDK 中使用它。检查 ~/.claude/plugins/ 以查找 CLI 安装的插件。

完整示例

以下是演示插件加载和使用的完整示例:

import { query } from "@anthropic-ai/claude-agent-sdk";
import * as path from "path";

async function runWithPlugin() {
  const pluginPath = path.join(__dirname, "plugins", "my-plugin");

  console.log("Loading plugin from:", pluginPath);

  for await (const message of query({
    prompt: "What custom commands do you have available?",
    options: {
      plugins: [{ type: "local", path: pluginPath }],
      maxTurns: 3
    }
  })) {
    if (message.type === "system" && message.subtype === "init") {
      console.log("Loaded plugins:", message.plugins);
      console.log("Available skills:", message.skills);
      console.log("Available commands:", message.slash_commands);
    }

    if (message.type === "assistant") {
      console.log("Assistant:", message.message.content);
    }
  }
}

runWithPlugin().catch(console.error);
#!/usr/bin/env python3
"""Example demonstrating how to use plugins with the Agent SDK."""

from pathlib import Path
import anyio
from claude_agent_sdk import (
    AssistantMessage,
    ClaudeAgentOptions,
    SystemMessage,
    TextBlock,
    query,
)


async def run_with_plugin():
    """Example using a custom plugin."""
    plugin_path = Path(__file__).parent / "plugins" / "demo-plugin"

    print(f"Loading plugin from: {plugin_path}")

    options = ClaudeAgentOptions(
        plugins=[{"type": "local", "path": str(plugin_path)}],
        max_turns=3,
    )

    async for message in query(
        prompt="What custom commands do you have available?", options=options
    ):
        if isinstance(message, SystemMessage) and message.subtype == "init":
            print(f"Loaded plugins: {message.data.get('plugins')}")
            print(f"Available skills: {message.data.get('skills')}")
            print(f"Available commands: {message.data.get('slash_commands')}")

        if isinstance(message, AssistantMessage):
            for block in message.content:
                if isinstance(block, TextBlock):
                    print(f"Assistant: {block.text}")


if __name__ == "__main__":
    anyio.run(run_with_plugin)

插件结构参考

插件目录必须包含 .claude-plugin/plugin.json 清单文件。它可以可选地包含:

my-plugin/
├── .claude-plugin/
│   └── plugin.json          # Required: plugin manifest
├── skills/                   # Agent Skills (invoked autonomously or via /skill-name)
│   └── my-skill/
│       └── SKILL.md
├── commands/                 # Legacy: use skills/ instead
│   └── custom-cmd.md
├── agents/                   # Custom agents
│   └── specialist.md
├── hooks/                    # Event handlers
│   └── hooks.json
└── .mcp.json                # MCP server definitions

有关创建插件的详细信息,请参阅:

常见用例

开发和测试

在开发期间加载插件而无需全局安装:

plugins: [{ type: "local", path: "./dev-plugins/my-plugin" }];

项目特定扩展

在项目仓库中包含插件以实现团队范围的一致性:

plugins: [{ type: "local", path: "./project-plugins/team-workflows" }];

多插件来源

组合来自不同位置的插件:

plugins: [
  { type: "local", path: "./local-plugin" },
  { type: "local", path: "~/.claude/custom-plugins/shared-plugin" }
];

故障排除

插件未加载

如果您的插件未出现在初始化消息中:

  1. 检查路径:确保路径指向插件根目录(包含 .claude-plugin/
  2. 验证 plugin.json:确保清单文件具有有效的 JSON 语法
  3. 检查文件权限:确保插件目录可读

技能未出现

如果插件技能不工作:

  1. 使用命名空间:将插件技能调用为 /plugin-name:skill-name
  2. 检查初始化消息:验证技能是否出现在带有正确命名空间的 skills 列表中
  3. 验证技能文件:确保每个技能在 skills/ 下有自己的子目录中有 SKILL.md 文件,例如 skills/my-skill/SKILL.md

路径解析问题

如果相对路径不工作:

  1. 检查工作目录:相对路径从当前工作目录解析
  2. 使用绝对路径:为可靠性考虑使用绝对路径
  3. 规范化路径:使用路径工具正确构造路径

另请参阅