Appearance
通过 Agent SDK 加载本地插件,可以为 Claude Code 添加自定义技能、代理、钩子和 MCP 服务器。配置时需指定插件根目录路径(指向包含 .claude-plugin/plugin.json 的文件夹),type 固定为 "local"。加载成功后可在系统初始化消息中查看已加载插件和斜杠命令。技能调用使用 plugin-name:skill-name 命名空间格式;如果相对路径不生效,改用绝对路径。
Claude Code Agent SDK 插件加载与配置
通过 Agent SDK 加载自定义插件,扩展 Claude Code 的命令、代理、技能和钩子功能。
插件让你能为 Claude Code 添加可跨项目共享的自定义功能。通过 Agent SDK,你可以从本地目录加载插件,为会话添加自定义斜杠命令、代理、技能、钩子和 MCP 服务器。
插件包含什么
一个插件可以包含以下扩展:
- 技能(Skills):Claude 自主调用的能力(也可用
/skill-name调用) - 代理(Agents):用于特定任务的专用子代理
- 钩子(Hooks):响应工具调用等事件的事件处理器
- MCP 服务器:通过 Model Context Protocol 集成外部工具
commands/目录是遗留格式。新建插件请使用skills/。Claude Code 仍兼容两种格式。
插件完整结构和创建方法见插件开发指南。
怎么配置插件加载
在选项配置中提供本地文件系统路径来加载插件。type 字段必须为 "local",这是 SDK 唯一接受的值。如果要用市场或远程仓库分发的插件,先下载到本地,再提供路径。SDK 支持从不同位置加载多个插件。
typescript
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" }
]
}
})) {
// 插件提供的命令、代理等功能已可用
}python
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"},
]
),
):
# 插件功能已可用
pass
asyncio.run(main())路径类型
插件路径可以是:
- 相对路径:相对于当前工作目录解析(例如
"./plugins/my-plugin") - 绝对路径:完整的文件系统路径(例如
"/home/user/plugins/my-plugin")
路径应指向插件根目录(包含
.claude-plugin/plugin.json的目录)。
怎么验证插件加载成功
插件加载成功后,会出现在系统初始化消息中。可以通过以下代码验证:
typescript
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") {
console.log("已加载插件:", message.plugins);
// 示例: [{ name: "my-plugin", path: "./my-plugin" }]
console.log("可用命令:", message.slash_commands);
// 示例: ["/help", "/compact", "my-plugin:custom-command"]
}
}python
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":
print("Plugins:", message.data.get("plugins"))
# 示例: [{"name": "my-plugin", "path": "./my-plugin"}]
print("Commands:", message.data.get("slash_commands"))
# 示例: ["/help", "/compact", "my-plugin:custom-command"]
asyncio.run(main())怎么调用插件技能
插件的技能会自动加命名空间(插件名称),避免冲突。作为斜杠命令调用时,格式为 plugin-name:skill-name。
typescript
import { query } from "@anthropic-ai/claude-agent-sdk";
// 加载一个包含自定义 /greet 技能的插件
for await (const message of query({
prompt: "/my-plugin:greet", // 使用命名空间调用插件技能
options: {
plugins: [{ type: "local", path: "./my-plugin" }]
}
})) {
if (message.type === "assistant") {
console.log(message.message.content);
}
}python
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, AssistantMessage, TextBlock
async def main():
# 加载一个包含自定义 /greet 技能的插件
async for message in query(
prompt="/demo-plugin:greet", # 使用命名空间调用插件技能
options=ClaudeAgentOptions(
plugins=[{"type": "local", path": "./plugins/demo-plugin"}]
),
):
if isinstance(message, AssistantMessage):
for block in message.content:
if isinstance(block, TextBlock):
print(f"Claude: {block.text}")
asyncio.run(main())如果你通过 CLI 安装了插件(例如
/plugin install my-plugin@marketplace),可以在 SDK 中直接使用其安装路径。CLI 安装的插件通常在~/.claude/plugins/。
完整示例
typescript
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 commands:", message.slash_commands);
}
if (message.type === "assistant") {
console.log("Assistant:", message.message.content);
}
}
}
runWithPlugin().catch(console.error);python
#!/usr/bin/env python3
from pathlib import Path
import anyio
from claude_agent_sdk import (
AssistantMessage,
ClaudeAgentOptions,
SystemMessage,
TextBlock,
query,
)
async def run_with_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 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 清单文件。可选目录如下:
text
my-plugin/
├── .claude-plugin/
│ └── plugin.json # 必需:插件清单
├── skills/ # 技能(自主调用或 /skill-name 调用)
│ └── my-skill/
│ └── SKILL.md
├── commands/ # 遗留:请改用 skills/
│ └── custom-cmd.md
├── agents/ # 自定义代理
│ └── specialist.md
├── hooks/ # 事件处理器
│ └── hooks.json
└── .mcp.json # MCP 服务器定义详细创建指南请参考:
常见使用场景
开发与测试
在开发阶段加载插件,无需全局安装:
typescript
plugins: [{ type: "local", path: "./dev-plugins/my-plugin" }];项目专用扩展
将插件包含在项目仓库中,确保团队一致性:
typescript
plugins: [{ type: "local", path: "./project-plugins/team-workflows" }];多插件来源
从不同位置组合加载插件:
typescript
plugins: [
{ type: "local", path: "./local-plugin" },
{ type: "local", path: "~/.claude/custom-plugins/shared-plugin" }
];常见问题
插件加载后看不到技能怎么办?
检查技能是否出现在初始化消息的 slash_commands 中。插件技能必须以 plugin-name:skill-name 格式调用。确保每个技能文件位于 skills/ 下的独立子目录中,例如 skills/my-skill/SKILL.md。
相对路径不生效怎么解决?
相对路径基于当前工作目录解析。确认工作目录是否正确。如果问题持续,改用绝对路径,或使用路径工具(如 path.join)正确构造路径。
插件加载失败时怎么排查?
检查路径是否指向包含 .claude-plugin/ 的根目录,验证 plugin.json 的 JSON 语法是否正确,并确认插件目录有读取权限。加载失败时不会报错,但技能不会出现在 slash_commands 中。