obsidian/wiki/agent-sdk/agent-skills-plugins.md
2026-04-17 12:40:31 +01:00

4 KiB

title aliases tags sources created updated
Agent Skills & Plugins in the SDK
sdk-plugins
agent-skills-sdk
claude-sdk-plugins
agent-sdk
plugins
skills
mcp
hooks
typescript
raw/Agent Skills in the SDK 1.md
2026-04-17 2026-04-17

Agent Skills & Plugins in the SDK

Plugins extend Claude Agent SDK sessions with packaged capabilities — skills, agents, hooks, and MCP servers — loaded from local directories at runtime.

What Plugins Contain

Component Description
Skills Model-invoked capabilities; also callable via /plugin-name:skill-name
Agents Specialized subagents for specific tasks
Hooks Event handlers that fire on tool use and other events
MCP servers External tool integrations via Model Context Protocol

skills/ is the current format. commands/ is legacy but still supported for backward compatibility.

Plugin Directory Structure

my-plugin/
├── .claude-plugin/
│   └── plugin.json          # Required manifest
├── skills/                  # New format — use this
│   └── my-skill/
│       └── SKILL.md
├── commands/                # Legacy format
├── agents/
├── hooks/
│   └── hooks.json
└── .mcp.json

The path passed to the SDK must point to the root directory containing .claude-plugin/.

Loading Plugins

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

for await (const message of query({
  prompt: "Hello",
  options: {
    plugins: [
      { type: "local", path: "./my-plugin" },           // relative
      { type: "local", path: "/absolute/path/plugin" }  // absolute
    ]
  }
})) { }
  • Relative paths resolve from the current working directory
  • CLI-installed plugins live at ~/.claude/plugins/ — use their path here too

Verifying Plugin Load

Check the system init message:

if (message.type === "system" && message.subtype === "init") {
  console.log(message.plugins);        // [{name, path}]
  console.log(message.slash_commands); // ["/help", "my-plugin:custom-cmd"]
}

Using Plugin Skills

Skills are auto-namespaced as plugin-name:skill-name:

for await (const message of query({
  prompt: "/my-plugin:greet",
  options: {
    plugins: [{ type: "local", path: "./my-plugin" }]
  }
})) { }

Common Patterns

// Dev/testing — load without global install
plugins: [{ type: "local", path: "./dev-plugins/my-plugin" }]

// Team consistency — commit plugin to repo
plugins: [{ type: "local", path: "./project-plugins/team-workflows" }]

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

Troubleshooting

Problem Fix
Plugin missing from init message Check path points to root (.claude-plugin/ must exist there)
Skill not invocable Use full namespace: plugin-name:skill-name
Relative path fails Run from expected CWD or switch to absolute path
Invalid manifest Validate .claude-plugin/plugin.json is valid JSON

Key Takeaways

  • Plugins are loaded per-session via options.plugins — no global install required
  • Skills from plugins are namespaced: plugin-name:skill-name to avoid conflicts
  • Verify loading via message.type === "system" && message.subtype === "init"
  • Prefer skills/ over commands/ for new plugin development
  • CLI-installed plugins (~/.claude/plugins/) can be loaded in SDK sessions by path
  • Plugin root = directory containing .claude-plugin/plugin.json

Source: raw/Agent Skills in the SDK 1.md