Introduction
Хуки — это внешние команды, которые выполняются в определённых жизненных точках сессии, обеспечивая индивидуальную автоматизацию, управление безопасностью и интеграции.
Крючки поддерживаются двумя Copilot поверхностями: Второй пилот CLI и Copilot облачный агент. Большинство конфигурационных форматов и событий одинаковы, но окружение выполнения и набор событий, которые могут запускаться, различаются.
На протяжении всей статьи поведение, отличающееся между двумя поверхностями, отмечается в заметках «только для CLI» и «только для облачных агентов». Всё, что не отмечено, относится к обеим.
Местоположение крючков
Места, где запускаются крючки и где можно хранить конфигурационные файлы крючков, зависят от поверхности:
-
**Второй пилот CLI ** — крючки запускаются на локальной машине разработчика в той же оболоке, что и CLI. Все события с крючками, описанные в этой статье, поддерживаются CLI.
Хуки загружаются из следующих источников в порядке (пользователь, затем проект, затем плагины) и комбинируются. Когда одно и то же событие появляется в нескольких источниках, выполняются все записи хуков из всех источников.
- Hook на уровне репозитория —
.github/hooks/*.jsonв корне репозитория. - Файлы хуков на уровне пользователя —
*.jsonфайлы в каталоге hooks на уровне пользователя. По умолчанию это~/.copilot/hooks/на macOS и Linux или%USERPROFILE%\.copilot\hooks\на Windows. ЕслиCOPILOT_HOMEустановлено, то это .$COPILOT_HOME/hooks/ - Встроенный
hooksблок в настройках репозитория —hooksполе на верхнем уровне (.github/copilot/settings.jsonGit committed) или.github/copilot/settings.local.json(обычно gitignore и пользователю) в репозитории. Также читаются кросс-инструменты.claude/settings.jsonи.claude/settings.local.jsonфайлы в репозитории. - Встроенный
hooksблок в пользовательской конфигурации —hooksполе на верхнем уровне~/.copilot/settings.json. - Крючки, добавленные установленными плагинами — объявленные каждым плагином в отдельном
hooks.json(или нижеhooks/hooks.json) в каталоге установки плагина.
- Hook на уровне репозитория —
-
**Copilot облачный агент ** — крючки работают внутри эфемерной песочницы Linux, которая предоставляет облачные агенты для каждой задачи. Песочница неинтерактивна, имеет ограниченную сеть и уничтожается после завершения работы. Подмножество событий срабатывает, и признаются только
bash(илиcommand) записи.Конфигурация крючка загружается из
.github/hooks/*.jsonфайлов в клонированном репозитории.
Среда выполнения облачных агентов
Этот раздел применяется только кCopilot облачный агент В нём описываются ограничения, влияющие на то, как вы пишете скрипты hook и настраиваете записи hook для заданий облачных агентов.
| Недвижимость | Ценность |
|---|---|
| Операционная система | Linux. Учитывается только поле bash командных крюков; powershell записи игнорируются. Кросс-платформенное command поле считается запасным вариантом. |
| Рабочий каталог |
`/workspace` когда репозиторий клонируется, иначе `/root`. Используйте этот путь при установке `cwd` записи hook или при ссылке на файлы из скрипта. |
| Filesystem | Эфемерно. Файлы, написанные с помощью hooks (логи, CSV, транскрипты), выбрасываются после окончания работы. Чтобы сохранить выход крючка, отправьте его через http вход с крючком. |
| Исходящая сеть | Ограничен файрволом облачных агентов. По умолчанию доступны только имена хостов GitHub и Copilot; чтобы получить доступ к любому другому хосту (например, https://hooks.example.com), требуется правило разрешения межсетевого экрана, настроенное администратором. |
| Доступные переменные среды |
GITHUB_COPILOT_API_TOKEN и GITHUB_COPILOT_GIT_TOKEN происходят в песочнице.
COPILOT_AGENT_PROMPT удерживает подсказку, с которой была вызвана работа.
HOME установлена на /root, поэтому любой скрипт крюка, разрешающий ~/... пути, записывает в эфемерную песочницу.
GITHUB_TOKEN не задан. |
| Интерактивность | Полностью неинтерактивный. Агент работает с заранее предоставленными всеми разрешениями инструментов, поэтому не отображаются диалоги разрешений и уведомления не появляются пользователю. |
| Обнаружение конфигурации | В задании облачного агента по умолчанию существует единственная конфигурация крючка, которая .github/hooks/*.json существует внутри клонированного репозитория. Песочница не поставляется с пользовательскими hook-файлами, settings.json, config.json, или установленными плагинами. |
Формат конфигурации крючка
Конфигурационные файлы крючка используют формат JSON с версией 1.
Командные крючки
Командные хуки запускают shell-скрипты и поддерживаются на всех типах хуков.
Примечание.
Только облачный агент. Облачный агент запускает крючки в песочнице Linux. Признаётся только поле bash ; powershell заявки игнорируются. Кросс-платформенное command поле считается запасным вариантом.
{
"version": 1,
"hooks": {
"preToolUse": [
{
"type": "command",
"bash": "your-bash-command",
"powershell": "your-powershell-command",
"cwd": "optional/working/directory",
"env": { "VAR": "value" },
"timeoutSec": 30
}
]
}
}
| Поле | Type | Обязательный | Description |
|---|---|---|---|
bash | string | Одно из значений bash, powershell или command. | Команда shell для Unix. |
command | string | Одно из значений bash, powershell или command. | Кроссплатформенный запасной вариант применяется, когда ни то, ни bash``powershell другое не предусмотрено для текущей платформы. |
cwd | string | Нет | Рабочая папка для команды (относительно корня репозитория или абсолюта). |
env | object | Нет | Переменные среды для установки (поддерживает расширение переменных). |
powershell | string | Одно из значений bash, powershell или command. | Команда shell для Windows. |
timeoutSec | Номер | Нет | Время ожидания в секундах. По умолчанию: 30. |
type | "command" | Да | Этот параметр должен содержать значение "command". |
HTTP-крючки
HTTP-хуки отправляют входную полезность в виде JSON POST на URL.
Примечание.
Только облачный агент. Исходящая сеть из песочницы ограничена межсетевым экраном облачного агента, поэтому url должна нацелиться на хост, указанный в списке разрешений.
{
"version": 1,
"hooks": {
"postToolUse": [
{
"type": "http",
"url": "https://hooks.example.com/copilot",
"headers": { "X-Source": "copilot-cli" },
"allowedEnvVars": ["GITHUB_TOKEN"],
"timeoutSec": 30
}
]
}
}
| Поле | Type | Обязательный | Description |
|---|---|---|---|
allowedEnvVars | string[] | Нет | Имена переменных среды, которые могут быть расширены внутри headers значений. Когда установлен, url нужно использовать https://. |
headers | object | Нет | Запросите заголовки для включения. |
timeoutSec | Номер | Нет | Время ожидания в секундах. По умолчанию: 30. |
type | "http" | Да | Этот параметр должен содержать значение "http". |
url | string | Да | Целевой URL-адрес. Обязательно использовать http: или https:. Для preToolUse и permissionRequest, обязательно использовать https:// , потому что ответ может предоставлять разрешения инструментам. |
Подсказочные зацепки
Подсказочные крючки автоматически отправляют текст так, будто его написал сам пользователь. Они поддерживаются только на sessionStart. Текст может быть подсказкой на естественном языке или командой слэша.
Примечание.
**
Второй пилот CLI Только.** Подсказки запускают только для новых интерактивных сессий. Они не срабатывают при возобновлении и не срабатывают в неинтерактивном режиме запросов (-p).
Примечание.
Облачный агент. Задания облачных агентов выполняются неинтерактивно (аналогично -p), поэтому prompt записи с крючками могут не срабатывать. Проверьте поведение в своей среде, прежде чем полагаться на них.
{
"version": 1,
"hooks": {
"sessionStart": [
{
"type": "prompt",
"prompt": "Your prompt text or /slash-command"
}
]
}
}
| Поле | Type | Обязательный | Description |
|---|---|---|---|
type | "prompt" | Да | Этот параметр должен содержать значение "prompt". |
prompt | string | Да | Текст для отправки — это может быть сообщение на естественном языке или команда слэша. |
События с крючками
В таблице ниже перечислены все поддерживаемые события. Столбец «Облачный агент» показывает, срабатывает ли событие под облачным агентом, и отмечает различия в поведении.
| Событие | Срабатывает, когда | Обработка выхода | Облачный агент |
|---|---|---|---|
agentStop | Главный агент завершает ход. | Да — может блокировать и заставлять продолжение. | Пожары. |
`decision: "block"` заставляет делать ещё один ход, который всё равно учитывается в тайм-ауте работы. |
| errorOccurred | Ошибка возникает во время выполнения. | Нет | Пожары. |
| notification | Срабатывает асинхронно, когда CLI отправляет системное уведомление (завершение оболочки, завершение работы агента или простоя, запросы разрешения, диалоги вызова). Удар и забыть: никогда не блокирует сессию. Поддерживает matcher regex на notification_type. | Опционально — можно вводить additionalContext в сессию. |
Не стреляет. Облачный агент не отображает уведомления пользователю (см. строку интерактивности в таблице среды выполнения облачных агентов выше). |
| permissionRequest | Срабатывает до запуска сервиса разрешений (движок правил, утверждение сессии, авторазрешение/автозапрет и подсказка пользователя). Если выход объединённого крючка возвращается behavior: "allow" или "deny", это решение приводит к короткому замыканию нормального потока разрешений. Поддерживает matcher regex на toolName. | Да — можно разрешить или отклонить программно. | Вызовы инструментов предварительно одобрены, поэтому этот крюк либо не срабатывает, либо не действует. Используйте preToolUse для принятия решений по разрешению. |
| postToolUse | После успешного завершения каждого инструмента. | Нет | Пожары. |
| postToolUseFailure | После того, как инструмент завершается с неудачей. | Да — может предоставить навигацию по восстановлению через additionalContext (код 2 выхода для командных хуков). | Пожары. |
| preCompact | Вот-вот начнётся уплотнение контекста (ручное или автоматическое). Поддерживают matcher фильтрацию по триггерам ("manual" или "auto"). | Нет — только уведомление. | Огонь только с trigger: "auto". Нет пользователя, который бы запросил ручное уплотнение. |
| preToolUse | Перед тем, как каждый инструмент сработает. | Да — можно разрешать, отрицать или изменять. | Пожары. Решение считается "ask" так "deny" , что нет доступного пользователя для ответа. |
| sessionEnd | Сессия заканчивается. | Нет | Пожары — один раз за работу.
reason обычно "complete", "error", или "timeout"; "abort" и "user_exit" не ожидаются, потому что пользователя нет. |
| sessionStart | Начинается новая или возобновлённая сессия. | Опционально — можно вводить additionalContext в сессию. | Уволяется один раз за каждую работу, как новая сессия (не резюме). См. примечание Prompt hooks выше для поведения prompt записей в облачном агенте. |
| subagentStart | Появляется субагент (до его запуска). Поддерживает matcher фильтрацию по имени агента. | Опционально — не может блокировать создание, но additionalContext предшествует подсказке субагента. | Пожары. |
| subagentStop | Субагент завершает. | Да — может блокировать и заставлять продолжение. | Пожары. |
| userPromptSubmitted | Пользователь отправляет запрос. | Нет | Срабатывает максимум один раз — по запросу, который подают на работу. Нет никакого дополнительного ввода пользователя. |
Полезные нагрузки для ввода событий hook
Каждое событие с крючком доставляет JSON-полезную нагрузку обработчику крючков. Поддерживаются два формата полезной нагрузки, выбираемых по имени события, используемому в конфигурации крючка:
- camelCase format — Настройте имя события в camelCase (например,
sessionStart). Поля используют CamelCase. - VS Code совместимый формат — Настройте имя события в PascalCase (например,
SessionStart). Поля используют snake_case для соответствия VS CodeCopilot формату расширения.
sessionStart / SessionStart
**Ввод CamelCase:**
{
sessionId: string;
timestamp: number; // Unix timestamp in milliseconds
cwd: string;
source: "startup" | "resume" | "new";
initialPrompt?: string;
}
**
VS Code Совместимый вход:**
{
hook_event_name: "SessionStart";
session_id: string;
timestamp: string; // ISO 8601 timestamp
cwd: string;
source: "startup" | "resume" | "new";
initial_prompt?: string;
}
sessionEnd / SessionEnd
**Ввод CamelCase:**
{
sessionId: string;
timestamp: number;
cwd: string;
reason: "complete" | "error" | "abort" | "timeout" | "user_exit";
}
**
VS Code Совместимый вход:**
{
hook_event_name: "SessionEnd";
session_id: string;
timestamp: string; // ISO 8601 timestamp
cwd: string;
reason: "complete" | "error" | "abort" | "timeout" | "user_exit";
}
userPromptSubmitted / UserPromptSubmit
**Ввод CamelCase:**
{
sessionId: string;
timestamp: number;
cwd: string;
prompt: string;
}
**
VS Code Совместимый вход:**
{
hook_event_name: "UserPromptSubmit";
session_id: string;
timestamp: string; // ISO 8601 timestamp
cwd: string;
prompt: string;
}
preToolUse / PreToolUse
**Ввод CamelCase:**
{
sessionId: string;
timestamp: number;
cwd: string;
toolName: string;
toolArgs: unknown;
}
**
VS Code Совместимый вход:**
При настройке с именем PreToolUseсобытия PascalCase полезная нагрузка использует snake_case имена полей, чтобы соответствовать формату VS CodeCopilot расширения:
{
hook_event_name: "PreToolUse";
session_id: string;
timestamp: string; // ISO 8601 timestamp
cwd: string;
tool_name: string;
tool_input: unknown; // Tool arguments (parsed from JSON string when possible)
}
postToolUse / PostToolUse
**Ввод CamelCase:**
{
sessionId: string;
timestamp: number;
cwd: string;
toolName: string;
toolArgs: unknown;
toolResult: {
resultType: "success";
textResultForLlm: string;
}
}
**
VS Code Совместимый вход:**
{
hook_event_name: "PostToolUse";
session_id: string;
timestamp: string; // ISO 8601 timestamp
cwd: string;
tool_name: string;
tool_input: unknown;
tool_result: {
result_type: "success";
text_result_for_llm: string;
}
}
postToolUseFailure / PostToolUseFailure
**Ввод CamelCase:**
{
sessionId: string;
timestamp: number;
cwd: string;
toolName: string;
toolArgs: unknown;
error: string;
}
**
VS Code Совместимый вход:**
{
hook_event_name: "PostToolUseFailure";
session_id: string;
timestamp: string; // ISO 8601 timestamp
cwd: string;
tool_name: string;
tool_input: unknown;
error: string;
}
agentStop / Stop
**Ввод CamelCase:**
{
sessionId: string;
timestamp: number;
cwd: string;
transcriptPath: string;
stopReason: "end_turn";
}
**
VS Code Совместимый вход:**
{
hook_event_name: "Stop";
session_id: string;
timestamp: string; // ISO 8601 timestamp
cwd: string;
transcript_path: string;
stop_reason: "end_turn";
}
subagentStart
**Входные данные:**
{
sessionId: string;
timestamp: number;
cwd: string;
transcriptPath: string;
agentName: string;
agentDisplayName?: string;
agentDescription?: string;
}
subagentStop / SubagentStop
**Ввод CamelCase:**
{
sessionId: string;
timestamp: number;
cwd: string;
transcriptPath: string;
agentName: string;
agentDisplayName?: string;
stopReason: "end_turn";
}
**
VS Code Совместимый вход:**
{
hook_event_name: "SubagentStop";
session_id: string;
timestamp: string; // ISO 8601 timestamp
cwd: string;
transcript_path: string;
agent_name: string;
agent_display_name?: string;
stop_reason: "end_turn";
}
errorOccurred / ErrorOccurred
**Ввод CamelCase:**
{
sessionId: string;
timestamp: number;
cwd: string;
error: {
message: string;
name: string;
stack?: string;
};
errorContext: "model_call" | "tool_execution" | "system" | "user_input";
recoverable: boolean;
}
**
VS Code Совместимый вход:**
{
hook_event_name: "ErrorOccurred";
session_id: string;
timestamp: string; // ISO 8601 timestamp
cwd: string;
error: {
message: string;
name: string;
stack?: string;
};
error_context: "model_call" | "tool_execution" | "system" | "user_input";
recoverable: boolean;
}
preCompact / PreCompact
**Ввод CamelCase:**
{
sessionId: string;
timestamp: number;
cwd: string;
transcriptPath: string;
trigger: "manual" | "auto";
customInstructions: string;
}
**
VS Code Совместимый вход:**
{
hook_event_name: "PreCompact";
session_id: string;
timestamp: string; // ISO 8601 timestamp
cwd: string;
transcript_path: string;
trigger: "manual" | "auto";
custom_instructions: string;
}
preToolUse Контроль принятия решений
Крюк preToolUse может управлять выполнением инструмента, записывая JSON-объект в stdout.
| Поле | Ценности | Description |
|---|---|---|
permissionDecision |
`"allow"`, , `"deny"``"ask"` | Работает ли инструмент. Пустой выход использует стандартное поведение. В облачном агенте `"ask"` рассматривается как `"deny"` отсутствие доступного пользователя для ответа. |
| permissionDecisionReason | string | Агенту показали разум. Требуется при принятии решения "deny". |
| modifiedArgs | object | Замените аргументы инструментов вместо оригиналов. |
agentStop
/
`subagentStop` Контроль принятия решений
| Поле | Ценности | Description |
|---|---|---|
decision |
`"block"`, `"allow"` |
`"block"` заставляет другого агента поступить, используя `reason` это как подсказку. |
| reason | string | Подсказка для следующего хода, когда decision ."block" |
permissionRequest Контроль принятия решений
Примечание.
**
Второй пилот CLI Только.** Крючок permissionRequest не применяется в Copilot облачный агент— вызовы инструментов там предварительно одобрены (см. строку интерактивности в таблице среды исполнения облачных агентов). Используйте preToolUse для принятия решений по разрешению в облачном агенте.
`permissionRequest` Крюк срабатывает до запуска сервиса разрешений — до проверки правил, одобрения сессии, авторазрешения/автозапрета и подсказки пользователя. Если крючки возвращаются `behavior: "allow"` или `"deny"`, это решение приводит к короткому замыканию нормального потока разрешений. Возврат ничего не выходит на обычную обработку разрешений. Используйте его для программного одобрения или отклонения вызовов инструментов — особенно полезно в режиме CLI pipe (`-p`) и других CLI CI, где нет интерактивного запроса. Это не относится к облачному агенту.
Все настроенные permissionRequest крючки работают для каждого запроса (кроме read типов hook с разрешениями, которые срабатывают перед хуками). Выходы крючка объединяются с более поздними выходами хука, переопределяя более ранние.
**Матчер:** Необязательный регулярный выражение, тестируемое против `toolName`. Закрепленное как `^(?:pattern)$`; должно совпадать с полным именем инструмента. При установке крюк срабатывает только при совпадающих названиях инструментов.
Выводите JSON в stdout, чтобы контролировать решение о разрешении:
| Поле | Ценности | Description |
|---|---|---|
behavior |
`"allow"`, `"deny"` | Одобрить или отклонить этот инструмент. |
| message | string | Причина возвращалась к LLM при отказе. |
| interrupt | boolean | В true сочетании с "deny", агент полностью останавливается. |
Вернуть пустой выход или {} провалиться в нормальный поток разрешений. Для командных хуков выходной код 2 рассматривается как отказ; stdout JSON (если он есть) объединяется с {"behavior":"deny"}, а stderr игнорируется.
notification Крюк
Примечание.
**
Второй пилот CLI Только.**
notification Крюк не стреляет под Copilot облачный агент.
`notification` Крюк срабатывает асинхронно, когда CLI издаёт системное уведомление. Эти хуки — это система «убери и забудь»: они никогда не блокируют сессию, а любые ошибки фиксируются и пропускаются.
**Входные данные:**
{
sessionId: string;
timestamp: number;
cwd: string;
hook_event_name: "Notification";
message: string; // Human-readable notification text
title?: string; // Short title (e.g., "Permission needed", "Shell completed")
notification_type: string; // One of the types listed below
}
**Типы уведомлений:**
| Type | Когда он срабатывает |
|---|---|
shell_completed | Заканчивается фоновая (асинхронная) команда shell |
shell_detached_completed | Завершается отделённая оболочная сессия |
agent_completed | Фоновый субагент заканчивает (выполнен или неудачно) |
agent_idle | Агент фона заканчивает ход и переходит в состояние простоя (ожидание write_agent) |
permission_prompt | Агент запрашивает разрешение на запуск инструмента |
elicitation_dialog | Агент запрашивает дополнительную информацию у пользователя |
**Output:**
{
additionalContext?: string; // Injected into the session as a user message
}
Если additionalContext он возвращается, текст вводится в сессию в виде предварительного пользовательского сообщения. Это может запустить дальнейшую обработку агентов, если сессия находится в простое. Возврат {} или опустошение выхода, чтобы не предпринимать действия.
**Матчер:** Опциональный регуляр на `notification_type`. Паттерн закреплён как `^(?:pattern)$`. Опустите `matcher` все типы уведомлений.
Фильтрация матчеров
Несколько событий принимают необязательный matcher регулярный выражений на каждом записи крюка, который фильтрует и вызывает срабатывание хука. Узор закреплён как ^(?:matcher)$ и должен соответствовать полному значению. Некорректные регексы приводят к пропуску записи с крюком.
| Событие |
matcher против него встречается |
|-------|------------------------------|
| notification | notification_type |
| permissionRequest | toolName |
| preCompact |
trigger ("manual" или "auto") |
| preToolUse | toolName |
| subagentStart | agentName |
Имена инструментов для подбора крючков
| Имя инструмента | Description |
|---|---|
ask_user | Задайте пользователю уточняющий вопрос. В облачном агенте нет пользователя, поэтому ask_user не даёт полезного результата. |
bash | Выполнять команды оболочки (Unix). |
create | Создавайте новые файлы. |
edit | Изменять содержимое файла. |
glob | Ищите файлы по шаблону. |
grep | Поиск по содержимому файла. |
powershell | Выполнять команды shell (Windows). Не отображается в облачном агенте (песочница Linux). |
task | Запускайте задачи субагентов. |
view | Чтение содержимого файла. |
web_fetch | Загружайте веб-страницы. |
Если настраивать несколько хуков одного типа, они выполняются по порядку. Для preToolUse, если какой-либо крюк возвращается "deny", инструмент блокируется. Сбои хуков (ненулевые коды выхода, кроме 2, или тайм-ауты) регистрируются и пропускаются — они никогда не блокируют выполнение агента.
Коды выхода для командных крючков
| Код выхода | Значение |
|---|---|
0 | Успех. |
`stdout` парсируется как выходной JSON для хука, если он присутствует. |
| 2 | По умолчанию это воспринимается как предупреждение.
stderr показывают пользователю, но забег продолжается. Для permissionRequest, выход 2 рассматривается как {"behavior":"deny"} , и любой stdout JSON объединяется. Для , выход 2 рассматривается как additionalContext и stdout добавляется к неудаче, postToolUseFailureпоказанному агенту. |
| Другие ненулевые значения | Зарегистрировано как сбой с крюком. Запуск продолжается (fail-open). |
Отключить все крючки
Используйте disableAllHooks его, когда хотите сохранить конфигурацию крючка на диске, но остановить её работу — например:
- Отладка проблемы — и вы хотите убедиться, что причиной является крючок, не удаляя конфигурацию.
- Приостановка автоматизации во время чувствительной задачи (обзор кода, ветка выпуска, работа с секретами) без потери настройки. (Второй пилот CLI только.)
- Отправка файла hooks в системе контроля версий, от которого участники могут отказаться локально, установив эту опцию в своём репозитории
settings.json. (Второй пилот CLI только.) - Временное отключение медленных или шумных хуков во время интерактивной сессии. (Второй пилот CLI только.)
Установите disableAllHooks верхний true уровень, чтобы пропускать все крючки в файле без удаления.
{
"version": 1,
"disableAllHooks": false,
"hooks": {
"preToolUse": [ /* hook entries */ ]
}
}
Поведение зависит от того, где вы устанавливаете флаг:
- Внутри одного
.github/hooks/*.jsonфайла пропускаются только объявленные крючки. Удостоен уважения от обоих Второй пилот CLI и Copilot облачный агент. - На верхнем уровне репозитория
settings.json— Второй пилот CLI только. Каждый хук из каждого источника (файлы репозитория, пользовательские файлы, плагины и встроенные блоки хуков) пропускается для сессий в этом репозитории. Облачный агент не загружаетсяsettings.json.