news 2026/9/15 20:10:43

GitHub Copilot SDK 插件目录(Plugin Directories)完全指南:打包 Skills、Hooks、MCP 与自定义 Agent 的单一加载单元

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
GitHub Copilot SDK 插件目录(Plugin Directories)完全指南:打包 Skills、Hooks、MCP 与自定义 Agent 的单一加载单元

GitHub Copilot SDK 插件目录(Plugin Directories)完全指南:打包 Skills、Hooks、MCP 与自定义 Agent 的单一加载单元

【免费下载链接】copilot-sdkMulti-platform SDK for integrating GitHub Copilot Agent into apps and services项目地址: https://gitcode.com/GitHub_Trending/co/copilot-sdk

插件目录(Plugin Directories)是 GitHub Copilot SDK 提供的一种扩展打包机制:一个plugin本质上是一个目录,通过单一清单把 SDK 扩展(skills、hooks、MCP servers、自定义 agents 以及 LSP 配置)捆绑在一起。只需把这个目录指给 SDK,插件贡献的所有扩展就会被一次性加载,从而让你能在宿主应用中打包并分发可复用的能力包,而无需在每一个宿主应用里编写逐项扩展的接线代码。

本文以 docs/features/plugin-directories.md 为主线,覆盖插件的目录布局、从 SDK 加载插件的三种途径(CLI 启动参数、会话级配置、受信任的内置目录)、插件与 marketplace 插件的区别、如何让插件集合具备确定性,并结合仓库源码(如 nodejs/src/client.ts、go/client.go、python/copilot/client.py)剖析底层 RPC 调用链路。读完本文,你将掌握在 Node.js/TypeScript、Python、Go、.NET、Java、Rust 六种语言中正确加载、验证与排障插件目录的完整实战方案。

何时使用插件目录

当你希望做到以下几点时,应当优先考虑插件目录:

  • 把一组能力打包成单个单元分发:例如一个 "TypeScript reviewer" 能力包,内含一个 skill、一个强制 lint 的preToolUsehook,以及一个运行评审流程的自定义 agent;
  • 把能力包 vendoring 进仓库:让宿主应用的每一次克隆都按确定性加载同一组扩展;
  • 在本地开发插件,之后再将插件发布到 marketplace;
  • 覆盖或扩展 marketplace 已安装的插件:用本地 checkout 进行测试。

反之,如果只是需要添加单个 MCP server、单个 hook 或单个自定义 agent,可以直接通过 SDK 配置(mcpServershookscustomAgents)内联注册。插件目录通常在三个及以上相关扩展需要一起发布时才最具价值。

插件文件夹布局

Copilot CLI 会扫描每个插件目录,寻找plugin.json清单或根目录级的SKILL.md。一个最小化的插件长这样:

my-plugin/ ├── plugin.json # 清单(除非只使用 SKILL.md,否则必填) ├── SKILL.md # 可选:顶层 skill ├── hooks.json # 可选:hooks 配置 ├── .mcp.json # 可选:MCP server 配置 ├── agents/ # 可选:自定义 agents(每个 agent 一个 .md 文件) │ └── code-reviewer.md └── skills/ # 可选:额外 skills └── lint-fix/ └── SKILL.md

清单还可以放在.github/plugin.json.github/plugin/plugin.json,这样插件可以嵌在既有仓库中而无需改动仓库根布局。每个子系统(hooks、MCP、LSP、skills、agents)都有各自的加载器,并且都是可选的——插件只需包含它实际贡献的部分即可。完整的清单 schema 可参见 CLI 的/plugin斜杠命令所引用的运行时文档。

从 SDK 加载插件目录

插件目录通过给 Copilot CLI 传入--plugin-dir <path>加载(由 SDK 负责拉起 CLI)。各语言通过运行时连接的 extra-args 选项暴露该参数,且该参数可以重复传入以加载多个插件。

Node.js / TypeScript

import { CopilotClient, RuntimeConnection } from "@github/copilot-sdk"; async function main() { const client = new CopilotClient({ connection: RuntimeConnection.forStdio({ args: [ "--plugin-dir", "./plugins/code-reviewer", "--plugin-dir", "./plugins/lint-fix", ], }), }); await client.start(); } main();

Python

from copilot import CopilotClient, StdioRuntimeConnection client = CopilotClient( connection=StdioRuntimeConnection( args=( "--plugin-dir", "./plugins/code-reviewer", "--plugin-dir", "./plugins/lint-fix", ), ), ) await client.start()

Go

client := copilot.NewClient(&copilot.ClientOptions{ Connection: copilot.StdioConnection{ Args: []string{ "--plugin-dir", "./plugins/code-reviewer", "--plugin-dir", "./plugins/lint-fix", }, }, }) if err := client.Start(ctx); err != nil { return err }

.NET

using GitHub.Copilot; await using var client = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.ForStdio(args: new[] { "--plugin-dir", "./plugins/code-reviewer", "--plugin-dir", "./plugins/lint-fix", }), }); await client.StartAsync();

Java

var options = new CopilotClientOptions() .setCliArgs(new String[] { "--plugin-dir", "./plugins/code-reviewer", "--plugin-dir", "./plugins/lint-fix", }); var client = new CopilotClient(options); client.start().get();

Rust

use github_copilot_sdk::{Client, ClientOptions}; let client = Client::start( ClientOptions::new().with_extra_args([ "--plugin-dir", "./plugins/code-reviewer", "--plugin-dir", "./plugins/lint-fix", ]), ) .await?;

上面的示例使用 stdio 运行时连接——这是 SDK 捆绑 CLI 时的默认方式。如果你通过 URL 连接到外部运行时(forUri/ForUri),则需要在启动该长驻 CLI server 时自行传入--plugin-dirSDK 不会把--plugin-dir转发给它没有拉起的运行时。这一点在 nodejs/src/client.ts 的启动逻辑中体现得很清楚:只有当连接类型不是外部 server 时,SDK 才会自己拉起 CLI server 进程并注入 extra args。

每会话级插件目录(Per-session plugin directories)

--plugin-dir是启动参数,因此它一次性固定了整个 CLI 进程及其上创建的所有会话的插件集合。当不同会话需要不同的插件集合,或者 SDK 连接的是一个并非自己拉起的运行时,应当把目录放到会话配置中传递。这些目录会随session.createsession.resume的 payload 通过 JSON-RPC 传输,而不是作为进程参数,因此对于外部运行时也能以与启动选项相同的方式生效。

以 Node.js / TypeScript 为例:

import { CopilotClient } from "@github/copilot-sdk"; const client = new CopilotClient(); await client.start(); const session = await client.createSession({ pluginDirectories: ["./plugins/code-reviewer"], });

各 SDK 中对应的会话级选项如下:

SDKSession 选项
Node.js / TypeScriptpluginDirectories: string[]
Pythonplugin_directories=[...]
GoPluginDirectories: []string{...}
.NETPluginDirectories = [...]
Java.setPluginDirectories(List.of(...))
Rust.with_plugin_directories([...])

路径解析规则:相对路径会相对于workingDirectory解析;若未设置工作目录,则相对于运行时的工作目录,因此推荐使用绝对路径。无法解析的条目只会被记录日志并跳过,而不会导致会话创建失败。该选项是显式 opt-in 的,意味着即使enableConfigDiscoveryfalse,插件 agents 和规则也会被加载。以这种方式加载的资源,在会话级优先级顺序中位于项目源与个人/主目录源之间。

从源码可以看到实现细节:nodejs/src/client.ts 在组装session.create请求时把pluginDirectories: config.pluginDirectories直接放入 payload;go/client.go 同样在会话请求中设置req.PluginDirectories = config.PluginDirectories;python/copilot/client.py 则执行payload["pluginDirectories"] = plugin_directories。三条实现路径殊途同归:插件目录随会话请求体通过 JSON-RPC 到达运行时。

受信任的宿主内置插件目录(Trusted host-bundled plugin directories)

对于自带可信插件的应用,可以把这些目录注册为客户端启动选项。SDK 会在连接并校验协议之后、start返回或任何会话创建之前,把完整的、保序的目录集合发送给运行时。路径必须是绝对路径;若该选项未设置或为空数组,则完全不会发起 RPC 调用。

以 Node.js / TypeScript 为例:

import { CopilotClient } from "@github/copilot-sdk"; async function main() { const client = new CopilotClient({ builtinPluginDirectories: [ "/opt/my-app/copilot-plugins/core", "/opt/my-app/copilot-plugins/github", ], }); await client.start(); } main();

各 SDK 中对应的启动选项如下:

SDK启动选项
Node.js / TypeScriptbuiltinPluginDirectories: string[]
Pythonbuiltin_plugin_directories=[...]
GoBuiltinPluginDirectories: []string{...}
.NETBuiltinPluginDirectories = [...]
Java.setBuiltinPluginDirectories(List.of(Path.of(...)))
Rust.with_builtin_plugin_directories([...])

这是一个信任边界:它只用于宿主应用自己捆绑并控制的插件。它和--plugin-dir有本质区别——后者是 CLI 进程的启动参数,用于显式加载普通插件目录。由于该启动选项通过 JSON-RPC 传输(而非转发进程参数),因此连接既有运行时也同样有效

源码证据非常直接:

  • nodejs/src/client.ts:构造函数会遍历builtinPluginDirectories,用isAbsolute校验每个路径,任何非绝对路径都会抛出"builtinPluginDirectories must contain only absolute paths: ..."错误;
  • nodejs/src/client.ts:doStart()在连接 server 并完成协议版本校验之后,调用plugins.builtin.setRPC,发送{ paths: this.builtinPluginDirectories },失败则forceStop并抛出异常;
  • go/client.go 与 python/copilot/client.py:Go 与 Python 实现同样强制执行绝对路径校验;
  • go/client.go、python/copilot/client.py:Go 与 Python 也在客户端启动流程中发送plugins.builtin.set请求。

插件可以贡献什么

加载一个插件目录后,其扩展对该客户端创建的每一个会话都可见。运行时会把插件提供的扩展与你在 SDK 内联注册的内容合并在一起:

插件贡献会话中可见为
Skills(SKILL.mdskills/*/SKILL.mdsession.skills.list()中的条目;可按名称注入
自定义 agents(agents/*.md可通过task(agent_type=...)工具调度
Hooks(hooks.json与通过 SDK 注册的 hooks 一起触发
MCP servers(.mcp.json通过session.mcp.*可访问的工具与资源
LSP servers(.lsp.json通过session.lsp.initialize(...)初始化

插件 agents 是 Fleet Mode 中的一等公民子 agent:父 agent 可以按agent_type调度它们,运行时也会像对待其他子 agent 一样为它们触发subagentStart/subagentStophooks。

插件目录 vs Marketplace 插件

运行时存在两种安装插件的方式,二者对会话最终呈现的效果相同:

  • Marketplace / 直接仓库插件:通过 CLI 的/plugin斜杠命令或底层的installedPlugins用户设置持久安装。它们是ambient(环境性)的——任何针对同一用户配置运行的会话都会看到它们,并参与插件发现规则;
  • --plugin-dir插件:是explicit(显式)且 ephemeral(临时)的——只对用该标志启动的那个 CLI 进程生效。它们优先于 ambient 发现,并会与具有相同缓存路径的 marketplace 条目去重,因此当两种途径都引用同一个插件时不会加载两次。

对于 SDK 驱动的应用,--plugin-dir通常是更合适的选择:它让插件集合始终处于应用的掌控之下,而不依赖于每台机器的用户状态。

让插件集合具备确定性

当宿主机器上可能安装了其他插件(marketplace 或个人插件)时,在运行时环境中设置COPILOT_PLUGIN_DIR_ONLY=true可以抑制自动插件发现——只有通过--plugin-dir传入的目录会被加载。

以 Node.js / TypeScript 为例:

process.env.COPILOT_PLUGIN_DIR_ONLY = "true"; const client = new CopilotClient({ connection: RuntimeConnection.forStdio({ args: ["--plugin-dir", "./plugins/code-reviewer"], }), }); await client.start();

这一做法非常适合 CI、无头服务器部署,以及任何希望插件集合可复现、不依赖宿主用户配置的场景。

检查哪些插件已加载

会话创建后,可以通过列出活动插件来确认目录是否被正确拾取:

import { CopilotClient } from "@github/copilot-sdk"; const client = new CopilotClient(); await client.start(); const session = await client.createSession({ onPermissionRequest: async () => ({ kind: "approve-once" }), }); const plugins = await session.rpc.plugins.list(); for (const plugin of plugins.plugins) { console.log(`${plugin.name} (${plugin.enabled ? "enabled" : "disabled"})`); }

通过--plugin-dir加载的插件会出现在该列表中,其缓存路径(cache path)被设置为你提供的目录;marketplace 安装项则会标记其 registry 来源。

故障排查

  • "no plugin.json or SKILL.md found in <dir>"—— 目录存在但不满足插件资格。请在根目录(或.github/下)添加plugin.json清单,或放入一个顶层SKILL.md
  • 插件已加载但 agents/skills 不可见—— 确保插件清单声明了其贡献的 agents/skills,或使用隐式布局(agents/*.mdskills/*/SKILL.md)。随后调用session.rpc.skills.reload()即可在不重启的情况下拾取变更;
  • 重复 hooks 触发—— 运行时按cache_path去重,但仅当同一个目录同时被引用为 marketplace 安装项和--plugin-dir时才会去重。如果两个不同目录包含同一个插件,两者都会加载。请移除其中一个,或使用COPILOT_PLUGIN_DIR_ONLY=true
  • 连接外部运行时后--plugin-dir被忽略—— SDK 只在自行拉起 CLI 时才转发 extra args。对于外部运行时(forUri/ForUri),请把--plugin-dir传给启动该运行时 server 的命令行。

延伸阅读

  • 自定义 Agents:编写随插件agents/目录分发的 agents;
  • Skills:SKILL.md文件的加载方式与 skill 层级排序规则;
  • Hooks:插件定义的 hooks 与 SDK 注册的 hooks 一起触发;
  • MCP Servers:插件提供的 MCP servers 与内联注册的集成方式相同;
  • Fleet Mode:插件提供的 agents 可作为子 agent 调度。

【免费下载链接】copilot-sdkMulti-platform SDK for integrating GitHub Copilot Agent into apps and services项目地址: https://gitcode.com/GitHub_Trending/co/copilot-sdk

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/15 20:09:10

破解OSGB多工程融合难题:坐标基准统一与瓦块索引重建实战

做三维GIS和倾斜摄影数据处理的人&#xff0c;迟早会碰到这么个需求&#xff1a;几个独立跑的OSGB工程&#xff0c;最后要合成一个整体。单看每个工程都挺正常&#xff0c;放在一起就出问题——有的模型整体飘了几米&#xff0c;有的干脆隔了几公里对不上&#xff1b;瓦块目录里…

作者头像 李华
网站建设 2026/9/15 20:08:33

免签接口与发卡平台自动交易:从回调验签到自动发货源码实现

简介&#xff1a;一套在线虚拟商品自动交易发卡平台源码&#xff0c;面向个人站长与虚拟商品卖家&#xff0c;基于ThinkPHP5与Layui2.2开发&#xff0c;支持支付宝、微信免签接口及第三方个人支付&#xff0c;可自动完成虚拟商品交易与发货&#xff0c;适合搭建发卡网、自动发货…

作者头像 李华
网站建设 2026/9/15 20:07:30

AI短剧制作全流程拆解:从技术原理到低成本实战指南

我只是没想到&#xff0c;连我那个结婚八年的老同学都开始“赖”在厕所里不出来了。上周末聚会&#xff0c;他老婆当着我们的面吐槽&#xff1a;说这人最近每天晚上抱着手机进厕所&#xff0c;一待就是半个多小时&#xff0c;出来还一脸意犹未尽。一开始以为他在躲什么家务&…

作者头像 李华
网站建设 2026/9/15 20:07:03

LabVIEW实现TCP多客户端通信:服务器与客户端架构全解析

直接上手一个挺典型的项目&#xff1a;用LabVIEW做服务器与多个客户端之间的通信。做设备数据采集、多台上位机协同、分布式监控这类活儿的人&#xff0c;迟早会撞上这个需求。我最初接触这个场景&#xff0c;是实验室里两套采集机箱要同时把波形送给一台控制电脑做实时分析&am…

作者头像 李华
网站建设 2026/9/15 20:06:52

3步搞定sns网站社区需求分析文档速查手册

3步搞定sns网站社区需求分析文档速查手册 网站做好了没人访问,往往不是代码写得不够漂亮,而是最底层的 sns网站社区需求分析文档 没写透。很多老板盯着页面配色纠结半天,却忽略了用户到底要什么、数据怎么存、权限怎么控。这份文档就是项目的地基,地基歪了,楼盖得再高也塌。今天把这套 速查手册…

作者头像 李华