Русский

Хуки

Хуки

Запускайте детерминированные скрипты в течение жизненного цикла 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|Write
  • mcp__filesystem__read_file
  • mcp__filesystem__.*
  • startup|resume|clear|compact
  • manual|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