한국어

Hooks

Codex 수명 주기 동안 결정론적 스크립트 실행

Hooks는 Codex를 위한 확장성 프레임워크입니다. 이를 사용하면 에이전트 루프에 자체 스크립트를 삽입하여 다음과 같은 기능을 구현할 수 있습니다.

  • 채팅을 사용자 지정 로깅/분석 엔진으로 전송
  • 팀의 프롬프트를 검사하여 API key를 실수로 붙여 넣는 것을 차단
  • 채팅을 요약하여 영구 메모리를 자동으로 생성
  • 채팅 턴이 중지될 때 사용자 지정 검증 검사를 실행하여 표준 준수 적용
  • 특정 디렉터리에 있을 때 프롬프트 사용자 지정

유의해야 할 런타임 동작은 다음과 같습니다.

  • 여러 파일에서 일치하는 Hooks가 모두 실행됩니다.
  • 동일한 이벤트에 대해 일치하는 여러 명령 Hooks는 동시에 시작되므로, 한 Hook이 일치하는 다른 Hook의 시작을 막을 수 없습니다.
  • 관리되지 않는 명령 Hooks는 실행 전에 검토하고 신뢰해야 합니다.

Hooks는 대화의 여러 시점에 실행됩니다.

시점 Hooks
턴 진행 중 PreToolUse, PermissionRequest, PostToolUse, PreCompact, PostCompact, UserPromptSubmit, SubagentStop, Stop
세션 또는 하위 에이전트 시작 시 SessionStart, SubagentStart
메인 스레드 종료 시 SessionEnd (하위 에이전트에는 실행되지 않음)

Codex가 Hooks를 찾는 위치

Codex는 활성 구성 계층 옆에서 다음 형식 중 하나로 Hooks를 검색합니다.

  • hooks.json
  • config.toml 내부의 인라인 [hooks] 테이블

설치된 플러그인도 플러그인 매니페스트 또는 기본 hooks/hooks.json 파일을 통해 수명 주기 구성을 묶어서 제공할 수 있습니다. 플러그인 패키징 규칙은 플러그인 빌드를 참조하세요.

실제로 가장 유용한 네 위치는 다음과 같습니다.

  • ~/.codex/hooks.json
  • ~/.codex/config.toml
  • <repo>/.codex/hooks.json
  • <repo>/.codex/config.toml

Hook 소스가 둘 이상 있으면 Codex는 일치하는 모든 Hooks를 로드합니다. 우선순위가 높은 구성 계층이 우선순위가 낮은 계층의 Hooks를 대체하지 않습니다. 단일 계층에 hooks.json와 인라인 [hooks]가 모두 있으면 Codex는 이를 병합하고 시작할 때 경고합니다. 계층마다 한 가지 표현 방식만 사용하는 것이 좋습니다.

Codex는 활성화된 플러그인에 포함된 Hooks도 검색할 수 있습니다. 플러그인에 포함된 Hooks는 다른 Hook 소스와 함께 로드되며, 관리되지 않는 다른 Hooks와 동일한 신뢰 검토 절차를 사용합니다.

프로젝트 로컬 Hooks는 프로젝트 .codex/ 계층이 신뢰된 경우에만 로드됩니다. 신뢰되지 않은 프로젝트에서도 Codex는 사용자 및 시스템 Hooks를 각각의 활성 구성 계층에서 계속 로드합니다.

Hooks 검토 및 신뢰

Codex는 실행할 수 있는 Hooks를 결정하기 전에 구성된 Hooks를 나열합니다. 관리되지 않는 명령 Hook을 실행하려면 정확한 Hook 정의를 검토하고 신뢰해야 합니다. Codex는 Hook의 현재 해시를 기준으로 신뢰를 기록하므로, 새로 추가되거나 변경된 Hooks는 검토 대상으로 표시되고 신뢰하기 전까지 건너뜁니다.

CLI에서 /hooks를 사용하여 Hook 소스를 검사하고, 새로 추가되거나 변경된 Hooks를 검토하고, Hooks를 신뢰하거나, 관리되지 않는 개별 Hooks를 비활성화할 수 있습니다. 시작 시 Hooks를 검토해야 하면 Codex는 /hooks를 열라는 경고를 표시합니다.

시스템, MDM, 클라우드 또는 requirements.toml 소스의 관리형 Hooks는 관리형으로 표시되고 정책에 따라 신뢰되며, 사용자 Hook 브라우저에서 비활성화할 수 없습니다.

Codex 외부에서 이미 Hook 소스를 검증하는 일회성 자동화의 경우 --dangerously-bypass-hook-trust를 전달하면 해당 호출에 대해 저장된 Hook 신뢰 없이도 활성화된 Hooks를 실행할 수 있습니다.

구성 구조

Hooks는 세 가지 수준으로 구성됩니다.

  • PreToolUse, PostToolUse, PreCompact, SubagentStart 또는 Stop 같은 Hook 이벤트
  • 해당 이벤트가 일치하는 시점을 결정하는 매처 그룹
  • 매처 그룹이 일치할 때 실행되는 하나 이상의 Hook 핸들러
{
  "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
          }
        ]
      }
    ]
  }
}

참고:

  • descriptionhooks.json 파일의 선택적 최상위 메타데이터입니다. 이는 실행되는 Hooks를 변경하지 않습니다.
  • timeout의 단위는 초입니다.
  • timeout를 생략하면 Codex는 대부분의 Hooks에 600초를 사용합니다.
    • SessionEnd는 기본적으로 1초를 사용하며 최대 3초를 지원합니다.
  • statusMessage는 선택 사항입니다.
  • additionalContextLimit는 명령 Hook이 모델로 보낼 수 있는 additionalContext의 양을 설정합니다. 이 한도를 넘으면 Codex는 전체 텍스트를 디스크에 저장하고 대신 더 짧은 미리 보기를 전송합니다. 대용량 Hook 출력을 참조하세요.
  • commandWindows는 Windows 전용 선택적 명령 재정의입니다. TOML에서는 command_windows 또는 commandWindows를 사용하세요.
  • async 옵션은 파싱되지만 비동기 명령 Hooks는 아직 지원되지 않습니다.
  • 현재는 type: "command" 핸들러만 실행됩니다. promptagent 핸들러는 파싱되지만 건너뜁니다.
  • 명령은 세션 cwd를 작업 디렉터리로 사용하여 실행됩니다.
  • 저장소 로컬 Hooks에서는 .codex/hooks/... 같은 상대 경로를 사용하는 대신 git 루트에서 경로를 해석하는 것이 좋습니다. Codex는 하위 디렉터리에서 시작될 수 있으며, git 루트 기반 경로를 사용하면 Hook 위치가 일정하게 유지됩니다.

config.toml의 동등한 인라인 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"

Hooks 끄기

Hooks는 기본적으로 활성화됩니다. config.toml에서 Hooks를 끄려면 다음과 같이 설정하세요.

[features]
hooks = false

표준 기능 키로 hooks를 사용하세요. codex_hooks도 더 이상 사용되지 않는 별칭으로 계속 작동합니다. 관리자는 requirements.toml에서 [features].hooks = false를 사용해 동일한 방식으로 Hooks를 강제로 끌 수 있습니다.

requirements.toml의 관리형 Hooks

엔터프라이즈 관리 요구 사항에서도 [hooks] 아래에 Hooks를 인라인으로 정의할 수 있습니다. 이는 관리자가 Hook 구성을 강제 적용하면서 실제 스크립트는 MDM이나 다른 기기 관리 시스템을 통해 배포하려는 경우 유용합니다. 로컬에서 Hooks를 비활성화한 사용자에게도 관리형 Hooks를 적용하려면 [hooks]와 함께 requirements.toml[features].hooks = true를 고정하세요. 관리자 관리형 Hooks는 계속 허용하면서 사용자, 프로젝트, 세션 및 플러그인 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"

관리형 Hooks에 관한 참고 사항:

  • managed_dir는 macOS 및 Linux에서 사용됩니다.
  • windows_managed_dir는 Windows에서 사용됩니다.
  • Codex는 managed_dir의 스크립트를 배포하지 않습니다. 엔터프라이즈 도구에서 해당 스크립트를 별도로 설치하고 업데이트해야 합니다.
  • 관리형 Hook 명령은 구성된 관리 디렉터리 아래의 절대 스크립트 경로를 사용해야 합니다.
  • allow_managed_hooks_only = true는 사용자, 프로젝트, 세션 및 플러그인 소스의 Hooks를 건너뛰지만, requirements.toml 및 다른 관리형 구성 계층의 관리형 Hooks는 계속 로드합니다.

플러그인에 포함된 Hooks

플러그인이 활성화되면 Codex는 해당 플러그인의 수명 주기 Hooks를 사용자, 프로젝트 및 관리형 Hooks와 함께 로드할 수 있습니다.

Codex는 기본적으로 플러그인 루트 내부에서 hooks/hooks.json을 찾습니다. 플러그인 매니페스트는 .codex-plugin/plugin.jsonhooks 항목으로 이 기본값을 재정의할 수 있습니다. 매니페스트 항목은 ./ 접두사가 붙은 경로, ./ 접두사가 붙은 경로의 배열, 인라인 Hooks 객체 또는 인라인 Hooks 객체의 배열일 수 있습니다.

{
  "name": "repo-policy",
  "hooks": "./hooks/hooks.json"
}

매니페스트 Hook 경로는 플러그인 루트를 기준으로 해석되며 해당 루트 내부에 있어야 합니다. 매니페스트가 hooks를 정의하면 Codex는 기본 hooks/hooks.json 대신 해당 매니페스트 항목을 사용합니다.

플러그인 Hook 명령에는 다음 환경 변수가 전달됩니다.

  • PLUGIN_ROOT는 설치된 플러그인 루트를 가리키는 Codex 전용 확장입니다.
  • PLUGIN_DATA는 플러그인의 쓰기 가능한 데이터 디렉터리를 가리키는 Codex 전용 확장입니다.
  • Codex는 기존 플러그인 Hooks와의 호환성을 위해 CLAUDE_PLUGIN_ROOTCLAUDE_PLUGIN_DATA도 설정합니다.

플러그인 Hooks는 다른 Hooks와 동일한 이벤트 스키마를 사용합니다. 플러그인을 설치하거나 활성화해도 해당 Hooks가 자동으로 신뢰되지는 않습니다. Codex는 현재 Hook 정의를 검토하고 신뢰하기 전까지 플러그인에 포함된 Hooks를 건너뜁니다.

매처 패턴

matcher 필드는 Hooks가 실행되는 시점을 필터링하는 정규식 문자열입니다. 지원되는 이벤트가 발생할 때마다 일치시키려면 "*", ""을 사용하거나 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은 이 이벤트에서 무시됩니다

*apply_patch의 경우 matcher 값에 Edit 또는 Write도 사용할 수 있습니다.

예시:

  • Bash
  • ^apply_patch$
  • Edit|Write
  • mcp__filesystem__read_file
  • mcp__filesystem__.*
  • startup|resume|clear|compact
  • manual|auto

도구 적용 범위

PreToolUsePostToolUse은 셸과 MCP 호출 외의 항목도 관찰할 수 있습니다. 대부분의 로컬 함수 도구가 동일한 훅 경로를 사용하므로 도구 이름을 일치시키고, JSON 인수를 검사하며, PreToolUse의 경우 호출을 차단하거나 다시 작성할 수 있습니다.

도구 경로 PreToolUse PostToolUse 참고
셸 명령 Bash으로 일치시킵니다.
통합 실행(exec_command) Bash으로 일치시킵니다. 이후 write_stdin 폴링은 원래 명령이 완료될 때 해당 명령의 PostToolUse을 전달할 수 있습니다.
apply_patch apply_patch, Edit 또는 Write으로 일치시킵니다.
MCP 도구 mcp__filesystem__read_file 같은 MCP 도구 이름을 일치시킵니다.
기타 로컬 함수 도구 update_plan 같은 함수 도구 이름을 일치시킵니다. spawn_agentAgent과도 일치합니다.
WebSearch 같은 호스팅 도구 아니요 아니요 이러한 도구는 로컬 함수 도구 훅 경로를 사용하지 않습니다.

write_stdin은 기존 통합 실행 세션을 위한 전송 수단입니다. 입력을 보내거나 이미 PreToolUse을 통과한 명령을 폴링할 때 PreToolUse을 다시 실행하지 않습니다.

일부 특수 도구 경로는 기본 훅 경로를 사용하지 않도록 선택할 수 있습니다. 도구 훅은 완전한 강제 적용 경계가 아니라 유용한 가드레일로 간주하세요.

공통 입력 필드

모든 명령 훅은 stdin에서 하나의 JSON 객체를 받습니다.

일반적으로 사용하는 공통 필드는 다음과 같습니다.

필드 유형 의미
session_id string 현재 Codex 세션 ID입니다. 하위 에이전트 훅은 상위 세션 ID를 사용합니다.
transcript_path string | null 세션 대화 기록 파일이 있는 경우 해당 파일의 경로
cwd string 세션의 작업 디렉터리
hook_event_name string 현재 훅 이벤트 이름
model string Codex 전용 확장 기능입니다. 활성 모델 슬러그

턴 범위 훅의 이벤트별 표에는 turn_id이 Codex 전용 확장 기능으로 나열됩니다.

SessionStart, PreToolUse, PermissionRequest, PostToolUse, UserPromptSubmit, SubagentStart, SubagentStopStop에는 현재 권한 모드를 default, acceptEdits, plan, dontAsk 또는 bypassPermissions으로 설명하는 permission_mode도 포함됩니다.

transcript_path은 편의를 위해 채팅 대화 기록을 가리키지만, 대화 기록 형식은 훅을 위한 안정적인 인터페이스가 아니며 시간이 지나면서 변경될 수 있습니다.

전체 와이어 형식이 필요한 경우 스키마를 참조하세요.

공통 출력 필드

SessionStart, PreCompact, PostCompact, UserPromptSubmit, SubagentStopStop은 다음과 같은 공통 JSON 필드를 지원합니다. SubagentStartsystemMessage과 훅별 컨텍스트에 동일한 형식을 허용하지만, continue: false은 하위 에이전트를 중지하지 않습니다.

{
  "continue": true,
  "stopReason": "optional",
  "systemMessage": "optional",
  "suppressOutput": false
}
필드 효과
continue false이면 해당 훅 실행을 중지된 것으로 표시합니다
stopReason 중지 사유로 기록됩니다
systemMessage UI 또는 이벤트 스트림에 경고로 표시됩니다
suppressOutput 현재는 파싱되지만 아직 구현되지 않았습니다

출력 없이 0으로 종료하면 성공으로 처리되며 Codex가 계속 진행합니다.

PreToolUsePermissionRequestsystemMessage을 지원하지만, 현재 해당 이벤트에서는 continue, stopReasonsuppressOutput이 지원되지 않습니다. PreToolUse 훅이 지원되지 않는 필드 중 하나를 반환하면 Codex는 해당 훅 실행을 실패로 표시하고 오류를 보고한 후 도구 호출을 계속합니다.

PostToolUsesystemMessage, continue: falsestopReason을 지원합니다. 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
}

기본 2500토큰 임계값을 사용하려면 additionalContextLimit을 생략하세요. 다른 임계값을 선택하려면 양의 정수를 사용하고, 핸들러의 전체 추가 컨텍스트를 모델에 직접 전달하려면 0을 사용합니다. Codex는 일치하는 각 핸들러를 독립적으로 평가합니다. 추가 컨텍스트를 생성할 수 없는 이벤트의 경우 Codex는 additionalContextLimit을 무시하고 구성 경고를 보고합니다.

이 설정은 additionalContext에만 적용됩니다. 도구 피드백과 후속 실행 프롬프트에는 기본 한도가 유지됩니다.

지나치게 큰 출력은 디스크에 기록될 수 있으므로 훅 출력에 비밀 정보나 기타 민감한 데이터를 반환하지 마세요.

SessionStart

이 이벤트에서는 matchersource에 적용됩니다.

공통 입력 필드 외에 추가되는 필드는 다음과 같습니다.

필드 유형 의미
source string 세션 시작 방식: startup, resume, clear 또는 compact

stdout의 일반 텍스트는 추가 개발자 컨텍스트로 추가됩니다.

stdout의 JSON은 공통 출력 필드와 다음 훅별 형식을 지원합니다.

{
  "hookSpecificOutput": {
    "hookEventName": "SessionStart",
    "additionalContext": "Load the workspace conventions before editing."
  }
}

해당 additionalContext 텍스트는 추가 개발자 컨텍스트로 추가됩니다.

Codex가 루트 세션을 압축한 후에는 source: "compact"과 일치하는 SessionStart 훅이 다음 모델 요청 전에 실행됩니다. 이는 턴 도중 자동 압축이 발생하는 경우에도 적용됩니다. Codex는 이후 사용자 턴을 기다리지 않고 훅의 추가 컨텍스트를 즉시 이어지는 처리에 전달합니다. 훅이 continue: false을 반환하면 Codex는 다른 모델 요청을 보내지 않고 턴을 종료합니다.

SessionEnd

SessionEnd을 사용하면 세션이 종료될 때 최종 메모를 저장하거나 파일을 정리하는 등의 명령을 실행할 수 있습니다. 아직 열려 있는 대화를 보관하거나 삭제할 때, Codex가 정상적으로 종료될 때 또는 대화가 30분 동안 유휴 상태이고 연결된 어떤 클라이언트에서도 열려 있지 않을 때 기본 스레드에서 실행됩니다. 하위 에이전트에서는 실행되지 않습니다.

대화에서 다른 곳으로 이동하거나 thread/unsubscribe을 호출해도 세션이 즉시 종료되지는 않으므로 SessionEnd이 바로 실행되지 않습니다. 훅이 실행되는 동안에도 세션 대화 기록을 읽을 수 있습니다.

이 이벤트에서는 matcherreason을 필터링합니다. 현재 reason은 항상 other입니다. 모든 SessionEnd 이벤트에서 실행하려면 matcher을 생략하거나 other을 사용할 수 있습니다.

공통 입력 필드 외에 추가되는 필드는 다음과 같습니다.

필드 유형 의미
reason string 세션 종료 사유: other

예를 들어 SessionEnd 명령은 다음을 받습니다.

{
  "session_id": "thr_123",
  "transcript_path": "/workspace/.codex/rollout.jsonl",
  "cwd": "/workspace",
  "hook_event_name": "SessionEnd",
  "reason": "other"
}

SessionEnd 훅은 권고용입니다. 출력으로 Codex의 동작을 제어하거나 스레드를 열린 상태로 유지할 수 없습니다. 명령 시간이 초과되거나 오류와 함께 종료되면 Codex는 이를 훅 실패로 보고합니다.

SubagentStart

이 이벤트에서는 matcheragent_type에 적용됩니다.

공통 입력 필드 외에 추가되는 필드는 다음과 같습니다.

필드 유형 의미
turn_id string Codex 전용 확장 기능입니다. 활성 Codex 턴 ID
agent_id string 하위 에이전트 식별자
agent_type string 하위 에이전트 유형 또는 프로필
permission_mode string 현재 권한 모드

stdout의 일반 텍스트는 하위 에이전트를 위한 추가 개발자 컨텍스트로 추가됩니다.

stdout의 JSON은 systemMessage과 다음 훅별 형식을 지원합니다.

{
  "hookSpecificOutput": {
    "hookEventName": "SubagentStart",
    "additionalContext": "Review the repository test conventions first."
  }
}

해당 additionalContext 텍스트는 하위 에이전트를 위한 추가 개발자 컨텍스트로 추가됩니다. continue: false은 호환성을 위해 파싱되지만, 하위 에이전트가 시작되는 것을 막지는 않습니다.

PreToolUse

PreToolUse은 Bash, apply_patch을 통해 수행되는 파일 편집, MCP 도구 호출 및 기타 로컬 함수 도구를 가로챌 수 있습니다. 지원되는 경로와 예외는 도구 적용 범위를 참조하세요.

matchertool_name 및 매처 별칭에 적용됩니다. apply_patch을 통한 파일 편집의 경우 matcher 값으로 apply_patch, Edit 또는 Write을 사용할 수 있지만, 훅 입력에는 여전히 tool_name: "apply_patch"이 보고됩니다.

공통 입력 필드에 추가되는 필드:

필드 유형 의미
turn_id string Codex 전용 확장입니다. 활성 Codex 턴 ID
tool_name string Bash, apply_patch 또는 mcp__fs__read 같은 MCP 이름 등의 정규 훅 도구 이름
tool_use_id string 이 호출의 도구 호출 ID
tool_input JSON value 도구별 입력입니다. Bashapply_patchtool_input.command을 사용합니다. MCP 및 기타 로컬 함수 도구는 인수를 전송합니다.

stdout의 일반 텍스트는 무시됩니다.

stdout의 JSON은 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."
  }
}

차단하지 않고 지원되는 도구 호출을 다시 작성하려면 updatedInput과 함께 permissionDecision: "allow"을 반환하세요.

{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "allow",
    "updatedInput": {
      "command": "echo rewritten"
    }
  }
}

Bash 명령 및 apply_patch의 경우 updatedInput에는 문자열 command 필드가 포함되어야 합니다. MCP 및 기타 로컬 함수 도구에서 updatedInput는 대체 인수 객체입니다. permissionDecision: "allow"과 함께 사용할 때만 updatedInput를 반환하세요. 그 밖의 updatedInput 형식은 오류로 보고됩니다.

permissionDecision: "ask", 레거시 decision: "approve", continue: false, stopReasonsuppressOutput은 파싱되지만 아직 지원되지 않습니다. Codex는 훅 실행을 실패로 표시하고 오류를 보고한 후 도구 호출을 계속합니다.

PermissionRequest

PermissionRequest은 셸 권한 상승이나 관리형 네트워크 승인처럼 Codex가 승인을 요청하려 할 때 실행됩니다. 요청을 허용하거나 거부할 수 있으며, 결정을 보류하여 일반 승인 프롬프트가 계속되도록 할 수도 있습니다. 승인이 필요하지 않은 명령에는 실행되지 않습니다.

matchertool_name 및 매처 별칭에 적용됩니다. 현재 정규 값에는 Bash, apply_patchmcp__server__tool 같은 MCP 도구 이름이 포함되며, apply_patchEditWrite과도 일치합니다.

공통 입력 필드에 추가되는 필드:

필드 유형 의미
turn_id string Codex 전용 확장입니다. 활성 Codex 턴 ID
tool_name string Bash, apply_patch 또는 mcp__fs__read 같은 MCP 이름 등의 정규 훅 도구 이름
tool_input JSON value 도구별 입력입니다. Bashapply_patchtool_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는 일반 승인 흐름을 사용합니다.

PermissionRequest에 대해 updatedInput, updatedPermissions 또는 interrupt을 반환하지 마세요. 해당 필드는 향후 동작을 위해 예약되어 있으며 현재는 안전하게 실패하도록 처리됩니다.

PostToolUse

PostToolUse은 Bash, apply_patch, MCP 도구 호출 및 기타 로컬 함수 도구를 포함해 지원되는 도구가 출력을 생성한 후 실행됩니다. Bash의 경우 0이 아닌 상태로 종료된 명령 뒤에도 실행됩니다. 이미 실행된 도구의 부작용을 되돌릴 수는 없습니다. 지원되는 경로와 예외는 도구 적용 범위를 참조하세요.

matchertool_name 및 매처 별칭에 적용됩니다. apply_patch을 통한 파일 편집의 경우 matcher 값으로 apply_patch, Edit 또는 Write을 사용할 수 있지만, 훅 입력에는 여전히 tool_name: "apply_patch"이 보고됩니다.

공통 입력 필드에 추가되는 필드:

필드 유형 의미
turn_id string Codex 전용 확장입니다. 활성 Codex 턴 ID
tool_name string Bash, apply_patch 또는 mcp__fs__read 같은 MCP 이름 등의 정규 훅 도구 이름
tool_use_id string 이 호출의 도구 호출 ID
tool_input JSON value 도구별 입력입니다. Bashapply_patchtool_input.command을 사용합니다. MCP 및 기타 로컬 함수 도구는 인수를 전송합니다.
tool_response JSON value 도구별 출력입니다. MCP 도구는 MCP 호출 결과를 전송합니다. 기타 로컬 함수 도구는 일반적으로 모델에 표시되는 출력을 전송합니다.

stdout의 일반 텍스트는 무시됩니다.

stdout의 JSON은 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는 도구 결과를 피드백 또는 중단 텍스트로 대체하고 그 지점부터 계속합니다.

updatedMCPToolOutputsuppressOutput은 파싱되지만 아직 지원되지 않습니다. Codex는 훅 실행을 실패로 표시하고 오류를 보고한 후 도구 결과의 정상 처리를 계속합니다.

코드 모드의 도구 호출

모델이 코드 모드를 사용하여 JavaScript에서 도구를 호출하면 훅 결정이 해당 중첩 호출에 적용됩니다. PreToolUse은 도구가 실행되기 전에 중단하거나 입력을 다시 작성할 수 있습니다. 차단하는 PostToolUse은 도구의 부작용을 되돌릴 수 없지만, 원래 결과가 실행 중인 스크립트에 전달되지 않도록 할 수 있습니다.

훅 결과 코드 모드에 표시되는 내용
PreToolUse이 차단함 도구가 실행되기 전에 도구 프로미스가 거부됩니다.
PreToolUseupdatedInput을 반환함 다시 작성된 입력으로 도구가 실행되고 프로미스가 해당 결과로 이행됩니다.
PostToolUsedecision: "block"을 반환하거나 코드 2로 종료함 도구가 실행된 후 훅 사유와 함께 프로미스가 거부됩니다.
PostToolUsecontinue: false을 반환함 Codex는 모델에 표시되는 결과로 훅 피드백을 사용하지만, 중첩된 도구 프로미스를 거부하지는 않습니다.

PreCompact

PreCompact은 Codex가 채팅을 압축하기 전에 실행됩니다. matchertrigger에 적용되며, 해당 값은 manualauto입니다.

공통 입력 필드에 추가되는 필드:

필드 유형 의미
turn_id string Codex 전용 확장입니다. 활성 Codex 턴 ID
trigger string 압축을 트리거한 항목: manual 또는 auto

stdout의 일반 텍스트는 무시됩니다.

stdout의 JSON은 공통 출력 필드를 지원합니다. 일치하는 PreCompact 훅이 continue: false을 반환하면 Codex는 압축 전에 중단합니다.

PostCompact

PostCompact는 Codex가 채팅을 압축한 후 실행됩니다. matchertrigger에 적용되며, 해당 값은 manualauto입니다.

공통 입력 필드에 추가되는 필드:

필드 유형 의미
turn_id string Codex 전용 확장입니다. 활성 Codex 턴 ID
trigger string 압축을 트리거한 항목: manual 또는 auto

stdout의 일반 텍스트는 무시됩니다.

stdout의 JSON은 공통 출력 필드를 지원합니다. 일치하는 PostCompact 훅이 continue: false을 반환하면 Codex는 압축 후 중단합니다.

UserPromptSubmit

matcher은 현재 이 이벤트에 사용되지 않습니다.

공통 입력 필드에 추가되는 필드:

필드 유형 의미
turn_id string Codex 전용 확장입니다. 활성 Codex 턴 ID
prompt string 곧 전송될 사용자 프롬프트

stdout의 일반 텍스트는 추가 개발자 컨텍스트로 추가됩니다.

stdout의 JSON은 공통 출력 필드와 이 훅에만 적용되는 다음 형식을 지원합니다.

{
  "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

이 이벤트에는 matcheragent_type에 적용됩니다.

공통 입력 필드 외의 필드:

필드 유형 의미
turn_id string Codex 전용 확장. 활성 Codex 턴 ID
agent_id string 하위 에이전트의 식별자
agent_type string 하위 에이전트 유형 또는 프로필
agent_transcript_path string | null 하위 에이전트 트랜스크립트 파일의 경로(있는 경우)
stop_hook_active boolean 이 하위 에이전트가 이미 계속 진행되었는지 여부
last_assistant_message string | null 사용 가능한 경우 하위 에이전트의 최신 어시스턴트 메시지

SubagentStop은 종료 코드가 0일 때 stdout에서 JSON을 받습니다. 일반 텍스트 출력은 이 이벤트에서 유효하지 않습니다.

stdout의 JSON은 공통 출력 필드를 지원합니다. Codex에 하위 에이전트 흐름을 계속하도록 요청하려면 다음을 반환합니다.

{
  "decision": "block",
  "reason": "Run one more focused pass inside the subagent."
}

종료 코드 2을 사용하고 계속 진행하는 이유를 stderr에 작성할 수도 있습니다.

일치하는 SubagentStop 훅 중 하나라도 continue: false을 반환하면 다른 일치하는 SubagentStop 훅의 계속 진행 결정보다 우선합니다.

Stop

현재 이 이벤트에는 matcher이 사용되지 않습니다.

공통 입력 필드 외의 필드:

필드 유형 의미
turn_id string Codex 전용 확장. 활성 Codex 턴 ID
stop_hook_active boolean 이 턴이 Stop에 의해 이미 계속 진행되었는지 여부
last_assistant_message string | null 사용 가능한 경우 최신 어시스턴트 메시지 텍스트

Stop은 종료 코드가 0일 때 stdout에서 JSON을 받습니다. 일반 텍스트 출력은 이 이벤트에서 유효하지 않습니다.

stdout의 JSON은 공통 출력 필드를 지원합니다. Codex가 계속 진행하도록 하려면 다음을 반환합니다.

{
  "decision": "block",
  "reason": "Run one more pass over the failing tests."
}

종료 코드 2을 사용하고 계속 진행하는 이유를 stderr에 작성할 수도 있습니다.

이 이벤트에서 decision: "block"은 턴을 거부하지 않습니다. 대신 Codex에 계속 진행하도록 지시하고, reason을 프롬프트 텍스트로 사용하여 새 사용자 프롬프트 역할을 하는 새로운 계속 진행 프롬프트를 자동으로 생성합니다.

일치하는 Stop 훅 중 하나라도 continue: false을 반환하면 다른 일치하는 Stop 훅의 계속 진행 결정보다 우선합니다.

스키마

현재의 정확한 와이어 형식이 필요하다면 Codex GitHub 저장소에서 생성된 스키마를 확인하세요.

일반 텍스트 별칭

  • 문자열 | null