מדריך קלוד קוד בעברית

תיעוד 184

תוספים ב-SDK

טען תוספים מותאמים אישית כדי להרחיב את Claude Code עם skills, agents, hooks ושרתי MCP דרך Agent SDK

תוספים מאפשרים להרחיב את Claude Code עם פונקציונליות מותאמת אישית שאפשר לשתף בין פרויקטים. דרך Agent SDK אפשר לטעון תוספים באופן תכנותי מתיקיות מקומיות כדי להוסיף יכולות לסשנים של הסוכן. תוסף יכול לכלול:

  • Skills: יכולות ש-Claude מפעיל באופן עצמאי כשהן רלוונטיות. אפשר גם להפעיל skill של תוסף ישירות עם /plugin-name:skill-name.
  • Agents: תת-סוכנים מתמחים למשימות מסוימות
  • Hooks: מטפלי אירועים שמגיבים לשימוש בכלים ולאירועים אחרים
  • שרתי MCP: שילובי כלים חיצוניים דרך Model Context Protocol

למידע מלא על מבנה תוסף ואיך ליצור תוספים, ראה תוספים.

#טעינת תוספים

טען תוספים על ידי אספקת נתיבי מערכת הקבצים המקומית שלהם בהגדרות האפשרויות. השדה type חייב להיות "local", הערך היחיד שה-SDK מקבל. ה-SDK תומך בטעינת כמה תוספים ממיקומים שונים.

כדי להשתמש בתוסף שמופץ דרך marketplace או מאגר מרוחק, הורד אותו קודם וספק את נתיב התיקייה המקומית. למבנה התיקיות שתוסף צריך, ראה את הפניה למבנה תוסף למטה.

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

#מפרטי נתיב

נתיבי תוספים יכולים להיות:

  • נתיבים יחסיים: נפתרים יחסית לאפשרות cwd (לדוגמה, "./plugins/my-plugin")
  • נתיבים מוחלטים: נתיבי מערכת קבצים מלאים (לדוגמה, "/home/user/plugins/my-plugin")

הערה

הנתיב צריך להצביע לתיקיית השורש של התוסף: ההורה של skills/, agents/, hooks/, commands/ או .claude-plugin/.

#טעינה מחדש של תוספים בסשן פעיל

כדי להחיל שינוי על skills, commands, agents או hooks של תוסף בלי להתחיל סשן חדש, קרא ל-reloadPlugins() על אובייקט Query של TypeScript SDK. Python SDK לא חושף מתודה מקבילה. שלח /reload-plugins כ-prompt בסשן במקום זאת.

#הוספת תוספים לסשן פעיל

ב-TypeScript SDK, קרא ל-reloadPlugins() על אובייקט Query ש-query() החזיר, וציין את תיקיית התוסף באפשרות addPlugins של אותה קריאה. כל רשומה ב-addPlugins היא אובייקט { type: "local", path } עם path מוחלט. נדרש TypeScript Agent SDK מגרסה v0.3.301 ואילך.

בדוגמה הזו, q הוא אובייקט Query ש-query() החזיר. הדוגמה מוסיפה תיקיית תוסף אחת לסשן הפעיל, ואחרי ש-reloadPlugins() חוזר, מדפיסה את הנתיב של כל תוסף בסשן:

const result = await q.reloadPlugins({
  addPlugins: [{ type: "local", path: "/home/user/plugins/another-plugin" }]
});

console.log(result.plugins.map((plugin) => plugin.path));

אם התוסף נטען, הרשימה המודפסת כוללת את /home/user/plugins/another-plugin. אם הנתיב הזה חסר מהרשימה, או ש-reloadPlugins() נדחה, ראה כש-reloadPlugins() לא טוען את תיקיות addPlugins לסיבות.

#אימות התקנת תוסף

כשתוספים נטענים בהצלחה, הם מופיעים בהודעת האתחול של המערכת. אפשר לוודא שהתוספים זמינים:

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: "/absolute/path/to/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": "/absolute/path/to/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())

#שימוש ב-skills של תוסף

Skills מתוספים מקבלים אוטומטית namespace עם שם התוסף כדי למנוע התנגשויות. כדי להפעיל אחד ישירות, שלח /plugin-name:skill-name כ-prompt.

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="/my-plugin:greet",  # Use plugin skill with namespace
        options=ClaudeAgentOptions(
            plugins=[{"type": "local", "path": "./my-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())

הערה

אם התקנת תוסף דרך ה-CLI (לדוגמה, /plugin install my-plugin@marketplace), עדיין אפשר להשתמש בו ב-SDK על ידי אספקת נתיב ההתקנה שלו. בדוק את ~/.claude/plugins/ לתוספים שהותקנו דרך CLI.

#דוגמה מלאה

הנה דוגמה מלאה שמדגימה טעינת תוסף ושימוש בו:

import { query } from "@anthropic-ai/claude-agent-sdk";
import { fileURLToPath } from "node:url";

async function runWithPlugin() {
  const pluginPath = fileURLToPath(new URL("./plugins/my-plugin", import.meta.url));

  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."""

import asyncio
from pathlib import Path

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" / "my-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__":
    asyncio.run(run_with_plugin())

#הפניה למבנה תוסף

תיקיית תוסף מכילה בדרך כלל קובץ מניפסט .claude-plugin/plugin.json. המניפסט אופציונלי. כשהוא מושמט, Claude Code מגלה רכיבים אוטומטית ממבנה התיקיות. התיקייה יכולה לכלול:

my-plugin/
├── .claude-plugin/
│   └── plugin.json          # Plugin manifest (optional, components auto-discovered without it)
├── skills/                   # Agent Skills (invoked autonomously or via /plugin-name:skill-name)
│   └── my-skill/
│       └── SKILL.md
├── commands/                 # Skills as flat .md files
│   └── custom-cmd.md
├── agents/                   # Custom agents
│   └── specialist.md
├── hooks/                    # Event handlers
│   └── hooks.json
└── .mcp.json                # MCP server definitions

הערה

התיקייה commands/ מחזיקה skills כקבצי Markdown שטוחים. השתמש ב-skills/ לתוספים חדשים. Claude Code תומך בשני המיקומים.

#מקורות מרובים לתוספים

שלב תוספים ממיקומים שונים:

import * as os from "node:os";
import * as path from "node:path";

plugins: [
  { type: "local", path: "./local-plugin" },
  {
    type: "local",
    path: path.join(os.homedir(), ".claude", "custom-plugins", "shared-plugin")
  }
];

הערה

ה-SDK לא מרחיב נתיבי tilde כמו ~/plugins. אם נתיב תוסף לא קיים, ה-SDK מדלג על התוסף והסשן ממשיך, אז בדוק את רשימת plugins בהודעת init כדי לאשר שכל תוסף נטען.

#פתרון בעיות

#תוסף לא נטען

אם התוסף לא מופיע ברשימת plugins של הודעת init, בדוק את השדה plugin_errors שלו לסיבה, ואז עבור על הבדיקות האלה:

  1. בדוק את הנתיב: ודא שהנתיב מצביע לתיקיית השורש של התוסף, ההורה של skills/, agents/, hooks/, commands/ או .claude-plugin/
  2. אמת את plugin.json: אם התוסף כולל מניפסט, ודא שיש לו תחביר JSON תקין
  3. בדוק הרשאות קבצים: ודא שתיקיית התוסף ניתנת לקריאה
  4. אשר שהתיקייה קיימת: ה-SDK מדלג על נתיב שלא קיים, והתוסף לא מופיע ברשימת plugins של הודעת init

#Skills לא מופיעים

אם skills של תוסף לא עובדים:

  1. השתמש ב-namespace: הפעל skills של תוסף כ-/plugin-name:skill-name
  2. בדוק את הודעת init: ודא שה-skill מופיע ברשימת skills עם ה-namespace הנכון
  3. אמת קבצי skill: ודא שלכל skill יש קובץ SKILL.md בתת-תיקייה משלו תחת skills/, לדוגמה skills/my-skill/SKILL.md

#ראה גם