이 페이지는 영어 문서의 번역입니다. 명령, 식별자, 예제는 그대로입니다. 런타임 7.24.4 · SDK 2.6.7. 영어 원문
수명 주기 훅
상태: 활성 범위: 현재 상태 최종 검토: 2026-08-23 담당: ax-code 런타임
수명 주기 훅은 런타임을 다시 빌드하지 않고 에이전트 이벤트에서 셸 명령을 실행하게 합니다. 권한 규칙과 격리 샌드박스를 보완합니다. 훅은 결정적인 부작용입니다(“항상 포맷”, “강제 푸시 금지”). 프롬프트는 조언으로 남습니다.
이벤트
| 이벤트 | 시점 | 막을 수 있는가 |
|---|---|---|
| PreToolUse | 도구가 실행되기 전 | 예 (blockOnFailure: true) |
| PostToolUse | 도구가 완료된 뒤 (args: 도구 인수). 제한된 stdout / 구조화된 피드백이 모델이 보는 도구 결과에 덧붙습니다. 아래를 보십시오 |
아니요 |
| PostToolUseFailure | 도구가 예외를 던진 뒤 (args: { args, error }, 오류 텍스트는 4,000자로 제한). 보내고 잊습니다. 오류는 여전히 바꾸지 않고 모델에 도달합니다 |
아니요 |
| Stop | 세션 턴이 완료될 때 (팩은 자동화를 통해 중지 시 실행될 수 있음) | 아니요 |
| UserPromptSubmit | 사용자 프롬프트가 제출될 때, 메시지가 저장되기 전 | 예 (blockOnFailure: true) |
| PreCompact | 세션 압축이 실행되기 전 (args: { auto, overflow }) |
아니요 |
| SubagentStop | task 서브에이전트가 끝날 때 (args: { agent, status }) |
아니요 |
| SessionStart | 최상위 세션이 만들어질 때 (args: { sessionID, title, time }) |
아니요 |
| SessionEnd | 세션이 제거되거나 보관될 때 (args: { sessionID, reason }, reason는 "remove" 또는 "archive") |
아니요 |
| PostCompact | 세션 압축이 성공적으로 끝난 뒤 (args: { sessionID, reason }, reason는 "auto" 또는 "manual". 컨텍스트 넘침처럼 압축이 중단되면 발생하지 않음) |
아니요 |
| Interrupt | 사용자나 운영자가 실행 중인 턴을 명시적으로 취소할 때 (args: { sessionID }. 정상적인 턴 완료나 내부 정리에서는 발생하지 않음) |
아니요 |
네 가지 세션 수명 주기 이벤트(SessionStart, SessionEnd, PostCompact, Interrupt)와 PostToolUseFailure은 관찰 전용입니다. 발생하고 잊으며, 수명 주기 경로를 막지 않고, 페이로드에는 ID/이유/타임스탬프만 있습니다. 대화 텍스트, 요약, 도구 출력은 없습니다. 서브에이전트 세션은 SessionStart를 발생시키지 않습니다(이미 SubagentStop으로 나타납니다). SubagentStop은 task와 task_parallel이 시작한 자식 모두에 대해 발생합니다.
PostToolUse 피드백이 모델에 도달합니다
PostToolUse 훅은 텍스트를 모델에 돌려줄 수 있습니다. 도구 자신의 출력 뒤, <hook_feedback event="PostToolUse"> 블록 안의 도구 결과에 덧붙습니다. 출력을 대체하지 않고 막지도 않습니다.
- 이전 항목(
protocol없음): 종료 코드 0인 훅의 다듬어진 stdout. protocol: "claude-code"항목:hookSpecificOutput.additionalContext, 또는reason({"decision": "block", "reason": "..."}판정에서 온 값), 또는 훅이 2로 끝날 때의 stderr. 그 밖의 0이 아닌 종료는 아무것도 기여하지 않습니다.
피드백은 훅당 4,000자, 도구 호출당 8,000자로 제한되므로, 시끄러운 훅이 컨텍스트를 가득 채울 수 없습니다. 이것이 format-after-edit 팩을 유용하게 만듭니다. 이제 알림이 로그에만 남지 않고 모델의 다음 턴에 들어갑니다.
이 이름은 AX Code 내부 플러그인 트리거(tool.execute.before / tool.execute.after)와 세션 수준의 프롬프트, 압축, 서브에이전트, 중지 훅에 대응합니다. 합성 이어가기 프롬프트(내부 agentRouting: "preserve" 프롬프트)는 UserPromptSubmit를 발생시키지 않습니다.
팩을 켭니다
프로젝트 훅과 플러그인은 저장소가 제어하는 코드를 실행하므로, .ax-code/hooks.json, .ax-code/plugin/, 프로젝트에 구성된 플러그인은 기본적으로 꺼져 있습니다. 검토한 뒤, AX Code를 시작할 때 저장소 밖에서 선택합니다.
AX_CODE_TRUST_PROJECT_CONFIG=1 ax-code
그다음 프로젝트에 .ax-code/hooks.json을 만듭니다.
{
"packs": ["format-after-edit", "block-force-push", "require-tests-on-stop", "protect-env-files", "log-bash-commands"]
}
공식 팩(5개 이상)
| 팩 | 이벤트 | 설명 |
|---|---|---|
format-after-edit |
PostToolUse | 편집 뒤에 포맷하라고 에이전트에게 알림 |
block-force-push |
PreToolUse | git push --force / -f를 막음 |
require-tests-on-stop |
Stop | 변경 뒤에 검증하라고 알림 |
protect-env-files |
PreToolUse | 도구가 .env를 건드릴 때 경고 |
log-bash-commands |
PreToolUse | 감사를 위해 bash 명령을 기록 |
사용자 정의 훅:
{
"hooks": [
{
"event": "PreToolUse",
"matcher": "bash",
"command": "echo running bash",
"blockOnFailure": false
}
]
}
Claude Code 와이어 프로토콜(선택)
이미 Claude Code용으로 쓴 훅이 있으면, 항목이 "protocol": "claude-code"로 Claude Code 와이어 프로토콜을 선택할 수 있습니다.
{
"hooks": [
{
"event": "PreToolUse",
"matcher": "bash",
"command": "my-claude-code-hook.sh",
"protocol": "claude-code"
}
]
}
막을 수 있는 이벤트(PreToolUse, UserPromptSubmit)에서, 선택한 항목은 blockOnFailure 확인 대신 Claude Code 의미로 디코딩됩니다.
- 종료 2는 동작을 막습니다. 훅의 stderr가 이유로 나타납니다. 잘못된 stdout도 여전히 막습니다(실패 시 안전).
- 종료 0과 stdout JSON
{"permissionDecision": "allow"|"deny"|"ask", "reason"?}:allow는 진행합니다.deny은reason와 함께 막습니다.ask는 이유를 보여 주는 대화형hook권한 프롬프트에서 도구 호출을 일시 중지합니다(기본"hook requested user confirmation"). 프롬프트는 대화형 전용입니다.always규칙, 와일드카드 부여, 자율 자동 승인은 응답할 수 없고, 헤드리스 실행은 거부하며, 모델은 이것을 일반적인 권한 거부로 봅니다. 나중에deny로 답하는 훅이 이전ask보다 우선합니다.UserPromptSubmit에는 프롬프트를 붙일 도구 호출이 없으므로ask는 거기서 여전히 막습니다. 중첩된 Claude Code 형태{"hookSpecificOutput": {"permissionDecision": "...", "permissionDecisionReason": "..."}}은 별칭으로 받아들여집니다. - 그 밖의 종료는 막지 않는 오류입니다(기록되고 동작은 진행).
관찰 전용 이벤트는 디코더를 완전히 무시합니다. 막을 수 없습니다. protocol 필드가 없는 항목은 이전과 정확히 같이 동작합니다.
훅 명령에 사용할 수 있는 환경 변수:
HOOK_EVENT— 이벤트 이름입니다. PreToolUse(사용 전), PostToolUse(사용 후), PostToolUseFailure(실패 후), Stop(중지), UserPromptSubmit(프롬프트 제출), PreCompact(압축 전), SubagentStop(서브에이전트 중지), SessionStart(세션 시작), SessionEnd(세션 종료), PostCompact(압축 후), Interrupt(중단)HOOK_TOOL— 도구 IDHOOK_SESSION_IDHOOK_ARGS_JSON— JSON 도구 인수HOOK_ARGS_STDIN=1— 완전한 JSON 인수는 항상 stdin에서 사용할 수 있습니다. 페이로드가 32 KiB보다 크면HOOK_ARGS_JSON은 비어 있습니다HOOK_PACK— 해당할 때의 팩 이름
훅 자식 프로세스는 AX Code 환경의 정화된 버전을 물려받습니다. AX Code는 일반적인 플랫폼과 도구 변수는 유지하지만, 비밀처럼 보이는 이름, 자격 증명이 든 URL, SSH_AUTH_SOCK 같은 자격 증명 도우미, NODE_OPTIONS 같은 프로세스 주입 변수는 제거합니다. 위의 HOOK_* 프로토콜 변수는 정화 뒤에 추가되며 항상 사용할 수 있습니다.
주변 자격 증명이 필요한, 완전히 신뢰하는 이전 훅은 저장소 밖에서 이전 동작을 복원할 수 있습니다.
AX_CODE_HOOKS_FULL_ENV=1 AX_CODE_TRUST_PROJECT_CONFIG=1 ax-code
이 탈출구는 켜진 모든 훅에 모든 환경 변수를 노출합니다. 저장소는 .ax-code/hooks.json를 통해 이것을 요청할 수 없습니다. 모든 훅과 팩을 검토한 뒤에만 사용합니다.
보안 참고: 환경 정화는 주변 자격 증명 노출을 줄이지만 훅 명령을 샌드박스하지는 않습니다. 훅은 접근 가능한 파일을 읽고 호스트 네트워크를 쓸 수 있는 임의의 셸 코드로 남습니다. 신뢰하는 코드로 취급하고, 켠 모든 훅과 팩을 검토합니다.
격리와의 관계
훅은 샌드박스를 대체하지 않습니다. 다음을 사용합니다.
- 옮길 수 있는 쓰기/네트워크 경계에는 앱 격리
- 사용할 수 있을 때 커널이 강제하는 bash 샌드박스에는 OS 격리(기본
"auto"백엔드) - 강제 푸시 같은 정책 부작용과 단단한 차단에는 훅
샌드박스 모드와 SECURITY.md를 보십시오.