跳转到内容

插件系统架构与组件发现

插件系统架构与组件发现

学习目标

读完本章后,你将能够:

  • 理解约定优于配置的组件自动发现机制
  • 设计四类核心组件(Commands、Agents、Skills、Hooks)的目录结构
  • 掌握 ${CLAUDE_PLUGIN_ROOT} 环境变量的跨组件可移植性
  • 了解插件清单文件的作用边界

核心概念

约定优于配置的发现机制

插件系统采用约定优于配置(Convention over Configuration)的设计哲学:组件不需要在清单文件中显式注册,而是通过目录结构和文件命名自动发现。

四类核心组件

组件类型文件位置定义格式生命周期
Commandcommands/*.mdMarkdown + YAML frontmatter用户触发时加载
Agentagents/*.mdMarkdown + YAML frontmatter被调用时加载
Skillskills/<name>/SKILL.mdMarkdown SKILL.md + references/ + examples/触发短语匹配时加载
Hookhooks/hooks.json + 脚本JSON 注册 + Python/Bash 执行脚本对应事件发生时执行

插件清单文件的边界

plugin.json 仅声明元数据,不声明组件列表:

{
"name": "feature-dev",
"version": "1.0.0",
"description": "Comprehensive feature development workflow",
"author": {
"name": "Author Name",
"email": "author@example.com"
}
}

不声明的内容

  • commands 列表 → 从 commands/ 目录自动发现
  • agents 列表 → 从 agents/ 目录自动发现
  • skills 列表 → 从 skills/ 目录自动发现
  • hooks 列表 → 从 hooks/hooks.json 读取

为什么这样设计? 避免清单文件与实际文件不同步。清单只回答”这个插件是什么”,不回答”这个插件包含什么”——后者由文件系统直接回答。

跨组件可移植性:${CLAUDE_PLUGIN_ROOT}

所有组件中使用 ${CLAUDE_PLUGIN_ROOT} 环境变量引用插件内部路径:

Terminal window
# Hook 脚本中引用插件内的 Python 脚本
python3 ${CLAUDE_PLUGIN_ROOT}/hooks/my_hook.py
# 命令中引用插件内的设置脚本
${CLAUDE_PLUGIN_ROOT}/scripts/setup.sh $ARGUMENTS

这确保插件无论安装到哪个路径,内部引用始终正确。

陷阱与对策

陷阱表现对策
组件名称与约定不匹配命令未被发现commands/ 下的文件必须为 .md 格式,文件名即命令名
plugin.json 格式错误插件无法安装使用标准 JSON schema 验证
Hook 脚本无执行权限事件触发时报错Hook 脚本需 chmod +x
重叠路径导致重复计数统计显示组件数量翻倍避免 plugin.json 中声明的路径与实际目录重叠

设计取舍

为什么用 Markdown 而非 JSON/YAML 定义 Agent/Command?

Agent 的系统提示本质上是自然语言指令,Markdown 对人类作者和 AI 模型都直接可读。JSON/YAML 需要额外转义和结构化,降低了可读性和可维护性。

代价:缺少编译期格式检查,frontmatter 字段拼写错误只能在运行时发现。

为什么 Hook 用 Python/Bash 而非内置规则引擎?

外部脚本可以访问操作系统、文件系统、网络服务,灵活性远超内置 DSL。同时,脚本可以被独立测试、版本控制和共享。

代价:跨平台兼容性(Python 版本、Bash 版本差异)需要额外关注。

参考来源

补充:LangChain 的合作伙伴(Partner)包模式

LangChain 采用 Monorepo + 独立发版的合作伙伴包架构。每个第三方集成(如 OpenAI、Anthropic、Ollama)作为独立的 Python 包位于 libs/partners/ 目录下:

libs/partners/
├── openai/ → langchain-openai (独立版本号)
├── anthropic/ → langchain-anthropic (独立版本号)
├── ollama/ → langchain-ollama (独立版本号)
└── ...

独立版本:每个 partner 包有自己的版本号和发版周期,不跟随核心包版本变化。这使得 OpenAI 集成的 bug 修复不需要等待整个 LangChain 发版。

标准测试套件libs/standard-tests/ 提供共享的集成测试框架,所有 partner 包运行同一套测试,保证 API 行为一致性。

uv 包管理:Monorepo 使用 uv(而非 pip/poetry)进行依赖管理,每个包有独立的 pyproject.tomluv.lock,通过 editable installs 实现本地开发。

设计取舍:相比将所有集成放在单一包中,独立发版降低了发布协调成本,但增加了 Monorepo 管理的复杂度(依赖解析、CI 矩阵测试)。