Хуки
Хуки
Запускайте детерминированные скрипты в течение жизненного цикла Codex
Хуки — это механизм расширения возможностей Codex. Они позволяют запускать скрипты или инструменты MCP во время агентного цикла и реализовывать такие возможности, как:
- Отправка чата в пользовательскую систему журналирования или аналитики
- Проверка запросов вашей команды, предотвращающая случайную вставку API keys
- Автоматическое резюмирование чатов для создания постоянной памяти
- Запуск пользовательской проверки при завершении хода чата для обеспечения соблюдения стандартов
- Настройка запросов при работе в определённом каталоге
Особенности поведения во время выполнения:
- Запускаются все подходящие хуки из нескольких файлов.
- Несколько подходящих командных хуков для одного события запускаются параллельно, поэтому один хук не может помешать запуску другого подходящего хука.
- Перед запуском неуправляемые хуки необходимо проверить и признать доверенными.
Хуки запускаются на разных этапах диалога:
| Когда | Хуки |
|---|---|
| Во время хода | PreToolUse, PermissionRequest, PostToolUse, PreCompact, PostCompact, UserPromptSubmit, SubagentStop, Stop |
| При прерывании активного хода | Interrupt (не выполняется для субагентов) |
| При запуске сеанса или субагента | SessionStart, SubagentStart |
| При завершении основного потока | SessionEnd (не выполняется для субагентов) |
Где Codex ищет хуки
Codex обнаруживает хуки рядом с активными уровнями конфигурации в одной из следующих форм:
hooks.json- встроенные таблицы
[hooks]вconfig.toml
Установленные плагины также могут включать конфигурацию жизненного цикла через свой
манифест или стандартный файл hooks/hooks.json. Правила упаковки
плагинов приведены в разделе Создание
плагинов.
На практике наиболее полезны следующие четыре расположения:
~/.codex/hooks.json~/.codex/config.toml<repo>/.codex/hooks.json<repo>/.codex/config.toml
Если существует несколько источников хуков, Codex загружает все подходящие хуки.
Уровни конфигурации с более высоким приоритетом не заменяют хуки с уровней с более низким приоритетом.
Если один уровень содержит и hooks.json, и встроенные [hooks], Codex
объединяет их и при запуске выводит предупреждение. На каждом уровне рекомендуется использовать один вариант представления.
Codex также может обнаруживать хуки, входящие в состав включённых плагинов. Хуки из плагинов загружаются вместе с хуками из других источников и проходят ту же процедуру проверки доверия, что и остальные неуправляемые хуки.
Локальные хуки проекта загружаются, только если уровень проекта .codex/ является доверенным. В
недоверенных проектах Codex по-прежнему загружает пользовательские и системные хуки из их собственных
активных уровней конфигурации.
Проверка хуков и управление доверием
Прежде чем определить, какие хуки можно запускать, Codex выводит список настроенных хуков. Перед запуском неуправляемого хука Codex требует проверить конкретное определение хука и признать его доверенным. Codex привязывает доверие к текущему хешу хука, поэтому новые или изменённые хуки помечаются как требующие проверки и пропускаются до подтверждения доверия.
Используйте /hooks в CLI, чтобы просматривать источники хуков, проверять новые или изменённые хуки,
признавать их доверенными либо отключать отдельные неуправляемые хуки. Если при
запуске хуки требуют проверки, Codex выводит предупреждение с предложением открыть /hooks.
Управляемые хуки из системных, MDM, облачных источников или источников requirements.toml помечаются
как управляемые, считаются доверенными согласно политике и не могут быть отключены в пользовательском средстве просмотра хуков.
Для однократной автоматизации, в которой источники хуков уже проверяются вне Codex, передайте
--dangerously-bypass-hook-trust, чтобы запустить включённые хуки без необходимости
сохранять доверие к ним для этого вызова.
Структура конфигурации
Хуки организованы на трёх уровнях:
- Событие хука, например
PreToolUse,PostToolUse,PreCompact,SubagentStartилиStop - Группа сопоставления, определяющая условия соответствия событию
- Один или несколько обработчиков хуков, запускаемых при совпадении группы
{
"description": "Optional lifecycle hooks for this workspace.",
"hooks": {
"SessionStart": [
{
"matcher": "startup|resume",
"hooks": [
{
"type": "command",
"command": "python3 ~/.codex/hooks/session_start.py",
"statusMessage": "Loading session notes",
"additionalContextLimit": 5000
}
]
}
],
"SessionEnd": [
{
"hooks": [
{
"type": "command",
"command": "python3 ~/.codex/hooks/session_end.py",
"timeout": 3
}
]
}
],
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "/usr/bin/python3 \"$(git rev-parse --show-toplevel)/.codex/hooks/pre_tool_use_policy.py\"",
"statusMessage": "Checking Bash command"
}
]
}
],
"PermissionRequest": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "/usr/bin/python3 \"$(git rev-parse --show-toplevel)/.codex/hooks/permission_request.py\"",
"statusMessage": "Checking approval request"
}
]
}
],
"PostToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "/usr/bin/python3 \"$(git rev-parse --show-toplevel)/.codex/hooks/post_tool_use_review.py\"",
"statusMessage": "Reviewing Bash output"
}
]
}
],
"UserPromptSubmit": [
{
"hooks": [
{
"type": "command",
"command": "/usr/bin/python3 \"$(git rev-parse --show-toplevel)/.codex/hooks/user_prompt_submit_data_flywheel.py\""
}
]
}
],
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "/usr/bin/python3 \"$(git rev-parse --show-toplevel)/.codex/hooks/stop_continue.py\"",
"timeout": 30
}
]
}
]
}
}Примечания:
description— необязательные метаданные верхнего уровня для файлаhooks.json. Они не влияют на то, какие хуки выполняются.timeoutзадаётся в секундах.- Если
timeoutне указан, Codex использует600секунд для большинства хуков.- Для
SessionEndиInterruptпо умолчанию используется1секунда, а максимальное значение составляет3секунды.
- Для
statusMessage— необязательный параметр.additionalContextLimitопределяет, какой объёмadditionalContextкомандный хук может отправить модели, прежде чем Codex сохранит полный текст на диск и вместо него отправит сокращённый предварительный просмотр. См. раздел Большой объём вывода хука.commandWindows— необязательное переопределение команды только для Windows. В TOML используйтеcommand_windowsилиcommandWindows.- Установите для
asyncзначениеtrue, чтобы запускать командный хук в фоновом режиме. - Поддерживаются обработчики
commandиmcp_tool. Обработчикиpromptиagentразбираются, но пропускаются. - Команды выполняются с каталогом
cwdсеанса в качестве рабочего каталога. - Для хуков внутри репозитория предпочтительно определять путь от корня git, а не использовать
относительный путь, например
.codex/hooks/.... Codex может быть запущен из подкаталога, а путь на основе корня git сохраняет расположение хука неизменным.
Эквивалентная встроенная конфигурация TOML в config.toml:
[[hooks.SessionStart]]
matcher = "^compact$"
[[hooks.SessionStart.hooks]]
type = "command"
command = '/usr/bin/python3 "$(git rev-parse --show-toplevel)/.codex/hooks/session_start.py"'
additionalContextLimit = 5000
[[hooks.PreToolUse]]
matcher = "^Bash$"
[[hooks.PreToolUse.hooks]]
type = "command"
command = '/usr/bin/python3 "$(git rev-parse --show-toplevel)/.codex/hooks/pre_tool_use_policy.py"'
timeout = 30
statusMessage = "Checking Bash command"
[[hooks.PostToolUse]]
matcher = "^Bash$"
[[hooks.PostToolUse.hooks]]
type = "command"
command = '/usr/bin/python3 "$(git rev-parse --show-toplevel)/.codex/hooks/post_tool_use_review.py"'
timeout = 30
statusMessage = "Reviewing Bash output"Хуки инструментов MCP
Хук инструмента MCP позволяет событию жизненного цикла вызывать инструмент на уже подключённом сервере MCP. Он передаёт структурированные аргументы непосредственно инструменту и использует тот же механизм проверки доверия и контракт вывода, что и командный хук.
Настройка хука инструмента MCP
Этот хук просит сервер MCP scanner сканировать каждое изменение после того, как Codex записывает или
редактирует файлы:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "mcp_tool",
"server": "scanner",
"tool": "scan_patch",
"input": { "patch": "${tool_input.command}" },
"timeout": 30,
"statusMessage": "Scanning edited files"
}
]
}
]
}
}| Поле | Значение |
|---|---|
type |
Должно иметь значение mcp_tool. |
server |
Обязательное имя уже подключённого сервера MCP. |
tool |
Обязательное имя инструмента, предоставляемого этим сервером. |
input |
Необязательный объект JSON с шаблонами аргументов. По умолчанию {}. |
timeout |
Необязательный тайм-аут активного выполнения в секундах. По умолчанию 600. |
statusMessage |
Необязательное сообщение, отображаемое во время работы хука. |
Подстановка аргументов из события хука
Используйте ${field.nested}, чтобы прочитать вложенное поле события хука. Заполнитель,
который занимает всё значение, сохраняет свой тип JSON. Заполнитель внутри более длинной
строки преобразуется в текст. Codex рекурсивно обрабатывает объекты и массивы.
Для события, содержащего {"tool_input":{"file_path":"src/main.rs","count":3}},
этот шаблон аргументов:
{
"path": "${tool_input.file_path}",
"count": "${tool_input.count}",
"message": "Scanning ${tool_input.file_path}"
}преобразуется в:
{
"path": "src/main.rs",
"count": 3,
"message": "Scanning src/main.rs"
}Выполнение и жизненный цикл
- Хуки используют существующее подключение MCP. Они не запускают серверы и не подключаются к ним повторно.
- Хук может заблокировать операцию, если инструмент возвращает решение о блокировке. Ошибки, отсутствующие серверы и недоступные инструменты не блокируют операцию.
- Хуки инструментов MCP выполняются синхронно. Они не запрашивают подтверждение инструмента и не запускают другие хуки.
- Применяется более короткий из тайм-аутов хука и сервера. Время ожидания ответа на запрос дополнительной информации MCP не засчитывается в тайм-аут.
- Хуки
SessionStartмогут запускаться до готовности сервера MCP. В таком случае они не блокируют сеанс. SessionEndне поддерживает хуки инструментов MCP.
Отключение хуков
По умолчанию хуки включены. Чтобы отключить их в config.toml, задайте:
[features]
hooks = falseИспользуйте hooks как канонический ключ функции. codex_hooks по-прежнему работает как
устаревший псевдоним. Администраторы могут принудительно отключить хуки аналогичным образом в
requirements.toml с помощью [features].hooks = false.
Управляемые хуки из requirements.toml
Требования, управляемые на уровне организации, также могут определять встроенные хуки в [hooks].
Это удобно, когда администраторам нужно принудительно применять конфигурацию хуков, а
сами скрипты распространять через MDM или другую систему управления устройствами.
Чтобы принудительно применять управляемые хуки даже для пользователей, отключивших хуки локально, закрепите
[features].hooks = true в requirements.toml вместе с [hooks]. Чтобы игнорировать
пользовательские хуки, хуки проекта, сеанса и плагинов, но по-прежнему разрешать управляемые
администратором хуки, установите allow_managed_hooks_only = true.
allow_managed_hooks_only = true
[features]
hooks = true
[hooks]
managed_dir = "/enterprise/hooks"
windows_managed_dir = 'C:\enterprise\hooks'
[[hooks.PreToolUse]]
matcher = "^Bash$"
[[hooks.PreToolUse.hooks]]
type = "command"
command = "python3 /enterprise/hooks/pre_tool_use_policy.py"
command_windows = 'py -3 C:\enterprise\hooks\pre_tool_use_policy.py'
timeout = 30
statusMessage = "Checking managed Bash command"Примечания об управляемых хуках:
managed_dirиспользуется в macOS и Linux.windows_managed_dirиспользуется в Windows.- Codex не распространяет скрипты из
managed_dir; корпоративные инструменты должны устанавливать и обновлять их отдельно. - Команды управляемых хуков должны использовать абсолютные пути к скриптам в настроенном управляемом каталоге.
allow_managed_hooks_only = trueпропускает хуки из пользовательских источников, источников проекта, сеанса и плагинов, но продолжает загружать управляемые хуки изrequirements.tomlи других управляемых уровней конфигурации.
Хуки из плагинов
Когда плагин включён, Codex может загружать хуки жизненного цикла из этого плагина вместе с пользовательскими, проектными и управляемыми хуками.
По умолчанию Codex ищет hooks/hooks.json в корне плагина. Манифест
плагина может переопределить это значение с помощью записи hooks в
.codex-plugin/plugin.json. Запись манифеста может быть путём с префиксом ./, массивом
путей с префиксом ./, встроенным объектом хуков или массивом встроенных
объектов хуков.
{
"name": "repo-policy",
"hooks": "./hooks/hooks.json"
}Пути к хукам в манифесте разрешаются относительно корня плагина и не должны выходить
за его пределы. Если манифест определяет hooks, Codex использует эти записи
манифеста вместо стандартного hooks/hooks.json.
Команды хуков плагина получают следующие переменные среды:
PLUGIN_ROOT— специальное расширение Codex, указывающее на корень установленного плагина.PLUGIN_DATA— специальное расширение Codex, указывающее на доступный для записи каталог данных плагина.- Для совместимости с существующими хуками плагинов Codex также задаёт
CLAUDE_PLUGIN_ROOTиCLAUDE_PLUGIN_DATA.
Хуки плагинов используют ту же схему событий, что и остальные хуки. Установка или включение плагина не делает его хуки автоматически доверенными; Codex пропускает хуки из плагина, пока вы не проверите текущее определение хука и не признаете его доверенным.
Шаблоны сопоставления
Поле matcher содержит строку регулярного выражения, определяющую условия срабатывания хуков. Используйте "*",
"" или полностью опустите matcher, чтобы сопоставлять каждое возникновение поддерживаемого
события.
Только некоторые текущие события Codex учитывают matcher:
| Событие | Что фильтрует matcher |
Примечания |
|---|---|---|
PermissionRequest |
имя инструмента | Поддерживаются Bash, apply_patch* и имена инструментов MCP |
PostToolUse |
имя инструмента | См. Охват инструментов |
PostCompact |
триггер сжатия | Возможные значения: manual или auto |
PreCompact |
триггер сжатия | Возможные значения: manual или auto |
PreToolUse |
имя инструмента | См. Охват инструментов |
SessionEnd |
причина завершения | В настоящее время только other |
SessionStart |
источник запуска | Возможные значения: startup, resume, clear и compact |
SubagentStart |
тип субагента | Значения зависят от запускаемого субагента |
SubagentStop |
тип субагента | Значения зависят от останавливаемого субагента |
UserPromptSubmit |
не поддерживается | Любой настроенный matcher игнорируется для этого события |
Stop |
не поддерживается | Любой настроенный matcher игнорируется для этого события |
Interrupt |
не поддерживается | Любой настроенный matcher игнорируется для этого события |
*Для apply_patch значения matcher также могут использовать Edit или Write.
Примеры:
Bash^apply_patch$Edit|Writemcp__filesystem__read_filemcp__filesystem__.*startup|resume|clear|compactmanual|auto
Охват инструментов
PreToolUse и PostToolUse могут отслеживать не только вызовы оболочки и MCP. Большинство
локальных функциональных инструментов используют тот же механизм хуков, поэтому вы можете сопоставлять их имена,
проверять их аргументы JSON, а в случае PreToolUse — блокировать или изменять вызов.
| Путь инструмента | PreToolUse |
PostToolUse |
Примечания |
|---|---|---|---|
| Команды оболочки | Да | Да | Сопоставляется как Bash. |
Унифицированное выполнение (exec_command) |
Да | Да | Сопоставляется как Bash. Последующий опрос write_stdin может передать PostToolUse исходной команды после её завершения. |
apply_patch |
Да | Да | Сопоставляется как apply_patch, Edit или Write. |
| Инструменты MCP | Да | Да | Сопоставляется имя инструмента MCP, например mcp__filesystem__read_file. |
| Другие локальные функциональные инструменты | Да | Да | Сопоставляется имя функционального инструмента, например update_plan. spawn_agent также соответствует Agent. |
Размещённые инструменты, например WebSearch |
Нет | Нет | Они не используют механизм хуков локальных функциональных инструментов. |
write_stdin служит транспортом для существующего сеанса унифицированного выполнения. Он не запускает
PreToolUse повторно при отправке ввода или опросе команды, которая уже прошла
PreToolUse.
Некоторые специализированные пути инструментов могут не использовать стандартный механизм хуков. Рассматривайте хуки инструментов как полезную дополнительную защиту, а не как исчерпывающую границу контроля.
Общие поля ввода
Каждый командный хук получает один объект JSON через stdin.
Ниже приведены общие поля, которые обычно используются:
| Поле | Тип | Значение |
|---|---|---|
session_id |
string |
ID текущего сеанса Codex. Хуки субагентов используют ID родительского сеанса. |
transcript_path |
string | null |
Путь к файлу расшифровки сеанса, если он существует |
cwd |
string |
Рабочий каталог сеанса |
hook_event_name |
string |
Имя текущего события хука |
model |
string |
Специальное расширение Codex. Идентификатор активной модели |
В таблицах событий для хуков, ограниченных ходом, turn_id указан как специальное расширение Codex.
SessionStart, PreToolUse, PermissionRequest, PostToolUse,
UserPromptSubmit, SubagentStart, SubagentStop, Stop и Interrupt также включают
permission_mode, который описывает текущий режим разрешений как default,
acceptEdits, plan, dontAsk или bypassPermissions.
Для удобства transcript_path указывает на расшифровку чата, но формат
расшифровки не является стабильным интерфейсом для хуков и со временем может измениться.
Полный формат обмена данными приведён в разделе Схемы.
Общие поля вывода
SessionStart, PreCompact, PostCompact, UserPromptSubmit,
SubagentStop и Stop поддерживают следующие общие поля JSON. SubagentStart
принимает ту же структуру для systemMessage и контекста конкретного хука, но
continue: false не останавливает субагента:
{
"continue": true,
"stopReason": "optional",
"systemMessage": "optional",
"suppressOutput": false
}| Поле | Результат |
|---|---|
continue |
Если false, этот запуск хука помечается как остановленный |
stopReason |
Записывается как причина остановки |
systemMessage |
Отображается как предупреждение в UI или потоке событий |
suppressOutput |
Сейчас разбирается, но ещё не реализовано |
Завершение с кодом 0 без вывода считается успешным, и Codex продолжает работу.
PreToolUse и PermissionRequest поддерживают systemMessage, но continue,
stopReason и suppressOutput сейчас не поддерживаются для этих событий.
Если хук PreToolUse возвращает одно из этих неподдерживаемых полей, Codex помечает
запуск хука как неудачный, сообщает об ошибке и продолжает вызов инструмента.
PostToolUse поддерживает systemMessage, continue: false и stopReason.
suppressOutput разбирается, но сейчас не поддерживается для этого события.
Большой объём вывода хука
По умолчанию Codex ограничивает каждое видимое модели сообщение с выводом хука примерно
2 500 токенами. Если хук возвращает больший объём, Codex сохраняет полный текст в
<temp_dir>/hook_outputs/<session_id>/<uuid>.txt и передаёт модели
предварительный просмотр начала и конца текста с путём к сохранённому файлу. Это поведение называется
выгрузкой: Codex сохраняет слишком большой вывод на диск и заменяет его более
коротким предварительным просмотром, видимым модели. Если записать файл не удаётся, модель всё равно
получает усечённый предварительный просмотр.
Для любого командного хука, возвращающего additionalContext, задайте
additionalContextLimit в обработчике, чтобы настроить приблизительный порог
в токенах:
{
"type": "command",
"command": "python3 ~/.codex/hooks/session_start.py",
"additionalContextLimit": 5000
}Не указывайте additionalContextLimit, чтобы использовать стандартный порог в 2500 токенов. Укажите
положительное целое число, чтобы выбрать другой порог, или 0, чтобы передать модели полный
дополнительный контекст обработчика напрямую. Codex оценивает каждый
подходящий обработчик независимо. Для событий, которые не могут создавать дополнительный
контекст, Codex игнорирует additionalContextLimit и выводит предупреждение
о конфигурации.
Эта настройка применяется только к additionalContext. Для обратной связи от инструментов и запросов
продолжения сохраняется стандартное ограничение.
Поскольку слишком большой вывод может быть записан на диск, не возвращайте в выводе хука секреты или другие конфиденциальные данные.
Запуск хуков в фоновом режиме
По умолчанию Codex ожидает завершения командного хука, прежде чем продолжить
операцию, которая его запустила. Установите async в true, чтобы запустить командный хук в
фоновом режиме, пока Codex продолжает работу.
Настройка фонового хука
Добавьте "async": true в обработчик команды в hooks.json:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "python3 ~/.codex/hooks/post_tool_use.py",
"async": true,
"timeout": 120
}
]
}
]
}
}Для встроенного хука в config.toml задайте async = true:
[[hooks.PostToolUse]]
matcher = "Bash"
[[hooks.PostToolUse.hooks]]
type = "command"
command = "python3 ~/.codex/hooks/post_tool_use.py"
async = true
timeout = 120Фоновые хуки используют те же входные данные, сопоставление, проверку доверия, тайм-аут и
обработку большого объёма вывода, что и синхронные командные хуки. Как и
для других командных хуков, timeout измеряется в секундах и по умолчанию имеет значение
600. Для хуков Interrupt значение по умолчанию составляет одну секунду, а максимальное — три секунды,
в том числе при выполнении в фоновом режиме.
Выполнение фоновых хуков
Когда фоновый хук завершается, Codex передаёт поддерживаемый информационный вывод в следующей безопасной точке диалога:
- Если ход активен, Codex ожидает завершения текущего запроса модели и вызовов инструментов, а затем делает вывод доступным для следующего запроса модели в этом ходе.
- Если активного хода нет, Codex ожидает следующего хода пользователя. Завершение фонового хука не начинает новый ход.
Используйте тот же JSON-вывод для конкретного события, что и для синхронного хука. Codex добавляет
additionalContext в контекст модели и отображает systemMessage как
предупреждение.
Ограничения
- Codex одновременно запускает не более восьми фоновых хуков на сеанс. Остальные хуки ожидают завершения одного из выполняющихся хуков.
- Каждый подходящий вызов выполняется независимо, и фоновые хуки могут завершаться в порядке, отличном от порядка запуска.
- При завершении сеанса Codex отменяет незавершённые фоновые хуки и отбрасывает ещё не переданный вывод.
- Хуки
SessionEndвсегда выполняются синхронно.
Хуки
SessionStart
Для этого события matcher применяется к source.
Поля в дополнение к общим полям ввода:
| Поле | Тип | Значение |
|---|---|---|
source |
string |
Способ запуска сеанса: startup, resume, clear или compact |
Обычный текст в stdout добавляется как дополнительный контекст разработчика.
JSON в stdout поддерживает общие поля вывода и следующую
структуру, специфичную для этого хука:
{
"hookSpecificOutput": {
"hookEventName": "SessionStart",
"additionalContext": "Load the workspace conventions before editing."
}
}Текст additionalContext добавляется как дополнительный контекст разработчика.
После сжатия корневого сеанса Codex хуки SessionStart, соответствующие
source: "compact", запускаются перед следующим запросом модели. Это также относится к
автоматическому сжатию в середине хода: Codex передаёт дополнительный контекст хука
непосредственному продолжению, а не ждёт следующего
хода пользователя. Если хук возвращает continue: false, Codex завершает ход,
не отправляя ещё один запрос модели.
SessionEnd
SessionEnd позволяет запускать команду при завершении сеанса, например для сохранения итоговых
заметок или очистки файлов. Он запускается для основного потока, когда вы архивируете или
удаляете всё ещё открытый диалог, когда Codex штатно завершает работу либо когда
диалог бездействовал 30 минут и не открыт ни в одном подключённом клиенте.
Для субагентов он не запускается.
Переход к другому диалогу или вызов thread/unsubscribe не завершает
сеанс немедленно, поэтому SessionEnd не запустится сразу. Во время работы хук
по-прежнему может читать расшифровку сеанса.
Для этого события matcher фильтрует reason. Сейчас reason всегда имеет значение other.
Можно опустить matcher или использовать other для запуска при каждом событии SessionEnd.
Поля в дополнение к общим полям ввода:
| Поле | Тип | Значение |
|---|---|---|
reason |
string |
Причина завершения сеанса: other |
Например, команда SessionEnd получает:
{
"session_id": "thr_123",
"transcript_path": "/workspace/.codex/rollout.jsonl",
"cwd": "/workspace",
"hook_event_name": "SessionEnd",
"reason": "other"
}Хуки SessionEnd всегда выполняются синхронно, даже если async имеет значение true. Они
носят рекомендательный характер, поэтому их вывод не влияет на поведение Codex и не оставляет поток открытым. Если
команда превышает тайм-аут или завершается с ошибкой, Codex сообщает о сбое хука.
SubagentStart
Для этого события matcher применяется к agent_type.
Поля в дополнение к общим полям ввода:
| Поле | Тип | Значение |
|---|---|---|
turn_id |
string |
Специальное расширение Codex. ID активного хода Codex |
agent_id |
string |
Идентификатор субагента |
agent_type |
string |
Тип или профиль субагента |
permission_mode |
string |
Текущий режим разрешений |
Обычный текст в stdout добавляется как дополнительный контекст разработчика для субагента.
JSON в stdout поддерживает systemMessage и следующую структуру, специфичную для этого хука:
{
"hookSpecificOutput": {
"hookEventName": "SubagentStart",
"additionalContext": "Review the repository test conventions first."
}
}Текст additionalContext добавляется как дополнительный контекст разработчика для
субагента. continue: false разбирается для совместимости, но не препятствует
запуску субагента.
PreToolUse
PreToolUse может перехватывать Bash, редактирование файлов через apply_patch,
вызовы инструментов MCP и другие локальные функциональные инструменты. Поддерживаемые пути
и исключения приведены в разделе Охват инструментов.
matcher применяется к tool_name и псевдонимам сопоставления. Для редактирования файлов через
apply_patch значения matcher могут использовать apply_patch, Edit или Write; во входных данных хука
по-прежнему указывается tool_name: "apply_patch".
Поля в дополнение к общим полям ввода:
| Поле | Тип | Значение |
|---|---|---|
turn_id |
string |
Специальное расширение Codex. ID активного хода Codex |
tool_name |
string |
Каноническое имя инструмента хука, например Bash, apply_patch или имя MCP вроде mcp__fs__read |
tool_use_id |
string |
ID вызова инструмента для этого обращения |
tool_input |
JSON value |
Входные данные конкретного инструмента. Bash и apply_patch используют tool_input.command. MCP и другие локальные функциональные инструменты передают свои аргументы. |
Обычный текст в stdout игнорируется.
JSON в stdout может использовать systemMessage. Чтобы запретить поддерживаемый вызов инструмента, верните
следующую структуру, специфичную для этого хука:
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": "Destructive command blocked by hook."
}
}Codex также принимает следующую устаревшую структуру блокировки:
{
"decision": "block",
"reason": "Destructive command blocked by hook."
}Можно также использовать код завершения 2 и записать причину блокировки в stderr.
Чтобы добавить видимый модели контекст без блокировки, верните
hookSpecificOutput.additionalContext:
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"additionalContext": "The pending command touches generated files."
}
}Чтобы изменить поддерживаемый вызов инструмента без блокировки, верните
permissionDecision: "allow" с updatedInput:
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "allow",
"updatedInput": {
"command": "echo rewritten"
}
}
}Для команд Bash и apply_patch значение updatedInput должно содержать строковое
поле command. Для MCP и других локальных функциональных инструментов updatedInput представляет собой
объект замещающих аргументов. Возвращайте updatedInput только с
permissionDecision: "allow"; другие структуры updatedInput считаются
ошибочными.
permissionDecision: "ask", устаревшее decision: "approve", continue: false,
stopReason и suppressOutput разбираются, но пока не поддерживаются. Codex помечает
запуск хука как неудачный, сообщает об ошибке и продолжает вызов инструмента.
PermissionRequest
PermissionRequest запускается, когда Codex собирается запросить подтверждение, например для
повышения прав оболочки или доступа к управляемой сети. Он может разрешить запрос, отклонить
его либо не принимать решение и оставить обычный запрос подтверждения. Он не
запускается для команд, которым подтверждение не требуется.
matcher применяется к tool_name и псевдонимам сопоставления. Текущие канонические
значения включают Bash, apply_patch и имена инструментов MCP, например
mcp__server__tool; apply_patch также соответствует Edit и Write.
Поля в дополнение к общим полям ввода:
| Поле | Тип | Значение |
|---|---|---|
turn_id |
string |
Специальное расширение Codex. ID активного хода Codex |
tool_name |
string |
Каноническое имя инструмента хука, например Bash, apply_patch или имя MCP вроде mcp__fs__read |
tool_input |
JSON value |
Входные данные конкретного инструмента. Bash и apply_patch используют tool_input.command, а инструменты MCP передают все аргументы. |
tool_input.description |
string | null |
Понятное пользователю обоснование подтверждения, если оно есть у Codex |
Обычный текст в stdout игнорируется.
Входные данные некоторых инструментов могут содержать понятное пользователю описание, но не следует рассчитывать на
наличие поля tool_input.description у каждого инструмента.
Чтобы одобрить запрос, верните:
{
"hookSpecificOutput": {
"hookEventName": "PermissionRequest",
"decision": {
"behavior": "allow"
}
}
}Чтобы отклонить запрос, верните:
{
"hookSpecificOutput": {
"hookEventName": "PermissionRequest",
"decision": {
"behavior": "deny",
"message": "Blocked by repository policy."
}
}
}Если несколько подходящих хуков возвращают решения, любое решение deny имеет приоритет. В противном случае
allow позволяет продолжить выполнение запроса без показа запроса подтверждения. Если ни один
подходящий хук не принял решение, Codex использует обычную процедуру подтверждения.
Не возвращайте updatedInput, updatedPermissions или interrupt для
PermissionRequest; эти поля зарезервированы для будущего поведения и сейчас приводят
к блокировке при ошибке.
PostToolUse
PostToolUse запускается после того, как поддерживаемые инструменты создают вывод, включая Bash,
apply_patch, вызовы инструментов MCP и другие локальные функциональные инструменты. Для Bash он
также запускается после команд, завершившихся с ненулевым статусом. Он не может отменить побочные
эффекты уже запущенного инструмента. Поддерживаемые пути и исключения приведены
в разделе Охват инструментов.
matcher применяется к tool_name и псевдонимам сопоставления. Для редактирования файлов через
apply_patch значения matcher могут использовать apply_patch, Edit или Write; во входных данных хука
по-прежнему указывается tool_name: "apply_patch".
Поля в дополнение к общим полям ввода:
| Поле | Тип | Значение |
|---|---|---|
turn_id |
string |
Специальное расширение Codex. ID активного хода Codex |
tool_name |
string |
Каноническое имя инструмента хука, например Bash, apply_patch или имя MCP вроде mcp__fs__read |
tool_use_id |
string |
ID вызова инструмента для этого обращения |
tool_input |
JSON value |
Входные данные конкретного инструмента. Bash и apply_patch используют tool_input.command. MCP и другие локальные функциональные инструменты передают свои аргументы. |
tool_response |
JSON value |
Вывод конкретного инструмента. Инструменты MCP передают результат вызова MCP. Другие локальные функциональные инструменты обычно передают вывод, предназначенный для модели. |
Обычный текст в stdout игнорируется.
JSON в stdout может использовать systemMessage и следующую структуру, специфичную для этого хука:
{
"decision": "block",
"reason": "The Bash output needs review before continuing.",
"hookSpecificOutput": {
"hookEventName": "PostToolUse",
"additionalContext": "The command updated generated files."
}
}Текст additionalContext добавляется как дополнительный контекст разработчика.
Для этого события decision: "block" не отменяет выполненную команду Bash.
Вместо этого Codex записывает обратную связь, заменяет ею результат инструмента
и продолжает работу модели с сообщением, предоставленным хуком.
Можно также использовать код завершения 2 и записать причину обратной связи в stderr.
Чтобы прекратить обычную обработку исходного результата инструмента после того, как команда уже
выполнена, верните continue: false. Codex заменит результат инструмента
вашей обратной связью или текстом остановки и продолжит работу с этого места.
updatedMCPToolOutput и suppressOutput разбираются, но пока не поддерживаются.
Codex помечает запуск хука как неудачный, сообщает об ошибке и продолжает обычную
обработку результата инструмента.
Вызовы инструментов из режима кода
Когда модель использует режим кода для вызова инструмента из JavaScript, решения хуков применяются
к этому вложенному вызову. PreToolUse может остановить инструмент до запуска или изменить
его входные данные. Блокирующий PostToolUse не может отменить побочные эффекты инструмента, но может
не допустить передачи исходного результата выполняющемуся скрипту.
| Результат хука | Что получает режим кода |
|---|---|
PreToolUse блокирует |
Промис инструмента отклоняется до запуска инструмента. |
PreToolUse возвращает updatedInput |
Инструмент запускается с изменёнными входными данными, а промис разрешается с полученным результатом. |
PostToolUse возвращает decision: "block" или завершается с кодом 2 |
Инструмент запускается, после чего промис отклоняется с причиной от хука. |
PostToolUse возвращает continue: false |
Codex использует обратную связь хука как видимый модели результат, но не отклоняет промис вложенного инструмента. |
PreCompact
PreCompact запускается перед сжатием чата в Codex. matcher применяется
к trigger, возможные значения которого — manual и auto.
Поля в дополнение к общим полям ввода:
| Поле | Тип | Значение |
|---|---|---|
turn_id |
string |
Специальное расширение Codex. ID активного хода Codex |
trigger |
string |
Что запустило сжатие: manual или auto |
Обычный текст в stdout игнорируется.
JSON в stdout поддерживает общие поля вывода. Если
подходящий хук PreCompact возвращает continue: false, Codex останавливается перед
сжатием.
PostCompact
PostCompact запускается после сжатия чата в Codex. matcher применяется
к trigger, возможные значения которого — manual и auto.
Поля в дополнение к общим полям ввода:
| Поле | Тип | Значение |
|---|---|---|
turn_id |
string |
Специальное расширение Codex. ID активного хода Codex |
trigger |
string |
Что запустило сжатие: manual или auto |
Обычный текст в stdout игнорируется.
JSON в stdout поддерживает общие поля вывода. Если
подходящий хук PostCompact возвращает continue: false, Codex останавливается после
сжатия.
UserPromptSubmit
matcher сейчас не используется для этого события.
Поля в дополнение к общим полям ввода:
| Поле | Тип | Значение |
|---|---|---|
turn_id |
string |
Специальное расширение Codex. ID активного хода Codex |
prompt |
string |
Запрос пользователя, который будет отправлен |
Обычный текст в stdout добавляется как дополнительный контекст разработчика.
JSON в stdout поддерживает общие поля вывода и
следующую структуру, специфичную для этого хука:
{
"hookSpecificOutput": {
"hookEventName": "UserPromptSubmit",
"additionalContext": "Ask for a clearer reproduction before editing files."
}
}Текст additionalContext добавляется как дополнительный контекст разработчика.
Чтобы заблокировать запрос, верните:
{
"decision": "block",
"reason": "Ask for confirmation before doing that."
}Можно также использовать код завершения 2 и записать причину блокировки в stderr.
SubagentStop
Для этого события matcher применяется к agent_type.
Поля в дополнение к общим полям ввода:
| Поле | Тип | Значение |
|---|---|---|
turn_id |
string |
Специальное расширение Codex. ID активного хода Codex |
agent_id |
string |
Идентификатор субагента |
agent_type |
string |
Тип или профиль субагента |
agent_transcript_path |
string | null |
Путь к файлу расшифровки субагента, если он существует |
stop_hook_active |
boolean |
Было ли уже продолжено выполнение этого субагента |
last_assistant_message |
string | null |
Последнее сообщение ассистента субагента, если оно доступно |
При завершении с кодом 0 хук SubagentStop ожидает JSON в stdout. Обычный текстовый вывод
недопустим для этого события.
JSON в stdout поддерживает общие поля вывода. Чтобы попросить
Codex продолжить выполнение субагента, верните:
{
"decision": "block",
"reason": "Run one more focused pass inside the subagent."
}Можно также использовать код завершения 2 и записать причину продолжения в stderr.
Если какой-либо подходящий хук SubagentStop возвращает continue: false, это решение имеет
приоритет над решениями о продолжении от других подходящих хуков SubagentStop.
Stop
matcher сейчас не используется для этого события.
Поля в дополнение к общим полям ввода:
| Поле | Тип | Значение |
|---|---|---|
turn_id |
string |
Специальное расширение Codex. ID активного хода Codex |
stop_hook_active |
boolean |
Был ли этот ход уже продолжен с помощью Stop |
last_assistant_message |
string | null |
Текст последнего сообщения ассистента, если он доступен |
При завершении с кодом 0 хук Stop ожидает JSON в stdout. Обычный текстовый вывод недопустим
для этого события.
JSON в stdout поддерживает общие поля вывода. Чтобы Codex
продолжил работу, верните:
{
"decision": "block",
"reason": "Run one more pass over the failing tests."
}Можно также использовать код завершения 2 и записать причину продолжения в stderr.
Для этого события decision: "block" не отклоняет ход. Вместо этого он указывает
Codex продолжить работу и автоматически создаёт новый запрос продолжения, который действует
как новый запрос пользователя и использует reason в качестве текста запроса.
Если какой-либо подходящий хук Stop возвращает continue: false, это решение имеет приоритет
над решениями о продолжении от других подходящих хуков Stop.
Interrupt
Interrupt выполняется, когда вы прерываете активный ход в основном потоке. Используйте его,
чтобы зафиксировать прерывание или очистить результаты работы, запущенной хуком. Он не выполняется
для неактивных потоков или субагентов, а любой настроенный matcher игнорируется.
Помимо общих полей входных данных, событие включает
turn_id — идентификатор прерванного хода — и permission_mode.
Для командных хуков по умолчанию установлен тайм-аут в одну секунду. Настроенные тайм-ауты
ограничены диапазоном от одной до трёх секунд. Вывод хука не может предотвратить
прерывание или перезапустить ход. Завершите работу с кодом 0 без вывода либо верните JSON с
необязательным полем systemMessage, чтобы отобразить предупреждение. Обычный текстовый вывод недопустим
для этого события.
{ "systemMessage": "Saved the interrupted turn to the local audit log." }Схемы
Если вам нужен точный текущий формат обмена данными, см. сгенерированные схемы в репозитории Codex на GitHub.
Псевдонимы для обычного текста
- string | null