Claude Code·Cursor·Codex의 에이전트 hook 비교와 설정
Agent hooks in Claude Code, Cursor, and Codex explained
핵심 요약
- 에이전트 hook은 특정 이벤트에 맞춰 도구가 스크립트를 실행하므로, 에이전트가 지침을 잊을 수 있는 AGENTS.md나 전역 지침보다 반복 규칙을 일관되게 적용한다.
- hook은 이벤트, 트리거 조건, 스크립트, 실행 결과에 대한 동작으로 구성된다. 실행 전 hook은 호출을 차단하거나 바꿀 수 있지만, 실행 후 hook은 이미 일어난 동작을 되돌릴 수 없다.
- Claude Code·Cursor·Codex는 이벤트와 설정 형식, 실패 처리 방식이 다르다. hook을 켜기 전에 스크립트를 검토하고, 위험한 작업을 보호하는 경우와 편의 기능인 경우에 맞춰 실패 정책을 정해야 한다.
도입
AGENTS.md와 전역 지침은 에이전트의 컨텍스트에 들어가도 매번 준수된다는 보장이 없다. 반면 hook은 도구가 정해진 이벤트마다 스크립트를 실행한다. 이 글은 Claude Code, Cursor, Codex의 hook 구성 요소와 차이를 정리하고, 원시 xcodebuild 출력을 xcsift로 필터링하는 설정 예시와 안전하게 운용하는 방법을 제시한다.
상세 요약
지침과 hook의 차이
AGENTS.md, agent skill, 전역 지침은 에이전트가 읽고 따르도록 요청하는 내용이다. 실제로 따를지는 에이전트의 판단에 달려 있다. hook은 에이전트가 규칙을 기억하는지와 관계없이 도구가 정해진 시점에 스크립트를 실행한다. 지침은 의도를 설명하고, 매번 지켜야 하는 규칙은 hook으로 실행하도록 나눌 수 있다.
hook은 네 부분으로 이뤄진다.
- 이벤트: 도구 실행 직전, 에이전트 턴 종료, 세션 시작처럼 hook이 실행될 시점이다.
- 트리거: 이벤트 중 특정 도구 호출만 골라내는 조건이다.
- 스크립트: 이벤트 세부 정보를 표준 입력의 JSON으로 받는 코드다.
- 동작: 결과를 바탕으로 컨텍스트를 추가하거나 명령을 바꾸고, 호출을 거부하는 등 도구에 요청하는 조치다.
실행 전 hook은 호출을 막거나 바꿀 수 있다. 실행 후 hook은 이미 발생한 동작을 되돌릴 수 없다.
Claude Code·Cursor·Codex의 차이
세 도구는 같은 원리를 사용하지만 이벤트 이름과 설정 파일 형식이 다르다.
| 항목 | Claude Code | Cursor | Codex |
|---|---|---|---|
| 사용자 설정 | ~/.claude/settings.json |
~/.cursor/hooks.json |
~/.codex/hooks.json 또는 config.toml |
| 프로젝트 설정 | .claude/settings.json |
.cursor/hooks.json |
.codex/hooks.json 또는 config.toml |
| 실행 전 이벤트 | PreToolUse |
preToolUse, beforeShellExecution |
PreToolUse |
| 실행 후 이벤트 | PostToolUse |
postToolUse, afterFileEdit |
PostToolUse |
| 턴 종료 이벤트 | Stop |
stop |
Stop |
Claude Code와 Codex는 이벤트, matcher, handler 목록을 사용하는 비슷한 설정 구조를 쓴다. Cursor는 버전과 hook별 명령을 지정하는 더 평평한 hooks.json 형식이다. 도구 필터 이름도 다르다. Claude Code와 Codex는 Bash, Cursor는 Shell을 사용한다.
호출 차단은 exit code 2 또는 도구별 JSON 응답으로 처리한다. hook 실패 시 Claude Code와 Cursor는 별도 설정이 없으면 호출을 계속 진행할 수 있다. Codex는 hook 실패로 보고하므로 이벤트가 실제로 어떻게 동작하는지 확인해야 한다. Codex는 실행 전 hook을 검토하고 신뢰한 뒤 실행하며, 프로젝트 hook은 신뢰된 프로젝트에서만 불러온다. Cursor도 신뢰된 workspace에서만 프로젝트 hook을 실행한다.
xcodebuild 출력을 필터링하는 예
원시 xcodebuild 출력은 길고, 이 예시에서 에이전트에 필요한 정보는 오류, 경고, 테스트 결과다. 작성자는 출력 필터 xcsift를 사용해 빌드 명령을 set -o pipefail; <명령> 2>&1 | xcsift -f toon -w 형태로 다시 실행하도록 유도한다. 예시 hook은 필터가 없는 xcodebuild build 또는 xcodebuild test를 거부하고 대체 명령을 안내한다. 이미 xcsift를 사용하는 명령과 xcodebuild -list는 그대로 통과시킨다.
스크립트는 Cursor 입력의 cursor_version을 확인해 Cursor용 JSON 응답을 내보낸다. Claude Code와 Codex에서는 안내를 표준 오류로 출력하고 exit code 2로 호출을 거부한다. 입력이 예상과 다르거나 jq를 사용할 수 없는 경우에는 차단하지 않는다. 편의 기능이므로 실패 시 작업을 계속하는 fail open을 선택한 것이다.
설정은 Claude Code의 ~/.claude/settings.json 또는 Codex의 ~/.codex/hooks.json에서 PreToolUse와 Bash matcher를 지정한다. Cursor는 ~/.cursor/hooks.json에서 preToolUse와 Shell matcher를 지정한다. 두 구성 모두 예시에서 timeout을 5초로 설정한다. 이런 출력 필터링과 토큰 맥락은 Claude Code·Codex·Cursor의 토큰 사용량을 줄이는 방법에서도 다룬다.
운영 시 확인할 점
- 저장소나 플러그인에서 제공한 hook도 사용자 권한으로 실행되는 스크립트다. 활성화 전에 코드를 읽는다.
- 편의 hook은 fail open, 위험한 동작을 막는 hook은 실패 시 차단하도록 의도적으로 선택한다. Claude Code에서는 timeout만으로 호출이 차단되지 않을 수도 있다.
- hook 실행 중에는 에이전트가 기다리므로 timeout을 짧게 둔다. 작성자는 사용자 수준 hook에 5초 timeout을 설정했다.
- 턴 종료 hook이 후속 메시지를 보내면 반복 실행될 수 있다. Cursor는
loop_limit으로 stop hook 반복을 제한하며 기본값은 5다. - hook만 유일한 보호 장치로 삼지 않는다. Codex에서는 이미 통과한 명령을 에이전트가 다시 확인할 때
PreToolUse가 재실행되지 않는 경우가 있다.
그 밖에 턴 종료 후 AGENTS.md 갱신을 요청하는 hook, 오래된 worktree를 찾아 정리 대상을 보고하는 hook, 세션 종료 시 기록을 파일로 남기는 hook도 소개한다. 각 도구는 세션 시작·종료, 프롬프트 전송, subagent 실행 전후 등 표에 없는 이벤트도 제공하므로 실제 설정 전에는 해당 도구의 문서를 확인해야 한다.
결론
반복해서 적용해야 하는 규칙은 hook으로 자동화하되, 스크립트가 사용자 권한으로 실행된다는 점을 고려해 활성화 전에 내용을 확인해야 한다. 편의 목적의 빌드 필터는 실패해도 작업을 막지 않는 fail open으로, 위험한 명령을 막는 hook은 실패 시 차단하는 정책으로 구성한다. 짧은 timeout을 설정하고 도구별 이벤트와 예외 동작을 테스트한다.