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.jsonconfig.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
}
]
}
]
}
}참고:
description는hooks.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"핸들러만 실행됩니다.prompt및agent핸들러는 파싱되지만 건너뜁니다. - 명령은 세션
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.json의 hooks 항목으로 이 기본값을 재정의할 수 있습니다.
매니페스트 항목은 ./ 접두사가 붙은 경로, ./ 접두사가 붙은 경로의 배열,
인라인 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_ROOT및CLAUDE_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|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__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 전용 확장 기능입니다. 활성 모델 슬러그 |
턴 범위 훅의 이벤트별 표에는 turn_id이 Codex 전용 확장 기능으로
나열됩니다.
SessionStart, PreToolUse, PermissionRequest, PostToolUse,
UserPromptSubmit, SubagentStart, SubagentStop 및 Stop에는 현재 권한 모드를 default,
acceptEdits, plan, dontAsk 또는 bypassPermissions으로 설명하는
permission_mode도 포함됩니다.
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
}기본 2500토큰 임계값을 사용하려면 additionalContextLimit을 생략하세요. 다른 임계값을 선택하려면
양의 정수를 사용하고, 핸들러의 전체 추가 컨텍스트를 모델에 직접 전달하려면 0을 사용합니다.
Codex는 일치하는 각 핸들러를 독립적으로 평가합니다. 추가
컨텍스트를 생성할 수 없는 이벤트의 경우 Codex는 additionalContextLimit을 무시하고 구성
경고를 보고합니다.
이 설정은 additionalContext에만 적용됩니다. 도구 피드백과 후속 실행
프롬프트에는 기본 한도가 유지됩니다.
지나치게 큰 출력은 디스크에 기록될 수 있으므로 훅 출력에 비밀 정보나 기타 민감한 데이터를 반환하지 마세요.
훅
SessionStart
이 이벤트에서는 matcher이 source에 적용됩니다.
공통 입력 필드 외에 추가되는 필드는 다음과 같습니다.
| 필드 | 유형 | 의미 |
|---|---|---|
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이 바로 실행되지 않습니다. 훅이 실행되는 동안에도
세션 대화 기록을 읽을 수 있습니다.
이 이벤트에서는 matcher가 reason을 필터링합니다. 현재 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
이 이벤트에서는 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."
}
}차단하지 않고 지원되는 도구 호출을 다시 작성하려면
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,
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는 일반 승인 흐름을 사용합니다.
PermissionRequest에 대해 updatedInput, updatedPermissions 또는 interrupt을
반환하지 마세요. 해당 필드는 향후 동작을 위해 예약되어 있으며 현재는
안전하게 실패하도록 처리됩니다.
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는 모델에 표시되는 결과로 훅 피드백을 사용하지만, 중첩된 도구 프로미스를 거부하지는 않습니다. |
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은 종료 코드가 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