{/* TRANSLATED — 已翻译为中文 */}

> ## 文档索引
> 在此获取完整文档索引：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 继续支持两种格式以保持向后兼容性。
</Note>

有关插件结构和如何创建插件的完整信息，请参阅[插件](/en/plugins)。

## 加载插件

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

<CodeGroup>
  ```typescript TypeScript theme={null}
  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
  }
  ```

  ```python Python theme={null}
  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())
  ```
</CodeGroup>

### 路径规范

插件路径可以是：

* **相对路径**：相对于当前工作目录解析（例如，`"./plugins/my-plugin"`）
* **绝对路径**：完整的文件系统路径（例如，`"/home/user/plugins/my-plugin"`）

<Note>
  路径应指向插件的根目录（包含 `.claude-plugin/plugin.json` 的目录）。
</Note>

## 验证插件安装

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

<CodeGroup>
  ```typescript TypeScript theme={null}
  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"]
    }
  }
  ```

  ```python Python theme={null}
  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())
  ```
</CodeGroup>

## 使用插件技能

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

<CodeGroup>
  ```typescript TypeScript theme={null}
  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);
    }
  }
  ```

  ```python Python theme={null}
  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())
  ```
</CodeGroup>

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

## 完整示例

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

<CodeGroup>
  ```typescript TypeScript theme={null}
  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);
  ```

  ```python Python theme={null}
  #!/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)
  ```
</CodeGroup>

## 插件结构参考

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

```text theme={null}
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
```

有关创建插件的详细信息，请参阅：

* [插件](/en/plugins) - 完整的插件开发指南
* [插件参考](/en/plugins-reference) - 技术规范和模式

## 常见用例

### 开发和测试

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

```typescript theme={null}
plugins: [{ type: "local", path: "./dev-plugins/my-plugin" }];
```

### 项目特定扩展

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

```typescript theme={null}
plugins: [{ type: "local", path: "./project-plugins/team-workflows" }];
```

### 多插件来源

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

```typescript theme={null}
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. **规范化路径**：使用路径工具正确构造路径

## 另请参阅

* [插件](/en/plugins) - 完整的插件开发指南
* [插件参考](/en/plugins-reference) - 技术规范
* [命令](/en/agent-sdk/slash-commands) - 在 SDK 中使用命令
* [子智能体](/en/agent-sdk/subagents) - 使用专门的智能体
* [Skills](/en/agent-sdk/skills) - 使用 Agent Skills
