Quick Flow
| 시점 | Hook | 먼저 쓰는 목적 |
|---|---|---|
| 세션·subagent 시작 | SessionStart, SubagentStart | 제한된 context 주입 |
| 사용자 요청 직전 | UserPromptSubmit | 요청 형식 검사 또는 차단 |
| 도구 실행 전 | PreToolUse | 입력 검사·차단·지원 도구 input 수정 |
| 승인 요청 직전 | PermissionRequest | allow, deny, 일반 승인 흐름 유지 |
| 도구 실행 뒤 | PostToolUse | 결과 검토와 추가 context |
| compaction·종료 | PreCompact, PostCompact, SubagentStop, Stop, SessionEnd | 상태 보존·후속 제어 |
{
"hooks": {
"PreToolUse": [{
"matcher": "Bash",
"hooks": [{
"type": "command",
"command": "./.codex/hooks/check-command.sh"
}]
}]
}
}Hook은 hooks.json 또는 config.toml의 [hooks]에서 발견됩니다. 안전상 부작용을 막는 정책은 PreToolUse 또는 PermissionRequest에 두고, PostToolUse는 이미 실행한 명령의 결과를 읽는 용도로만 사용합니다.
이벤트와 발견 범위
현재 Hook은 turn 중 PreToolUse, PermissionRequest, PostToolUse, PreCompact, PostCompact, UserPromptSubmit, SubagentStop, Stop을 지원합니다. SessionStart, SubagentStart는 시작 시점에, SessionEnd는 main thread가 끝날 때 실행됩니다. SessionEnd는 subagent에는 실행되지 않습니다.
Codex는 active config layer 옆의 hooks.json과 inline [hooks]를 모두 읽고, enabled plugin이 제공하는 Hook도 함께 발견할 수 있습니다. 여러 source의 matching Hook은 모두 실행되고 같은 event의 command Hook은 병렬로 시작될 수 있습니다. higher-precedence layer가 lower Hook을 통째로 덮어쓰는 구조가 아니므로, 중복된 차단이나 외부 호출이 없는지 source 전체를 확인합니다.
project .codex/ Hook은 project layer가 trusted일 때만 로드됩니다. non-managed command Hook은 definition hash를 검토·신뢰하기 전에는 실행되지 않으며, CLI에서는 /hooks로 source와 trust 상태를 확인합니다. 관리되는 Hook은 조직 정책에 따라 trusted 상태로 적용될 수 있습니다.
승인과 도구 제어
PreToolUse는 지원되는 도구를 실행하기 전에 block하거나 입력을 바꿀 수 있습니다. PermissionRequest는 sandbox escalation, managed-network approval처럼 Codex가 승인을 물어보려 할 때만 실행됩니다. tool_name은 Bash, apply_patch, MCP tool name 같은 canonical 값이고, tool_input은 도구별 JSON입니다.
{
"hookSpecificOutput": {
"hookEventName": "PermissionRequest",
"decision": {
"behavior": "deny",
"message": "배포 명령은 운영 runbook에서만 승인합니다."
}
}
}matching Hook이 여러 결정을 반환하면 deny가 우선합니다. allow나 deny를 내리지 않으면 일반 approval prompt가 계속됩니다. PermissionRequest에 updatedInput, updatedPermissions, interrupt를 반환하는 방식은 현재 지원되지 않아 Hook failure가 되므로, 미래용 field를 추측해 사용하지 않습니다.
결과 처리와 운영 경계
PostToolUse는 side effect가 끝난 뒤 실행됩니다. decision: "block"은 이미 끝난 command를 되돌리지 못하고, model이 받는 tool result만 Hook feedback으로 바꿉니다. destructive command는 사후 로그 분석에 맡기지 말고 PreToolUse, permission profile, Rules에서 먼저 막습니다.
PreCompact와 PostCompact의 matcher는 manual 또는 auto compaction trigger를 받습니다. SubagentStop은 agent result를 검토하고 한 번 더 진행하도록 요청할 수 있지만, common output의 continue: false는 SubagentStart를 멈추지 않습니다. transcript path는 편의 정보이며 stable Hook interface가 아니므로 parser의 영속 입력으로 쓰지 않습니다.
Hook은 짧고 결정적이어야 합니다. 느린 network call이나 파일 변경을 Hook에 넣으면 모든 turn을 지연시키고 재현도 어렵게 만듭니다. 먼저 read-only 검증으로 시작하고, 실제 차단 정책은 반환 field와 지원 event를 현재 문서 기준으로 좁게 적용하십시오.
참고 링크
2 sources