В этом руководстве объясняется структура папок плагинов, как загружать плагин из каталога, когда использовать каталоги плагинов и когда регистрировать отдельные расширения, а также как сделать наборы плагинов детерминированными.
Когда использовать каталоги плагинов
Используйте папку плагинов, когда хотите:
- Распределите набор возможностей в одном едином блоке — например, пакет «TypeScript reviewer» с навыком,
preToolUseкрючок, обеспечивающий линт, и пользовательский агент, управляющий рецензентом. - Возможности поставщика упаковываются в репозиторий , так что каждый клон хост-приложения загружает одни и те же расширения детерминированно.
- Разработайте плагин локально перед тем, как публиковать его на маркетплейсе.
- Переопределите или расширите плагин, установленный на маркетплейсе, с помощью локальной проверки для тестирования.
Если вам нужно добавить только один MCP-сервер, один крюк или один пользовательский агент, вы можете зарегистрировать его в строке через конфигурацию SDK (mcpServers, hooks, customAgents). Папки плагинов наиболее полезны, когда у вас есть три или более связанных расширений, которые поставляются вместе.
Оформление папки плагина
Copilot CLI сканирует каждую папку плагина в поисках манифеста plugin.json или корневого уровня SKILL.md. Минимальный плагин выглядит так:
my-plugin/
├── plugin.json # manifest (required unless using SKILL.md only)
├── SKILL.md # optional: top-level skill
├── hooks.json # optional: hooks config
├── .mcp.json # optional: MCP server config
├── agents/ # optional: custom agents (one .md file per agent)
│ └── code-reviewer.md
└── skills/ # optional: additional skills
└── lint-fix/
└── SKILL.md
Манифест также может находиться в точке .github/plugin.json или .github/plugin/plugin.json около того, что плагины могут находиться внутри существующего репозитория без изменения его корневой структуры. Каждая подсистема (хуки, MCP, LSP, навыки, агенты) имеет свой загрузчик и является опциональной — плагину нужны только те части, которые он вносит.
Полную схему манифеста смотрите документацию по выполнению, на которую ссылка из команды слэш вашего /plugin CLI.
Загрузка каталога плагинов из SDK
Каталоги плагинов загружаются путём передачи --plugin-dir <path> Copilot CLI, когда SDK его создаёт. Каждый язык раскрывает это через опцию extra args в runtime connection. Флаг можно повторить для загрузки нескольких плагинов.
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();
import { CopilotClient, RuntimeConnection } from "@github/copilot-sdk";
const client = new CopilotClient({
connection: RuntimeConnection.forStdio({
args: [
"--plugin-dir", "./plugins/code-reviewer",
"--plugin-dir", "./plugins/lint-fix",
],
}),
});
await client.start();
from copilot import CopilotClient, StdioRuntimeConnection
client = CopilotClient(
connection=StdioRuntimeConnection(
args=(
"--plugin-dir", "./plugins/code-reviewer",
"--plugin-dir", "./plugins/lint-fix",
),
),
)
await client.start()
package main
import (
"context"
copilot "github.com/github/copilot-sdk/go"
)
func main() {
ctx := context.Background()
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
}
}
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
}
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();
import com.github.copilot.CopilotClient;
import com.github.copilot.rpc.CopilotClientOptions;
public class PluginDirectoriesExample {
public static void main(String[] args) throws Exception {
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();
}
}
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();
use github_copilot_sdk::{Client, ClientOptions};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let _client = Client::start(
ClientOptions::new().with_extra_args([
"--plugin-dir", "./plugins/code-reviewer",
"--plugin-dir", "./plugins/lint-fix",
]),
)
.await?;
Ok(())
}
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 runtime соединение — стандартное, когда SDK объединяет CLI. Если вы подключаетесь к внешнему серверу выполнения через URL (
forUri/ForUri), передайте данные--plugin-dirна долгоработающий CLI-сервер при запуске; SDK не пересылает--plugin-dirвремя выполнения, которые он не создал.
Что может внести плагин
Загрузка каталога плагинов делает его расширения видимыми для каждой сессии, созданной клиентом. Runtime объединяет расширения, предоставленные плагинами, с тем, что вы регистрируете в строке:
| Плагин вносит вклад | Видимо для сессии как |
|---|---|
Навыки (SKILL.md, skills/*/SKILL.md) | Элементы в session.skills.list(); инъекциируемые по названию |
Таможенные агенты (agents/*.md) | Можно отправить с помощью task(agent_type=...) инструмента |
Крючки (hooks.json) | Стреляет вместе с крюками, зарегистрированными через SDK |
MCP-серверы (.mcp.json) | Инструменты и ресурсы, доступные через session.mcp.* |
LSP-серверы (.lsp.json) | Инициализация с помощью session.lsp.initialize(...) |
Агенты плагинов — это первоклассные субагенты в Режим флота: родительский агент может отправить их через agent_type, и runtime запускает subagentStart / subagentStop крючки для них, как и любой другой подагент.
Plugin-dir против плагинов marketplace
В среде выполнения есть два способа установки плагинов, и оба в итоге выглядят одинаково для сессии:
- Плагины Marketplace / прямой репозиторий постоянно устанавливаются через команду слэш CLI
/pluginили через базовуюinstalledPluginsпользовательскую настановку. Они окружающие — каждая сессия, работающая с одной и той же пользовательской конфигурацией, видит их, и они участвуют в правилах обнаружения плагинов. --plugin-dirплагиныявны и эфемерны — они применимы только к CLI-процессу, который вы запустили с этим флагом. Они имеют приоритет над окружающим обнаружением и удаляются по сравнению с записями на рынке с одинаковым кэш-маршрутом, поэтому один и тот же плагин не загружается дважды, когда обе поверхности на него ссылаются.
Для приложений, управляемых SDK, --plugin-dir обычно это правильный выбор: плагин остаётся под контролем вашего приложения, а не зависит от состояния пользователя на каждой машине.
Детерминированные наборы плагинов
Когда на хост-машине могут быть установлены другие плагины (маркетплейсовые или личные), они устанавливаются COPILOT_PLUGIN_DIR_ONLY=true в среде выполнения для подавления автоматического обнаружения плагинов. Загружаются только те каталоги, через --plugin-dir которые вы проходите.
Node.js / TypeScript
import { CopilotClient, RuntimeConnection } from "@github/copilot-sdk";
async function main() {
process.env.COPILOT_PLUGIN_DIR_ONLY = "true";
const client = new CopilotClient({
connection: RuntimeConnection.forStdio({
args: ["--plugin-dir", "./plugins/code-reviewer"],
}),
});
await client.start();
}
main();
process.env.COPILOT_PLUGIN_DIR_ONLY = "true";
const client = new CopilotClient({
connection: RuntimeConnection.forStdio({
args: ["--plugin-dir", "./plugins/code-reviewer"],
}),
});
await client.start();
Используйте это в CI, в развертённых серверах без головы и везде, где нужен воспроизводимый набор плагинов, не зависящий от конфигурации пользователя хоста.
Проверка загрузки плагинов
После создания сессии перечислите активные плагины, чтобы убедиться, что каталог был правильно выбран:
Node.js / TypeScript
import { CopilotClient } from "@github/copilot-sdk";
async function main() {
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"})`);
}
}
main();
const plugins = await session.rpc.plugins.list();
for (const plugin of plugins.plugins) {
console.log(`${plugin.name} (${plugin.enabled ? "enabled" : "disabled"})`);
}
Плагины, загруженные через --plugin-dir BY, появляются в этом списке с их кэш-путём, установленным в указанной вами директории. Установки маркетплейса отмечены исходным кодом реестра.
Troubleshooting
- "нет plugin.json или SKILL.md в <DIR>" — каталог существует, но не считается плагином. Добавьте
plugin.jsonманифест в корень (или ниже.github/), или добавьте верхний уровеньSKILL.md. - Плагин загружен, но агенты/навыки не видны — убедитесь, что манифест плагина объявляет агентов/навыков, которые он вносит, или используйте неявную структуру (
agents/*.md,skills/*/SKILL.md). Потом звонитеsession.rpc.skills.reload(), чтобы забрать изменения, не перезагружаясь. - Срабатывание дублирующих крючков — время выполнения дедуплирует на
cache_path, но только тогда, когда одна и та же папка ссылается как на установку маркетплейса, так и на--plugin-dir. Если два разных каталога содержат один и тот же плагин, оба будут загружаться. Удалите один или используйтеCOPILOT_PLUGIN_DIR_ONLY=true. --plugin-dirигнорируется при подключении к внешнему runtime — SDK пересылает дополнительные arg-файлы только при создании самого CLI. Для внешних условий выполнения (forUri/ForUri), передайте--plugin-dirкомандную строку, которая запускает сервер выполнения.
Related
- Пользовательские агенты и оркестровка субагентов: пишите агенты, которые отправляются внутри папки
agents/плагина. - Настраиваемые навыки: как
SKILL.mdзагружаются файлы и правила порядка уровней навыков. - Работа с крючками: хуки, определяемые плагинами, вместе с хуками, зарегистрированными в SDK.
- Using MCP servers with the GitHub Copilot SDK: MCP-серверы, предоставляемые плагинами, интегрируются так же, как и встроенные регистрации.
- Режим флота: агенты, предоставленные плагинами, могут диспетчеризироваться как субагенты.