乐于分享
好东西不私藏

Claude Code 插件开发入门:一份给开发者的实践指南

Claude Code 插件开发入门:一份给开发者的实践指南

适合人群:熟悉命令行操作,想要扩展 Claude Code 功能的开发者 

前几天打开电脑,本来想写点东西,却发现自己不知道写什么好了。就想着自己是不是搞一个插件,可以让AI帮我时候搜索网上最新的咨询呢?那就动手写。不过反复用AI调试了几次,AI总是不能解决我的问题,浪费了我大量的调用次数。本身插件代码量不大,自己一番就找到了问题,所以借助官方文档总结一下。


一、什么是 Claude Code 插件?

Claude Code 插件是一种可打包、可分发的扩展包,让你能为 Claude Code 添加自定义的:

  • Commands(命令):自定义斜杠命令,如 /collect/deploy
  • Skills(技能):Claude 根据上下文自动调用的能力
  • Agents(智能体):专注特定任务的子智能体
  • Hooks(钩子):在特定事件(保存文件、会话结束等)时自动执行的脚本
  • MCP Servers:集成外部 API 和工具

与直接在 .claude/ 目录下配置不同,插件可以跨项目复用,并通过 Marketplace 分享给他人。


二、插件 vs 独立配置

方式
适用场景
命令格式
独立配置(.claude/ 目录)
单项目、个人用途、快速实验
/hello
插件(Plugin)
团队共享、跨项目复用、发布到社区
/my-plugin:hello

建议:先用独立配置快速验证想法,稳定后再打包成插件分发。


三、插件目录结构

my-plugin/├── .claude-plugin/│   └── plugin.json          # 插件清单(必须)├── commands/                # 命令文件(.md 格式)│   └── collect.md├── skills/                  # 技能目录│   └── code-review/│       └── SKILL.md├── agents/                  # 自定义智能体│   └── reviewer.md├── hooks/                   # 事件钩子│   └── hooks.json└── .mcp.json                # MCP 服务器配置(可选)

⚠️ 注意:commands/skills/ 等目录必须放在插件根目录,不能放到 .claude-plugin/ 里面。


四、快速上手:创建第一个插件

第 1 步:创建目录结构

mkdir -p my-first-plugin/.claude-pluginmkdir -p my-first-plugin/commands

第 2 步:创建插件清单 plugin.json

{  "name": "my-first-plugin",  "version": "1.0.0",  "description": "我的第一个 Claude Code 插件",  "author": {    "name": "Your Name"  }}

字段说明:

字段
说明
name
插件唯一标识,也是命令的命名空间前缀
version
版本号,省略则用 git commit SHA
description
在插件管理器中展示的描述
author
必须是对象格式,不能是字符串

第 3 步:创建命令文件

命令文件是普通 Markdown 文件,文件名即命令名。

commands/hello.md

向用户打招呼,问候 $ARGUMENTS 并询问今天有什么需要帮助的。

$ARGUMENTS 是占位符,会被替换为用户在命令后输入的内容。

例如输入 /my-first-plugin:hello 张三,Claude 就会向"张三"打招呼。

第 4 步:本地测试

# 用 --plugin-dir 加载本地插件,无需安装claude --plugin-dir ./my-first-plugin

启动后在 Claude Code 中运行:

/my-first-plugin:hello 张三

修改插件内容后,无需重启,直接运行 /reload-plugins 热更新。


五、plugin.json 常见字段格式

这是最容易出错的地方,以下是正确示例:

{  "name""tech-content-collector",  "version""1.0.0",  "description""收集和整理技术内容",  "author": {    "name""Lei Fu",    "email""lei@example.com"  },  "commands": ["./commands/"],  "skills": ["./skills/"],  "homepage""https://github.com/yourname/your-plugin"}

常见错误:

// ❌ author 不能是字符串"author": "Lei Fu"// ✅ author 必须是对象"author": { "name": "Lei Fu" }// ❌ commands 不能是对象数组"commands": [  { "name": "collect", "description": "..." }]// ✅ commands 必须是路径数组"commands": ["./commands/"]

六、添加 Skills(技能)

Skills 与 Commands 的区别:Commands 由用户主动调用,Skills 由 Claude 根据上下文自动调用

skills/code-review/SKILL.md

---description: 审查代码质量和潜在问题。当用户提交代码审查请求或分析代码质量时使用。---审查代码时,请检查以下方面:1. 代码结构和组织2. 错误处理3. 安全隐患4. 测试覆盖率提供具体的改进建议和示例代码。

description 字段告诉 Claude 何时应该调用这个技能,写得越准确,自动触发越精准。


七、添加 Hooks(钩子)

Hooks 让你在特定事件发生时自动执行脚本。

hooks/hooks.json

{  "hooks": {    "PostToolUse": [      {        "matcher": "Write|Edit",        "hooks": [          {            "type": "command",            "command": "echo '文件已修改' >> /tmp/claude-log.txt"          }        ]      }    ]  }}

常用的 Hook 事件:

事件
触发时机
PostToolUse
Claude 使用工具后
SessionStart
会话开始时
Stop
会话结束时

八、本地 Marketplace 安装

如果想像正式插件一样用 /plugin install 安装,需要创建本地 Marketplace。

目录结构

my-marketplace/├── .claude-plugin/│   └── marketplace.json     # Marketplace 描述文件└── my-first-plugin/         # 插件目录    ├── .claude-plugin/    │   └── plugin.json    └── commands/

marketplace.json

{  "name": "my-marketplace",  "owner": {    "name": "Lei Fu"  },  "plugins": [    {      "name": "my-first-plugin",      "source": "./my-first-plugin"    }  ]}

添加并安装

# 方式一:在 Claude Code 内添加/plugin marketplace add /path/to/my-marketplace# 方式二:命令行添加claude plugin marketplace add /path/to/my-marketplace# 安装插件(格式:插件名@marketplace名)/plugin install my-first-plugin@my-marketplace

九、开发调试技巧

# 加载多个插件同时测试claude --plugin-dir ./plugin-one --plugin-dir ./plugin-two# 热更新(修改文件后无需重启)/reload-plugins# 查看已配置的 marketplace/plugin marketplace list# 验证插件结构(需要最新版 Claude Code)claude plugin validate ./my-plugin

如果安装失败,先检查:

  1. .claude-plugin/plugin.json 是否存在且格式正确
  2. author 是否为对象格式
  3. commands / skills 是否为路径字符串数组
  4. 各目录是否在插件根目录(不是 .claude-plugin/ 内)

十、发布插件

准备好对外分发时:

  1. 将插件推送到 GitHub 仓库
  2. 用户通过 claude plugin marketplace add yourname/your-repo 添加你的 marketplace
  3. 然后 /plugin install plugin-name@your-marketplace 安装

如果想提交到 Anthropic 官方 Marketplace,访问 claude.ai/settings/plugins/submit 提交审核。


十一、常见陷阱与注意事项

根据开发者社区的反馈和本文档的核心要点,请特别留意以下几个容易出错的地方,可以避免 90% 的常见问题:

  1. plugin.json 的字段格式是关键

    • author 字段:必须是一个 JSON 对象,例如 {"name": "Your Name"}。绝对不能是 "Your Name" 这样的字符串。
    • commands 和 skills 字段:必须是路径数组,指向包含相应文件的目录,例如 ["./commands/"]。不能是包含命令或技能详细定义的对象数组。
  2. 严格遵守目录结构

    • commands/skills/agents/ 等功能目录必须与 .claude-plugin 目录平级,位于插件的根目录下。
    • 切勿将这些功能目录放在 .claude-plugin/ 文件夹内部。
  3. 理解命令的命名空间

    • 通过插件加载的命令,在调用时必须加上插件名作为前缀,格式为 /插件名:命令名(例如 /my-first-plugin:hello)。
    • 这与在项目本地 .claude/ 目录中定义的普通命令(直接使用 /hello)不同。

预先检查这几点能大幅提升插件开发的顺畅度。


十二、总结

步骤
要点
创建结构
.claude-plugin/plugin.json
 + 各功能目录
编写清单
author
 必须是对象,commands 必须是路径数组
本地测试
claude --plugin-dir ./my-plugin
热更新
/reload-plugins
分发
创建 Marketplace,用户添加后安装

十三、进阶主题探讨

本章节的内容主要基于社区实践和对插件架构的推测,因为关于这些高级主题的官方文档目前较为缺乏。请在实践中带着探索的心态使用,并以官方未来的更新为准。

1. Agents vs. Skills 的深度解析

你可能已经注意到,除了 Skills,还有 Agents。它们之间有什么区别?

  • Skill(技能):是一个工具。它定义了“如何做”一个特定的、原子化的任务。例如,一个 code-review 技能提供了代码审查的具体步骤和标准。它本身没有决策能力,等待被 Claude 主动调用。
  • Agent(智能体):是一个执行者角色。它定义了“做什么”以及“以什么身份去做”。Agent 更侧重于设定一个高层次的目标、工作流程或个性(Persona)。它可以拥有和协调多个 Skills 来完成一个复杂的、多步骤的任务。

举个例子,一个 Agent 的定义文件 agents/reviewer.md 可能看起来像这样:

---name: Code Reviewer Agentdescription: 一个专门负责代码审查的智能体。当被激活时,它会遵循严格的审查流程,并使用 code-review 技能来分析代码。---# 角色设定你是一个经验丰富的代码审查专家。你的目标是保证代码库的质量、可读性和安全性。# 工作流程1.  **理解需求**:首先,向用户询问本次代码提交的背景和目的。2.  **执行审查**:调用 `code-review` 技能来分析代码。3.  **总结报告**:基于技能的输出,整理一份清晰、完整的审查报告,包括优点、问题和修改建议。4.  **提供示例**:对关键的修改建议,提供具体的代码示例。

总结:你可以把 Agent 看作一个“项目经理”或“专家角色”,而 Skill 是他手边的“工具箱”。

2. MCP Servers: 集成外部 API (推测性示例)

MCP Servers 和 .mcp.json 文件是插件系统中最神秘也最强大的部分,它被认为是连接外部 API 和工具的桥梁。

⚠️ 免责声明: 以下关于 .mcp.json 的内容是纯粹的推测,基于对类似插件系统的分析。官方并未提供相关文档,其真实结构和用法可能存在巨大差异。

我们推测 .mcp.json 可能用于定义一个本地的 API 网关,将外部服务映射成 Claude Code 可以调用的内部工具。

一个假设的.mcp.json 可能如下所示:

{  // 定义该 MCP 服务的命名空间  "namespace""external_apis",  // 列出所有可用的外部服务  "services": [    {      // 服务名称,用于在 Claude Code 中调用      "name""get_weather",      // 服务的描述,帮助 Claude 理解其功能      "description""获取指定城市的实时天气",      // 定义 API 的具体细节      "endpoint": {        // 外部 API 的 URL,使用 {city} 作为参数占位符        "url""https://api.weather.com/v1/current?city={city}",        // HTTP 请求方法        "method""GET",        // 定义参数        "parameters": [          {            "name""city",            "in""path"// 表示参数在 URL 路径中            "description""The city to get the weather for",            "required"true,            "schema": {              "type""string"            }          }        ],        // 如果 API 需要认证,可以在这里配置        "authentication": {          "type""apiKey",          "name""X-API-Key",          "in""header",          // 密钥可以引用环境变量,避免硬编码          "value""${WEATHER_API_KEY}"        }      }    }  ]}

如果这个推测成立,当你对 Claude 说“帮我查一下北京的天气”时,它可能会找到 get_weather 这个服务,并调用对应的外部 API。

3. 更复杂的参数处理

内置的 $ARGUMENTS 变量虽然简单,但当命令需要多个、可选或带标志的参数时,就显得力不从心。由于没有发现官方支持的命名参数语法,最佳实践是在你的命令脚本内部自行解析。

示例:创建一个 /deploy 命令,支持指定环境(--env)和强制执行(--force)。

commands/deploy.md:

```shell#!/bin/bash# 默认值ENVIRONMENT="staging"FORCE=false# 解析命令行参数while [[ "$#" -gt 0 ]]; do    case $1 in        --env) ENVIRONMENT="$2"shift ;;        --force) FORCE=true ;;        *) echo "未知参数: $1"exit 1 ;;    esac    shiftdoneecho "准备部署到环境: $ENVIRONMENT"if [ "$FORCE" = true ]; then    echo "执行强制部署..."    # ./deploy_script.sh --force --env $ENVIRONMENTelse    echo "执行标准部署..."    # ./deploy_script.sh --env $ENVIRONMENTfiecho "部署完成。"```

使用方法:

/my-plugin:deploy --env production --force

通过在命令脚本顶部添加一小段 shell 解析逻辑,你可以轻松实现媲美原生 CLI 工具的参数灵活性。

4. Hooks 的进一步探索

教程中提到了 PostToolUse 等事件。关于 Hooks,还有一些值得探索的方向:

  • 更精确的 matcher:除了 Write|Edit,是否可以匹配其他工具名称,例如 RunShellCommand 或者你自定义的命令?这需要实验来验证。
  • 上下文变量:当一个 Hook 被触发时,Claude Code 很可能会通过环境变量向脚本传递上下文信息。例如,当 PostToolUse 匹配 Write 时,哪个文件被写入了?内容是什么?

你可以创建一个简单的 Hook 来探测试图传递了哪些环境变量:

hooks/hooks.json:

{  "hooks": {    "PostToolUse": [      {        "matcher": "Write",        "hooks": [          {            "type": "command",            "command": "env | grep CLAUDE_ > /tmp/claude_hook_env.log"          }        ]      }    ]  }}

执行一次文件写入操作后,检查 /tmp/claude_hook_env.log 文件的内容,你可能会发现类似 CLAUDE_TOOL_INPUT_FILE_PATH 或 CLAUDE_SESSION_ID 这样的宝贵信息,从而让你的 Hook 能够实现更强大的自动化。

完整官方文档:code.claude.com/docs/en/plugins