Cursor hooks 사용법, 에이전트 전후에 뭘 걸 수 있나

Cursor hooks는 에이전트 루프의 전·후 단계에 스크립트를 붙이는 장치입니다. 공식 Hooks 문서 기준으로 sessionStart→도구 before/after→stop/sessionEnd처럼 언제 도는지를 먼저 잡고, hooks.json과 /create-hook로 최소 구성을 올리면 됩니다. 가격·플랜 이야기는 없습니다.

이 글은 저장·커밋 전 가드(afterFileEdit·beforeShellExecution 중심)를 다시 쓰지 않습니다. 수명주기 before/after·hooks.json·/create-hook만 다룹니다.

hook이 실행되는 시점은?

한 줄 답: Agent Chat·Cmd+K에서는 세션 시작 → 프롬프트 제출 → 도구 전/후 → 응답/사고 후 → stop → 세션 종료 순으로 훅이 붙습니다. Tab·워크스페이스 오픈은 별 표면입니다.

공식 문서의 Agent hooks(에이전트 수명주기):

구간훅역할(요약)
세션sessionStart / sessionEnd세션 환경·컨텍스트 주입 / 종료 감사(fire-and-forget)
프롬프트beforeSubmitPrompt전송 직전 검증·차단(continue)
도구 일반preToolUse / postToolUse / postToolUseFailure모든 도구 전·후·실패
서브에이전트subagentStart / subagentStopTask 서브에이전트 생성·종료
셸·MCPbeforeShellExecution·afterShellExecution / beforeMCPExecution·afterMCPExecution셸·MCP 전후 통제·감사
파일beforeReadFile / afterFileEdit읽기 게이트 / 편집 후 후처리
컨텍스트preCompact컴팩션 관찰(차단 불가)
응답afterAgentResponse / afterAgentThought응답·사고 블록 추적
루프 종료stop완료 시 followup_message로 자동 이어가기 가능

별 표면:

  • Tab hooks: beforeTabFileRead / afterTabFileEdit — 인라인 Tab 전용
  • App: workspaceOpen — 워크스페이스 오픈·폴더 변경(에이전트 세션 밖)

실무에서 수명주기를 걸 때 자주 쓰는 축은 세 가지입니다.

  1. 시작·주입 — sessionStart로 env·additional_context (차단은 현재 호출부가 강제하지 않음)
  2. 도구 before/after — 좁은 이벤트(beforeShellExecution 등)를 먼저 쓰고, 전부 보려면 preToolUse/postToolUse
  3. 종료·루프 — stop·subagentStop의 followup_message + loop_limit(기본 5)

Cloud agent는 .cursor/hooks.json의 커맨드 훅을 로드합니다. sessionStart/sessionEnd·MCP before/after·Tab·workspaceOpen은 클라우드에서 없거나 지연되며, ~/.cursor/hooks.json 사용자 훅은 홈이 없어 적용되지 않습니다.

hooks.json 최소 예시는?

한 줄 답: version: 1과 hooks 맵이면 됩니다. 프로젝트는 /.cursor/hooks.json(경로는 루트 기준 .cursor/hooks/...), 전역은 ~/.cursor/hooks.json(경로는 ~/.cursor/ 기준). 빠른 생성은 Agent 채팅의 /create-hook.

/create-hook은 공식 Skills 목록에 있는 내장 스킬입니다. 자연어로 “세션 시작 시 감사 로그, stop에서 실패면 follow-up”처럼 요청하면 hooks.json과 스크립트를 스캐폴딩합니다. 손수 쓸 때는 Customize → Hooks 탭과 Hooks 출력 채널로 로드·실행을 확인합니다.

수명주기 최소 예(프로젝트):

{
  "version": 1,
  "hooks": {
    "sessionStart": [
      { "command": ".cursor/hooks/session-init.sh" }
    ],
    "preToolUse": [
      {
        "command": ".cursor/hooks/validate-tool.sh",
        "matcher": "Shell|Task"
      }
    ],
    "stop": [
      {
        "command": ".cursor/hooks/track-stop.sh",
        "loop_limit": 5
      }
    ]
  }
}

스크립트는 실행 권한이 필요합니다(chmod +x). stdin/stdout으로 JSON을 주고받으며, 기본 타입은 command입니다. 자연어 조건만 보려면 "type": "prompt" 훅도 가능하지만 Cloud에서는 커맨드 훅만 지원합니다.

정의 옵션 요약: command(필수), type, timeout, matcher(정규식 필터), failClosed(기본 false — 실패 시 fail-open), loop_limit(stop/subagentStop).

경로 규칙:

  • 프로젝트 훅: 작업 디렉터리 = 프로젝트 루트 → .cursor/hooks/format.sh
  • 사용자 훅: 작업 디렉터리 = ~/.cursor/ → ./hooks/format.sh

우선순위(높→낮): Enterprise → Team → Project → User. 같은 이벤트에 여러 소스가 있으면 모두 실행되고, permission은 deny > ask > allow로 병합됩니다.

실패하면 어디를 보나?

한 줄 답: Customize의 Hooks 탭과 Hooks 출력 채널을 먼저 보고, 경로·실행 권한·exit code·failClosed를 순서대로 점검합니다.

점검 순서:

  1. 로드 여부 — hooks.json 저장 시 Cursor가 다시 로드합니다. 안 보이면 Customize → Hooks, 그래도 안 되면 Cursor 재시작.
  2. 경로 — 프로젝트는 루트 기준 .cursor/hooks/..., 사용자 훅은 ~/.cursor/ 기준. ./hooks/...를 프로젝트에 쓰면 루트의 /hooks를 찾습니다.
  3. 실행 권한·환경 — chmod +x, 스크립트가 쓰는 jq/python 등이 훅 환경에 있는지.
  4. exit code — 0 = 성공(JSON 사용). 2 = 차단(permission: "deny"와 동등). 그 외 비정상 = 기본 fail-open(동작은 통과, 로그만).
  5. failClosed: true — 크래시·타임아웃·비정상 exit에서도 막고 싶을 때(보안 게이트용). permission 훅은 잘못된 JSON/스키마면 failClosed가 false여도 차단합니다.
  6. matcher — 이벤트가 안 뜨면 matcher가 너무 좁은지 확인합니다(preToolUse는 도구명, beforeShellExecution은 명령 문자열 등).

Cloud에서 안 도는 경우: 사용자 훅만 두었거나, sessionStart/MCP/Tab/workspaceOpen처럼 클라우드 미지원 이벤트인지, 초기 read-only 턴(훅 미로드)인지 확인합니다.

마무리

Cursor hooks 사용법의 핵심은 에이전트 수명주기의 before/after에 무엇을 걸지입니다. sessionStart·도구 전후·stop을 hooks.json에 최소로 두고, 스캐폴딩은 /create-hook로 시작하시면 됩니다. 실패 시에는 Hooks 탭·출력 채널 → 경로·exit code·failClosed 순입니다. 저장·커밋 가드만 필요하면 별도 hooks 가드 글을 보시고, 이벤트 전체는 Hooks를 참고하시기 바랍니다.

출처

  • Cursor Hooks — 이벤트 목록, hooks.json, exit code·failClosed, Cloud 지원 표
  • Agent Skills — 내장 /create-hook