For the complete documentation index, see llms.txt. Markdown versions of documentation pages are available by appending .md to the page URL.
기본 탐색 메뉴
Theme

훅

Codex 수명 주기의 여러 시점에 스크립트나 MCP 도구 실행하기

훅은 Codex의 기능을 확장하는 프레임워크입니다. 에이전트가 작업을 수행하는 루프 안에서 스크립트나 MCP 도구를 실행해 다음과 같은 작업을 할 수 있습니다.

  • 채팅 내용을 자체 로깅·분석 엔진으로 전송
  • 팀의 프롬프트를 검사해 실수로 붙여 넣은 API 키가 전송되지 않도록 차단
  • 채팅을 요약해 지속적으로 보관할 메모리를 자동 생성
  • 채팅 턴이 멈출 때 사용자 정의 검사를 실행해 정해진 기준을 적용
  • 특정 디렉터리에서 사용할 프롬프트 맞춤 설정

훅은 다음과 같이 실행됩니다.

  • 여러 파일에 일치하는 훅이 있으면 모두 실행합니다.
  • 같은 이벤트에 일치하는 명령어 훅이 여러 개면 동시에 시작합니다. 따라서 한 훅이 다른 훅의 시작을 막을 수 없습니다.
  • 비관리형 훅은 검토하고 신뢰하도록 설정해야 실행됩니다.

대화 중 훅이 실행되는 시점은 다음과 같습니다.

시점 훅
턴 진행 중 PreToolUse, PermissionRequest, PostToolUse, PreCompact, PostCompact, UserPromptSubmit, SubagentStop, Stop
모델 요청을 시도할 때마다 PreModelRequest, PostModelRequest
진행 중인 턴을 중단할 때 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는 훅의 현재 해시를 기준으로 신뢰 여부를 기록합니다. 따라서 새로 추가되거나 변경된 훅은 검토 대상으로 표시되며 신뢰하도록 설정할 때까지 실행에서 제외됩니다.

CLI에서 /hooks를 열면 훅 소스를 확인하고, 새로 추가되거나 변경된 훅을 검토하고, 훅을 신뢰하도록 설정하거나 개별 비관리형 훅을 비활성화할 수 있습니다. 시작 시 검토가 필요한 훅이 있으면 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을 생략하면 대부분의 훅에서 기본값으로 600초를 사용합니다.
    • SessionEnd와 Interrupt는 기본값이 1초이며 최대 3초까지 지원합니다.
  • statusMessage는 선택 사항입니다.
  • additionalContextLimit는 명령어 훅이 모델에 직접 보낼 수 있는 additionalContext의 양을 정합니다. 이 한도를 넘으면 Codex는 전체 텍스트를 디스크에 저장하고 짧은 미리보기를 보냅니다. 대용량 훅 출력을 참고하세요.
  • commandWindows는 Windows에서 실행할 명령어를 별도로 지정하는 선택적 필드입니다. TOML에서는 command_windows 또는 commandWindows를 사용하세요.
  • async를 true로 설정하면 명령어 훅을 백그라운드에서 실행할 수 있습니다.
  • command와 mcp_tool 핸들러를 지원합니다. prompt와 agent 핸들러는 파싱하지만 실행하지 않습니다.
  • 명령어는 세션의 cwd를 작업 디렉터리로 사용합니다.
  • 리포지터리 로컬 훅에서는 .codex/hooks/... 같은 상대 경로 대신 Git 루트를 기준으로 경로를 구하는 것이 좋습니다. 하위 디렉터리에서 Codex를 시작하더라도 Git 루트를 기준으로 하면 같은 위치에서 훅을 찾을 수 있습니다.

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"

MCP 도구 훅

MCP 도구 훅을 사용하면 수명 주기 이벤트가 발생할 때 이미 연결된 MCP 서버의 도구를 호출할 수 있습니다. 훅은 구조화된 인수를 도구에 직접 전달하며, 명령어 훅과 동일한 신뢰 검토 절차와 출력 규약을 따릅니다.

MCP 도구 훅 설정

다음 훅은 Codex가 파일을 작성하거나 편집한 후 scanner MCP 서버에 각 패치를 검사하도록 요청합니다.

{
  "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도 별칭으로 계속 작동하지만 사용 중단 예정(deprecated)입니다. 관리자는 같은 방식으로 requirements.toml에 [features].hooks = false를 설정해 훅을 강제로 비활성화할 수 있습니다.

requirements.toml의 관리형 훅

작업을 조율하는 환경에 맞게 훅을 선택하세요.

클라우드 오케스트레이션에서의 훅

관리형 정책과 원격 훅이 활성화된 워크스페이스에서는 로컬 컴퓨터 액세스가 있는 Work 클라우드와 dot이 지원되는 작업 이벤트나 도구 이벤트가 발생할 때 MCP 서비스를 호출할 수 있습니다. 이때 워크스페이스 관리자가 설정한 mcp_tool 핸들러를 사용합니다. 관리자는 에이전트 보안에서 이 핸들러를 설정합니다. 로컬 컴퓨터 액세스가 없는 Work 클라우드와 개인 계정은 이러한 엔터프라이즈 훅을 사용하지 않습니다.

클라우드 오케스트레이션에서는 도구가 연결된 컴퓨터에서 실행될 때도 전역 MCP 훅만 지원합니다. 명령어·프롬프트·에이전트 핸들러, 로컬 설정·플러그인·로컬 디렉터리에서 가져온 훅, 특정 환경에만 적용되는 훅, SessionEnd MCP 훅은 지원하지 않습니다. 오케스트레이션과 실행이 모두 로컬에서 이루어지면 로컬 전용 Work 및 Codex 스레드에서 기존 훅을 계속 사용할 수 있습니다.

지원되는 훅은 명시적인 거부 결정을 반환해 작업을 차단할 수 있습니다. PreToolUse에서 오류가 발생하거나 제한 시간이 초과되거나 응답 형식이 잘못되면 도구가 실행될 수 있습니다. MCP 훅은 감사 추적에 필요한 기록의 일부만 제공합니다. 배포 시 점검할 사항과 감사 기록의 범위는 훅 및 네트워크 호환성 확인을 참고하세요.

로컬 Codex의 관리형 훅

로컬 Codex 훅은 [hooks] 아래에 정의하세요. 이 설정은 requirements.toml에 작성합니다. 훅을 로컬에서 비활성화한 사용자에게도 관리형 훅을 강제하려면 [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도 설정합니다.

플러그인 훅은 다른 훅과 동일한 이벤트 스키마를 사용합니다. 실행 전에 훅을 검토하고 신뢰하도록 설정하세요. CLI에서는 /hooks를 여세요. 데스크톱 앱에서는 Composer에서 훅 검토를 선택하거나 설정 > 훅을 여세요. 플러그인 업데이트로 플러그인에 포함된 스크립트가 변경되면 훅 정의가 그대로여도 다시 검토해야 합니다.

매처 패턴

matcher 필드는 훅 실행 조건을 지정하는 정규식 문자열입니다. 지원되는 이벤트가 발생할 때마다 훅을 실행하려면 "*" 또는 ""를 사용하거나 matcher를 생략하세요.

현재 Codex에서는 일부 이벤트만 matcher를 적용합니다.

이벤트 matcher의 필터링 대상 참고 사항
PermissionRequest 도구 이름 Bash, apply_patch*, MCP 도구 이름 등을 지원합니다.
PostToolUse 도구 이름 지원되는 도구를 참고하세요.
PostCompact 컨텍스트 압축 계기 값은 manual 또는 auto입니다.
PreModelRequest, PostModelRequest 지원되지 않음 모델 요청을 시도할 때마다 두 이벤트가 모두 발생합니다.
PreCompact 컨텍스트 압축 계기 값은 manual 또는 auto입니다.
PreToolUse 도구 이름 지원되는 도구를 참고하세요.
SessionEnd 종료 사유 현재는 other만 사용합니다.
SessionStart 시작 방식 값은 startup, resume, clear, compact, fork입니다.
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|fork
  • manual|auto

지원되는 도구

PreToolUse와 PostToolUse는 셸 및 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_agent는 Agent에도 일치합니다.
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 전용 확장 필드. 활성 모델의 슬러그

턴 단위로 실행되는 훅의 이벤트별 표에는 Codex 전용 확장 필드인 turn_id도 나와 있습니다.

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에 저장하고, 저장 경로와 함께 출력의 앞부분과 뒷부분을 미리보기로 모델에 전달합니다. 이를 디스크 스필링이라고 합니다. 한도를 초과한 출력은 디스크에 보관하고 모델에는 짧은 미리보기를 제공합니다. 파일을 쓸 수 없는 경우에도 모델은 길이를 줄인 미리보기를 받습니다.

훅과 플러그인이 제공하는 컨텍스트는 간결하게 유지하세요. 여러 훅과 플러그인의 컨텍스트가 누적되면 모델 성능이 저하될 수 있습니다. additionalContextLimit를 높이면 이러한 위험이 커집니다. 훅 자체에서 출력량을 엄격하게 제한하는 경우에만 한도를 0으로 설정하세요. 그렇지 않으면 훅 하나가 컨텍스트 윈도우 전체를 소진할 수 있습니다.

additionalContext를 반환하는 명령어 훅에서는 핸들러에 additionalContextLimit를 설정해 대략적인 토큰 한도를 조정할 수 있습니다.

{
  "type": "command",
  "command": "python3 ~/.codex/hooks/session_start.py",
  "additionalContextLimit": 5000
}

additionalContextLimit를 생략하면 기본 한도인 2500토큰을 사용합니다. 다른 한도를 지정하려면 양의 정수를 사용하세요. 0을 지정하면 핸들러가 반환하는 추가 컨텍스트 전체를 모델에 직접 전달합니다. 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 훅은 백그라운드에서 실행할 때도 기본 제한 시간이 1초이고 최댓값은 3초입니다.

백그라운드 훅의 실행 방식

백그라운드 훅이 끝나면 Codex는 해당 훅에서 지원하는 정보성 출력을 대화 중 다음과 같이 안전한 시점에 전달합니다.

  • 진행 중인 턴이 있으면 현재 모델 요청과 도구 호출이 끝날 때까지 기다렸다가 같은 턴의 다음 모델 요청에 출력을 제공합니다.
  • 진행 중인 턴이 없으면 다음 사용자 턴까지 기다립니다. 백그라운드 훅이 끝나도 새 턴이 시작되지는 않습니다.

동기 훅과 같은 이벤트별 JSON 출력 형식을 사용하세요. Codex는 additionalContext를 모델 컨텍스트에 추가하고 systemMessage를 경고로 표시합니다.

백그라운드 훅은 자신을 실행시킨 작업을 차단하거나 승인하거나 변경하는 등 작업 자체를 제어할 수 없습니다. 도구 정책 적용, 권한 결정, 프롬프트 거부 또는 턴 계속 진행 여부 결정에는 동기 훅을 사용하세요.

제한 사항

  • Codex는 세션마다 최대 8개의 백그라운드 훅을 동시에 실행합니다. 나머지 훅은 실행 중인 훅이 끝날 때까지 기다립니다.
  • 조건이 일치하는 각 호출은 독립적으로 실행되며, 백그라운드 훅은 시작한 순서와 다른 순서로 끝날 수 있습니다.
  • 세션이 끝나면 Codex는 완료되지 않은 백그라운드 훅을 취소하고 아직 전달하지 않은 출력을 폐기합니다.
  • SessionEnd 훅은 항상 동기적으로 실행됩니다.

훅

SessionStart

이 이벤트에서는 matcher를 source에 적용합니다.

공통 입력 필드 외에 다음 필드가 있습니다.

필드 타입 의미
source string 세션 시작 방식. startup, resume, clear, compact 또는 fork

포크한 스레드는 source: "fork"를 사용합니다. 제공된 기록을 바탕으로 스레드를 재개하는 경우에는 여전히 source: "resume"를 사용합니다.

stdout에 출력한 일반 텍스트는 추가 개발자 컨텍스트로 전달됩니다.

stdout으로 반환하는 JSON은 공통 출력 필드와 다음과 같은 훅 전용 형식을 지원합니다.

{
  "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 전용 확장 필드. 진행 중인 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 도구 호출 및 기타 로컬 함수 도구 호출을 가로챌 수 있습니다. 지원되는 호출 경로와 예외는 지원되는 도구를 참고하세요.

matcher는 tool_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 도구별 입력. Bash와 apply_patch는 tool_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."
  }
}

지원되는 도구 호출을 차단하지 않고 입력을 변경하려면 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__server__tool 같은 MCP 도구 이름 등을 사용할 수 있습니다. apply_patch는 Edit와 Write에도 일치합니다.

공통 입력 필드 외에 다음 필드가 있습니다.

필드 타입 의미
turn_id string Codex 전용 확장 필드. 진행 중인 Codex 턴의 ID
tool_name string 훅에서 사용하는 도구의 정식 이름. 예를 들어 Bash, apply_patch 또는 mcp__fs__read 같은 MCP 도구 이름
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의 경우 명령어가 0이 아닌 상태 코드로 종료된 후에도 실행됩니다. 이미 실행된 도구의 사이드 이펙트는 되돌릴 수 없습니다. 지원되는 호출 경로와 예외는 지원되는 도구를 참고하세요.

matcher는 tool_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 도구별 입력. Bash와 apply_patch는 tool_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는 도구 결과를 훅의 피드백이나 중지 메시지로 대체한 뒤 작업을 이어갑니다.

updatedMCPToolOutput과 suppressOutput은 파싱하지만 아직 지원하지 않습니다. 이 경우 Codex는 훅 실행을 실패로 표시하고 오류를 보고한 후 도구 결과를 정상적으로 처리합니다.

코드 모드에서의 도구 호출

모델이 코드 모드에서 JavaScript로 도구를 호출하면 해당 중첩 호출에도 훅의 결정이 적용됩니다. PreToolUse는 도구 실행 전에 호출을 중지하거나 입력을 변경할 수 있습니다. PostToolUse로 차단하더라도 도구의 사이드 이펙트를 되돌릴 수는 없지만 원래 결과가 실행 중인 스크립트에 전달되는 것은 막을 수 있습니다.

훅 결과 코드 모드에서의 동작
PreToolUse가 차단 도구가 실행되기 전에 도구 호출의 프로미스가 거부됩니다.
PreToolUse가 updatedInput 반환 변경된 입력으로 도구가 실행되고 프로미스는 그 결과로 이행됩니다.
PostToolUse가 decision: "block"을 반환하거나 코드 2로 종료 도구가 실행된 뒤 훅이 제공한 사유와 함께 프로미스가 거부됩니다.
PostToolUse가 continue: false 반환 Codex는 모델에 전달할 결과로 훅의 피드백을 사용하지만 중첩된 도구 호출의 프로미스는 거부하지 않습니다.

PreModelRequest와 PostModelRequest

같은 턴 안에서의 재시도를 포함해 모델 요청을 기록하려면 이 두 훅을 사용하세요. PreModelRequest는 요청을 시도하기 전에 매번 실행됩니다. PostModelRequest는 각 시도의 결과를 보고합니다. 두 훅 모두 모델과 turn_id를 받으며, agent_id와 agent_type도 값이 있으면 받습니다. 훅 출력은 진단용으로만 사용됩니다. 이 출력으로 모델의 컨텍스트를 변경하거나 요청을 차단할 수 없습니다.

PostModelRequest에는 다음 세 필드가 추가로 포함됩니다.

필드 의미
status completed, failed 또는 cancelled
error 오류 메시지가 있으면 해당 메시지, 없으면 null
token_usage 해당 시도의 토큰 수 집계가 있으면 그 집계값, 없으면 null

PreCompact

PreCompact는 Codex가 채팅 컨텍스트를 압축하기 전에 실행됩니다. matcher는 trigger에 적용되며 가능한 값은 manual과 auto입니다.

공통 입력 필드 외에 다음 필드가 있습니다.

필드 타입 의미
turn_id string Codex 전용 확장 필드. 진행 중인 Codex 턴의 ID
trigger string 컨텍스트 압축을 시작한 계기. manual 또는 auto

stdout에 출력한 일반 텍스트는 무시합니다.

stdout으로 반환하는 JSON은 공통 출력 필드를 지원합니다. 일치하는 PreCompact 훅이 continue: false를 반환하면 Codex는 컨텍스트를 압축하기 전에 멈춥니다.

PostCompact

PostCompact는 Codex가 채팅 컨텍스트를 압축한 후 실행됩니다. matcher는 trigger에 적용되며 가능한 값은 manual과 auto입니다.

공통 입력 필드 외에 다음 필드가 있습니다.

필드 타입 의미
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

이 이벤트에서는 matcher를 agent_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 훅이 stdout에 출력하는 내용은 종료 코드가 0일 때 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 훅이 stdout에 출력하는 내용은 종료 코드가 0일 때 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 훅이 작업을 계속하도록 요청해도 중지가 우선합니다.

Interrupt

Interrupt는 메인 스레드에서 진행 중인 턴을 사용자가 중단할 때 실행됩니다. 중단 사실을 기록하거나 훅이 시작한 작업을 정리할 때 사용하세요. 유휴 스레드나 하위 에이전트에서는 실행되지 않으며, 설정된 matcher는 무시합니다.

이 이벤트에는 공통 입력 필드 외에도 중단된 턴의 ID인 turn_id와 permission_mode가 포함됩니다.

명령어 훅의 기본 제한 시간은 1초이며 1~3초 범위에서 설정할 수 있습니다. 훅 출력으로 중단을 막거나 턴을 다시 시작할 수는 없습니다. 출력 없이 종료 코드 0을 반환하거나, 경고를 표시하려면 선택적 systemMessage 필드를 포함한 JSON을 반환하세요. 이 이벤트에서 일반 텍스트 출력은 유효하지 않습니다.

{ "systemMessage": "Saved the interrupted turn to the local audit log." }

스키마

링크된 main 브랜치의 스키마에는 현재 릴리스에 없는 훅 필드가 포함될 수 있습니다. 릴리스 버전의 동작은 이 페이지를 기준으로 확인하세요.

현재 전송 형식을 정확히 확인하려면 Codex GitHub 리포지터리에 있는 자동 생성 스키마를 참고하세요.