رفتن به محتوا

Plugin‌ها در SDK

Plugins به تو امکان می‌دهند Claude Code را با قابلیتِ سفارشی گسترش بدهی که می‌تواند بینِ پروژه‌ها به اشتراک گذاشته شود. از طریقِ Agent SDK، می‌توانی به‌صورتِ برنامه‌نویسی‌شده plugin‌ها را از دایرکتوری‌های محلی بارگذاری کنی تا skillها، agentها، hookها و سرورهای MCP را به نشست‌های ایجنتِ خود اضافه کنی.

Plugin‌ها بسته‌هایی از افزونه‌های Claude Code هستند که می‌توانند شامل این‌ها باشند:

  • Skills: قابلیت‌هایی که توسطِ مدل فراخوانی می‌شوند و Claude به‌صورتِ خودمختار از آن‌ها استفاده می‌کند (با /skill-name هم می‌توان فراخوانی‌شان کرد)
  • Agents: ساب‌ایجنت‌های تخصصی برای تسک‌های مشخص
  • Hooks: رسیدگ‌کننده‌های event که به استفاده از ابزار و سایر eventها پاسخ می‌دهند
  • MCP servers: یکپارچه‌سازی‌های ابزارِ بیرونی از طریقِ Model Context Protocol

برای اطلاعاتِ کامل درباره‌ی ساختارِ plugin و نحوه‌ی ساختِ plugin، Plugins را ببین.

plugin‌ها را با فراهم‌کردنِ مسیرهای فایل‌سیستمِ محلی‌شان در پیکربندیِ optionsِ خود بارگذاری کن. فیلدِ type باید "local" باشد، که تنها مقداری است که SDK می‌پذیرد. برای استفاده از pluginی که از طریقِ یک marketplace یا مخزنِ remote توزیع شده، اول آن را دانلود کن و مسیرِ دایرکتوریِ محلی را فراهم کن. SDK از بارگذاریِ چند plugin از مکان‌های مختلف پشتیبانی می‌کند.

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())

مسیرهای plugin می‌توانند این‌ها باشند:

  • مسیرهای نسبی: نسبت به دایرکتوریِ کاریِ فعلیِ تو حل می‌شوند (مثلاً "./plugins/my-plugin")
  • مسیرهای مطلق: مسیرهای کاملِ فایل‌سیستم (مثلاً "/home/user/plugins/my-plugin")

وقتی plugin‌ها با موفقیت بارگذاری شوند، در پیامِ راه‌اندازیِ سیستم ظاهر می‌شوند. می‌توانی تأیید کنی که plugin‌هایت در دسترس‌اند:

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())

skillهای plugin‌ها برای جلوگیری از تداخل به‌صورتِ خودکار با نامِ plugin namespace می‌شوند. برای فراخوانیِ مستقیمِ یکی از آن‌ها، /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())

این یک مثالِ کامل است که بارگذاری و استفاده از plugin را نشان می‌دهد:

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)

یک دایرکتوریِ plugin معمولاً یک فایلِ manifestِ .claude-plugin/plugin.json دارد. این manifest اختیاری است. وقتی حذف شود، Claude Code اجزا را از چیدمانِ دایرکتوری خودکار کشف می‌کند. دایرکتوری می‌تواند شامل این‌ها باشد:

my-plugin/
├── .claude-plugin/
│ └── plugin.json # Plugin manifest (optional, components auto-discovered without it)
├── 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

برای اطلاعاتِ مفصل درباره‌ی ساختِ plugin، این‌ها را ببین:

plugin‌ها را در حینِ توسعه بدونِ نصبِ سراسری بارگذاری کن:

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

افزونه‌های مخصوصِ پروژه

Section titled “افزونه‌های مخصوصِ پروژه”

plugin‌ها را برای یکدستیِ در سطحِ تیم در مخزنِ پروژه‌ات بگنجان:

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

plugin‌ها را از مکان‌های مختلف ترکیب کن:

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

اگر plugin‌ات در پیامِ init ظاهر نشد:

  1. مسیر را بررسی کن: مطمئن شو مسیر به دایرکتوریِ ریشه‌ی plugin اشاره می‌کند، یعنی والدِ skills/، agents/، hooks/، commands/ (legacy) یا .claude-plugin/
  2. plugin.json را اعتبارسنجی کن: اگر plugin‌ات یک manifest دارد، مطمئن شو نحوِ JSON معتبری دارد
  3. دسترسی‌های فایل را بررسی کن: مطمئن شو دایرکتوریِ plugin قابلِ‌خواندن است

اگر skillهای plugin کار نمی‌کنند:

  1. از namespace استفاده کن: skillهای plugin را به‌صورتِ /plugin-name:skill-name فراخوانی کن
  2. پیامِ init را بررسی کن: تأیید کن که skill با namespaceِ درست در فهرستِ skills ظاهر می‌شود
  3. فایل‌های skill را اعتبارسنجی کن: مطمئن شو هر skill یک فایلِ SKILL.md در زیردایرکتوریِ خودش زیرِ skills/ دارد، مثلاً skills/my-skill/SKILL.md

اگر مسیرهای نسبی کار نمی‌کنند:

  1. دایرکتوریِ کاری را بررسی کن: مسیرهای نسبی از دایرکتوریِ کاریِ فعلیِ تو حل می‌شوند
  2. از مسیرهای مطلق استفاده کن: برای اطمینان، استفاده از مسیرهای مطلق را در نظر بگیر
  3. مسیرها را نرمال‌سازی کن: از ابزارهای کار با مسیر برای ساختِ درستِ مسیرها استفاده کن
  • Plugins - راهنمای کاملِ توسعه‌ی plugin
  • Plugins reference - مشخصاتِ فنی
  • Commands - استفاده از commandها در SDK
  • Subagents - کار با agentهای تخصصی
  • Skills - استفاده از Agent Skills