В этом руководстве объясняется структура папок плагинов, как загружать плагин из каталога, когда использовать каталоги плагинов и когда регистрировать отдельные расширения, а также как сделать наборы плагинов детерминированными.
Когда использовать каталоги плагинов
Используйте папку плагинов, когда хотите:
- Распределите набор возможностей в одном едином блоке — например, пакет «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";
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()
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();
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};
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время выполнения, которые он не создал.
Каталоги подключаемых модулей для сеанса
--plugin-dir — это аргумент запуска, поэтому он исправляет один подключаемый модуль для процесса CLI и каждого сеанса, созданного для него. Если сеансы нуждаются в разных наборах подключаемых модулей или когда пакет SDK подключен к среде выполнения, он не разрежен, передайте каталоги в конфигурации сеанса. Они перемещаются по session.create JSON-RPC и session.resume полезных данных, а не как аргументы процесса, поэтому они достигают внешней среды выполнения так же, как вариант запуска.
import { CopilotClient } from "@github/copilot-sdk";
const client = new CopilotClient();
await client.start();
const session = await client.createSession({
pluginDirectories: ["./plugins/code-reviewer"],
});
Относительные пути разрешаются для workingDirectoryрабочих каталогов среды выполнения, если это не задано, поэтому рекомендуется использовать абсолютные пути. Записи, которые не разрешаются, регистрируются и пропускаются, а не создаются сбой сеанса. Этот параметр является явным согласием, что означает загрузку агентов и правил подключаемого модуля, даже если enableConfigDiscovery значение false. Ресурсы, загруженные таким образом, сидят между источниками проекта и личными или домашними источниками в порядке приоритета на уровне сеанса.
Эквивалентный вариант в каждом пакете SDK:
| SDK | Параметр сеанса |
|---|---|
| Node.js / TypeScript | plugin |
| Python | plugin_directories=[...] |
| Go | Plugin |
| .NET | PluginDirectories = [...] |
| Java | .set |
| Rust | .with_plugin_directories([...]) |
Каталоги подключаемых модулей с доверенными узлами
Приложения, отправившие собственные доверенные подключаемые модули, могут зарегистрировать их в качестве варианта запуска клиента. Пакет SDK отправляет полный упорядоченный набор после подключения и проверки протокола перед start возвратом или любым сеансом. Пути должны быть абсолютными; Если параметр не задан или пуст, вызов RPC не вызывается.
Эквивалентный вариант в каждом пакете SDK:
| SDK | Параметр запуска |
|---|---|
| Node.js / TypeScript | builtin |
| Python | builtin_plugin_ |
| Go | Builtin |
| .NET | Builtin |
| Java | .set |
| Rust | .with_builtin_ |
Это граница доверия для подключаемых модулей, упакованных и контролируемых ведущим приложением. Это отличается от --plugin-dirаргумента запуска CLI для явной загрузки обычных каталогов подключаемых модулей. Параметр запуска также работает при подключении к существующей среде выполнения, так как он отправляется через JSON-RPC, а не пересылается в качестве аргумента процесса.
Что может внести плагин
Загрузка каталога плагинов делает его расширения видимыми для каждой сессии, созданной клиентом. 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
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
const plugins = await session.rpc.plugins.list();
for (const plugin of plugins.plugins) {
console.log(`${plugin.name} (${plugin.enabled ? "enabled" : "disabled"})`);
}
Плагины, загруженные через --plugin-dir BY, появляются в этом списке с их кэш-путём, установленным в указанной вами директории. Установки маркетплейса отмечены исходным кодом реестра.
Повторная попытка подключаемых модулей, необходимых для управляемых параметров
Если для управляемых параметров требуются подключаемые модули enabledPlugins, среда выполнения устанавливает или обновляет их перед сообщениями чата. Если это не удается, сеанс выдает session.warning запрос и warningType: "managed_plugins" ожидает час или пока управляемые параметры не изменятся, прежде чем повторить попытку. Экспериментальные session.rpc.plugins.retryManaged() попытки повторите попытку сразу, например из действия повтора рядом с этим предупреждением.
Вызовите его без аргументов, чтобы повторить каждый подключаемый модуль, необходимый для управляемых параметров, или передать plugin@marketplace спецификации только plugins для повторных попыток. Результат содержит одну запись для каждого подключаемого status``installedмодуля: , , updated, already_present, failedили not_required``deferred.
failed и deferred записи включают в errorсебя . Сеанс также выдает обычные session.info события хода выполнения и session.warning сбоя.
Node.js / TypeScript
// Retry every plugin the managed settings require, for example from a Retry action.
const result = await session.rpc.plugins.retryManaged();
for (const entry of result.plugins) {
console.log(`${entry.spec}: ${entry.status}${entry.error ? ` (${entry.error})` : ""}`);
}
// Or retry only the required plugins that are still missing.
const { plugins } = await session.rpc.plugins.list();
const missing = plugins
.filter((plugin) => plugin.managedDesiredEnabled === true && plugin.installed === false)
.map((plugin) => `${plugin.name}@${plugin.marketplace}`);
await session.rpc.plugins.retryManaged({ plugins: missing });
Среды выполнения, которые не подготавливают управляемые подключаемые модули для сеанса, отклоняют вызов.
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.
- Использование MCP-серверов с SDK GitHub Copilot: MCP-серверы, предоставляемые плагинами, интегрируются так же, как и встроенные регистрации.
- Режим флота: агенты, предоставленные плагинами, могут диспетчеризироваться как субагенты.