SpyBara
Go Premium

plugins/mods/events.md 2026-09-30 23:00 UTC to 2026-10-01 21:02 UTC

This page contains 336 additions and 0 deletions.

2026
Thu 1 21:02

이벤트에 모드로 반응하기

모드에서 Claude Code 이벤트 처리: 도구 호출, 프롬프트, 턴 관찰, 재작성 또는 응답, 훅이 처리하는 이벤트 필터링, 다른 모드 계획

훅은 이벤트 핸들러입니다. Claude Code가 명명된 이벤트가 발생할 때 실행하는 함수입니다. Claude Code는 도구를 실행하거나, 프롬프트를 제출하거나, 모델에 요청을 보내거나, 세션을 시작하거나 종료할 때와 같이 행동하려고 할 때마다 이벤트를 발생시킵니다. 훅은 Claude Code가 행동하기 전에 실행되므로 이벤트를 관찰하거나, 재작성하거나, Claude Code를 대신하여 응답할 수 있습니다. on(eventName, handler)로 훅을 등록합니다.

여기서 시작하기 전에 첫 번째 모드를 빌드하세요. 모든 이벤트와 정확한 필드는 참조를 보거나 빌드의 타입을 읽으세요.

훅이 이벤트를 처리하는 방법

훅은 이벤트와 Claude Code가 그것에 대해 할 일 사이에 있으므로 이벤트를 관찰하거나, 재작성하거나, 직접 응답할 수 있습니다. 세 가지 인수를 받습니다: mods API를 $로, 이벤트를 e로, 다음 핸들러를 next로 받습니다. 이벤트의 핸들러들은 미들웨어 체인을 형성합니다. next(e)는 다음 핸들러를 호출하는데, 이는 다른 모드의 훅이거나 체인의 끝에서 Claude Code 자신의 동작이며, 결과로 해결됩니다. 훅이 next로 무엇을 하는지가 세 가지 중 어느 것을 하는지 결정합니다.

이벤트 관찰하기

이벤트를 변경하지 않고 관찰하려면 작업을 수행하고 next(e)를 반환합니다. 이 훅은 Claude가 사용하려고 하는 각 도구를 기록합니다:

on('tool.call', async ($, e, next) => {
  // 도구가 실행되기 전에 실행됨
  $.ui.log('Claude is about to use ' + e.tool)
  // 이벤트를 변경하지 않고 전달
  return next(e)
})

각 도구가 실행되기 전에 ● my-mod: Claude is about to use Bash와 같은 흐릿한 줄이 트랜스크립트에 나타나며, 여기서 my-mod는 플러그인의 이름입니다. 도구는 모드 없이 실행되는 것처럼 실행됩니다.

이벤트 후에 행동하려면 await next(e)를 하고, 작업을 수행한 후 결과를 반환합니다. 이 훅은 각 도구가 실행된 후에 기록합니다:

on('tool.call', async ($, e, next) => {
  // 도구를 실행하고 결과를 기다림
  const result = await next(e)
  // 도구가 실행된 후에 실행됨
  $.ui.log(e.tool + ' finished')
  // 결과를 변경하지 않고 반환
  return result
})

이제 줄은 각 도구가 완료된 후에 나타납니다. Claude는 훅이 next(e)가 해결된 것을 반환하기 때문에 어느 쪽이든 같은 결과를 읽습니다.

이벤트 재작성하기

Claude Code가 행동하는 것을 변경하려면, 예를 들어 프롬프트의 텍스트를 변경하려면 수정된 이벤트 복사본으로 next를 호출합니다. 이벤트 자체는 불변입니다: 모든 깊이에서 동결되어 있으며, 필드에 할당하면 오류가 발생합니다. 이 훅은 각 프롬프트를 전송하기 전에 트림합니다:

on('prompt.submit', async ($, e, next) => {
  // 텍스트가 변경된 이벤트의 복사본을 전달
  return next({ ...e, text: e.text.trim() })
})

나중의 핸들러와 Claude Code는 트림된 프롬프트를 받고 원본을 절대 보지 않습니다. 결과를 변경할 수도 있습니다: await next(e)를 한 후 필드가 바뀐 결과의 복사본을 반환합니다.

이벤트에 응답하기

이벤트를 직접 처리하려면 next를 호출하지 않고 결과를 반환합니다. 이는 체인을 단락시키므로 나중의 모드와 Claude Code의 자신의 동작이 실행되지 않습니다. 이 훅은 모든 Bash 명령을 거부합니다:

on('tool.call', { tool: 'Bash' }, async () => {
  // next를 호출하지 않으므로 명령이 실행되지 않음
  return { deny: 'Bash is turned off in this project. Use the file tools.' }
})

Claude가 Bash 명령을 시도할 때 명령이 실행되지 않으며, Claude는 deny 텍스트를 도구의 결과로 읽습니다. 각 이벤트는 자신의 결과 형태를 가지고 있으며, 이벤트 참조에 나열되어 있습니다.

훅이 처리하는 이벤트 필터링하기

훅을 일부 이벤트에만 실행하려면 on의 두 번째 인수로 필터를 전달합니다. Claude Code는 필터를 매처라고 부릅니다. 이는 필드가 이벤트의 필드와 비교되는 객체이며, 모든 필드가 일치할 때만 훅이 실행됩니다. 필드는 값, 허용된 값의 배열, 또는 정규 표현식일 수 있습니다.

이 예제의 각 줄은 같은 함수 hook을 더 좁은 도구 호출 집합에 등록합니다:

// 문자열은 하나의 값과 일치: Bash 호출만
on('tool.call', { tool: 'Bash' }, hook)
// 배열은 그 안의 모든 값과 일치: Edit 호출과 Write 호출
on('tool.call', { tool: ['Edit', 'Write'] }, hook)
// 정규 표현식은 패턴으로 일치: 하나의 MCP 서버의 모든 도구
on('tool.call', { tool: /^mcp__github__/ }, hook)

hook은 Bash, Edit, 또는 Write 호출에 대해 한 번씩 실행되며, 이름이 mcp__github__로 시작하는 도구에 대한 호출에 대해 한 번씩 실행됩니다. Read와 같은 다른 도구에 대한 호출은 세 가지 중 어느 것도 일치하지 않으므로 hook은 그것에 대해 실행되지 않습니다.

이벤트 이름은 와일드카드일 수 있습니다. 'classic.*'는 모든 설정 훅 이벤트와 일치합니다. '*'는 텔레메트리 이벤트를 제외한 모든 이벤트와 일치하며, 이는 이름으로 또는 'telemetry.*'로 훅합니다.

각 이벤트를 매처당 한 번씩 등록합니다. 매처 없이 session.start에 대해 on을 두 번 호출하면 모듈이 on("session.start") is registered twice without a matcher로 로드되지 않습니다. 모드가 세션 시작 시 수행하는 모든 것을 하나의 훅에 넣으세요.

Claude가 하는 일을 훅하기

이 이벤트들을 훅하여 도구 호출, 프롬프트, 또는 턴이 발생할 때 보거나 변경합니다. 모든 이벤트와 훅이 반환할 수 있는 것은 이벤트 참조를 보세요.

도구 호출 보호 또는 변경하기

tool.call 훅은 Claude가 사용하려고 하는 각 도구를 보므로 호출을 거부하거나, 인수를 변경하거나, 통과시킬 수 있습니다. tool.call은 Claude Code가 도구를 실행하려고 할 때 발생하며, 서브에이전트가 만드는 호출과 MCP 도구에 대한 호출을 포함합니다. e.tool은 도구의 이름이고 도구의 인수는 e의 필드입니다. 예를 들어 Bash의 경우 e.command입니다. next(e)를 호출하면 Claude Code는 권한 확인을 실행한 후 도구를 실행합니다.

이 훅은 강제 푸시하는 Bash 명령을 거부하고 Claude에게 이유를 알립니다:

// 매처는 훅을 Bash 호출로 제한하므로 e.command는 셸 명령
on('tool.call', { tool: 'Bash' }, async ($, e, next) => {
  if (/git push .*--force/.test(e.command)) {
    // next를 호출하지 않고 반환하면 이벤트에 응답하므로 명령이 실행되지 않음
    return { deny: 'Force pushes are not allowed in this repository. Push to a new branch instead.' }
  }
  // 다른 모든 명령은 권한 확인을 거쳐 Bash로 진행
  return next(e)
})

Claude가 git push --force를 시도할 때 명령이 실행되지 않으며 훅이 next를 호출하지 않기 때문에 권한 프롬프트가 나타나지 않습니다. Claude는 deny 텍스트를 도구의 결과로 읽으므로 Claude가 행동할 수 있는 지시로 작성하세요. 다른 모든 Bash 명령은 모드 없이 실행되는 것처럼 실행됩니다.

도구가 실행된 후에 행동하려면 await next(e)를 하고, 작업을 수행한 후 next가 준 것을 반환합니다. 이 훅은 Claude가 변경하는 각 .mdx 파일을 $.ui.log로 기록하며, 이는 Claude가 읽지 않는 흐릿한 줄을 트랜스크립트에 추가합니다:

on('tool.call', { tool: ['Edit', 'Write'] }, async ($, e, next) => {
  // 권한 확인과 도구를 기다리고 그들이 생산한 것을 유지
  const result = await next(e)
  // 거부된 호출은 { deny }로 돌아오고, 실패한 것은 isError가 설정됨
  const changed = !result.deny && !result.isError
  if (changed && e.file_path.endsWith('.mdx')) $.ui.log('Claude changed ' + e.file_path)
  // 결과를 받은 대로 반환하므로 Claude는 도구가 반환한 것을 읽음
  return result
})

Claude가 .mdx 파일을 편집하거나 쓴 후 트랜스크립트의 흐릿한 줄이 파일의 이름을 지정합니다. 다른 종류의 파일이나 거부되거나 실패한 호출에 대해서는 아무것도 기록되지 않습니다. 훅이 받은 결과를 반환하기 때문에 호출에 대한 Claude의 보기는 변경되지 않습니다.

호출을 변경하려면 변경된 인수를 next에 전달합니다. 호출을 다시 시도하려면 next(e)를 다시 호출합니다: 첫 번째 결과에서 isError를 보는 훅은 도구를 두 번째로 실행하고 그 결과를 반환할 수 있습니다. 호출에 직접 응답하려면 next를 호출하지 않고 result 필드가 있는 객체를 반환합니다. 예를 들어 { result: 'Skipped by my-mod' }입니다. 그렇게 하면 권한 프롬프트가 나타나지 않으며 도구가 실행되지 않으므로 반환하는 결과가 Claude가 무슨 일이 일어났는지에 대해 배우는 모든 것입니다.

조직의 관리 설정의 훅은 모든 모드의 tool.call 훅 전에 실행되며, 그 중 하나의 블록은 최종입니다.

사용자가 결정할 때까지 도구 호출 보류하기

훅은 도구 호출을 일시 중지하고 진행하기 전에 사용자에게 무엇을 할지 물어볼 수 있습니다. tool.call 훅은 next를 호출하거나 반환하기 전에 await할 수 있으며, 도구 호출은 그때까지 보류됩니다. 사용자에게 질문을 하려면 $.ui.ask를 호출합니다. 이는 Claude가 당신에게 무언가를 물어보는 데 사용하는 대화 상자에서 번호가 매겨진 옵션 목록 위에 질문을 표시하고 사용자가 선택한 레이블로 해결됩니다. 옵션 후에 대화 상자는 다른 답변을 입력하기 위한 행과 Chat about this 행을 추가합니다.

이 예제의 RISKY 패턴은 rm -r, rm -rf, git reset --hard, 그리고 --force가 있는 git push와 일치하며, git push -f와 같은 다른 철자는 놓칩니다. 이 모듈은 패턴과 일치하는 Bash 명령을 실행하기 전에 물어봅니다:

const RISKY = /\brm\s+-rf?\b|\bgit\s+reset\s+--hard\b|\bgit\s+push\b.*--force/

export function register(on) {
  on('tool.call', { tool: 'Bash' }, async ($, e, next) => {
    // 질문 없이 다른 모든 명령을 통과시킴
    if (!RISKY.test(e.command)) return next(e)
    // 안전한 답변에서 시작하므로 아무도 답변하지 않는 질문은 명령을 거부
    let answer = 'Refuse'
    try {
      // 도구 호출은 사용자가 두 레이블 중 하나를 선택할 때까지 여기서 기다림
      answer = await $.ui.ask('Run this command? ' + e.command, ['Run it', 'Refuse'])
    } catch {
      // 사용자가 질문을 해제했거나 이것이 아무도 물어볼 사람이 없는 claude -p 실행
    }
    if (answer !== 'Run it') {
      // next를 호출하지 않고 응답하므로 명령이 실행되지 않음
      return { deny: 'The user declined this command. Ask before trying a different approach.' }
    }
    return next(e)
  })
}

Claude가 rm -rf build와 같은 명령을 시도할 때 질문이 명령과 함께 나타나고 명령은 답변을 기다립니다:

  • 사용자가 Run it을 선택: 훅이 next(e)를 호출하고 일반적인 권한 확인이 여전히 그 후에 실행됩니다
  • 사용자가 Refuse를 선택: 명령이 실행되지 않으며 Claude는 deny 텍스트를 읽습니다
  • 사용자가 답변을 입력: $.ui.ask는 입력된 텍스트로 해결됩니다. 훅은 Run it과 비교하므로 다른 텍스트는 명령을 거부합니다.
  • 아무도 답변하지 않음: $.ui.ask는 사용자가 질문을 해제하거나 Chat about this를 선택할 때 또는 claude -p 실행에서 거부하므로 catch 블록은 답변을 Refuse로 유지합니다

$.ui.ask와 같은 mods API 호출 내에서 대기를 유지하세요. 이 시간은 훅의 10초 시간 제한에 포함되지 않기 때문입니다. 자신의 약속을 기다리는 데 소비된 시간은 포함됩니다. Claude Code는 시간 초과된 훅을 건너뛰므로 보류된 명령이 실행됩니다.

프롬프트 재작성 또는 추가하기

prompt.submit 훅은 턴이 시작되기 전에 각 프롬프트를 보므로 텍스트를 재작성하거나 추가할 수 있습니다. e.text는 입력된 것입니다.

이것을 하려면 이것을 반환하세요
프롬프트를 재작성합니다. 트랜스크립트의 메시지는 새 텍스트를 표시합니다. next({ ...e, text: newText })
Claude만 읽는 텍스트를 프롬프트 후에 추가합니다 next({ ...e, context: [...(e.context ?? []), extraText] })
프롬프트가 전송되지 않도록 중지합니다 { drop: 'the reason' }

이 훅은 프롬프트가 풀 요청을 언급할 때마다 현재 브랜치 이름을 Claude에게 추가합니다:

on('prompt.submit', async ($, e, next) => {
  // 풀 요청을 언급하지 않는 프롬프트를 그대로 전달
  if (!/\bPR\b|pull request/i.test(e.text)) return next(e)
  const git = await $.process.run(['git', 'branch', '--show-current'])
  // git 저장소 외부에서 명령이 실패하므로 추가할 브랜치가 없음
  if (git.exitCode !== 0) return next(e)
  // 이전 훅이 추가한 모든 컨텍스트를 유지하고 Claude를 위해 하나 더 추가
  return next({ ...e, context: [...(e.context ?? []), 'Current branch: ' + git.stdout.trim()] })
})

open a PR for this change와 같은 프롬프트를 보낼 때 메시지는 트랜스크립트에서 동일하게 보이며, Claude는 Current branch: feature/auth와 같은 줄도 그 후에 읽습니다. 풀 요청을 언급하지 않는 프롬프트는 변경되지 않고 통과하며 git은 실행되지 않습니다.

다른 이벤트는 Claude가 읽는 나머지를 다룹니다: 시스템 프롬프트의 각 섹션에 대한 prompt.section, 첫 번째 메시지와 함께 전송되는 컨텍스트에 대한 prompt.context, 그리고 스킬의 텍스트에 대한 skill.prompt. 이 훅의 텍스트가 요청 간에 변경되면 프롬프트 캐시를 무효화합니다.

턴 따라가기

턴은 Claude가 하나의 프롬프트에 응답하여 수행하는 모든 것입니다. turn.start, turn.step, 그리고 turn.complete를 훅하여 하나를 따라가세요:

이벤트 언제 발생하는가 훅이 할 수 있는 것
turn.start 턴이 시작됩니다 관찰합니다. e.turnId는 다른 두 이벤트에서 턴을 식별합니다.
turn.step Claude Code가 모델에 하나의 요청을 보내려고 합니다. 도구 호출이 있는 턴은 여러 개를 가집니다. e.agentId는 서브에이전트의 요청에 대해 설정됩니다. 각 요청의 토큰 사용량을 읽고, next({ ...e, model })로 다른 모델에 보내거나, 모델을 호출하지 않고 응답합니다
turn.complete 턴이 끝났으며, 사용자가 중단한 턴을 포함하며, 여기서 e.isAborted는 true입니다. e.answer는 Claude의 최종 텍스트이고, e.durationMs는 소요된 시간이며, e.usage는 턴의 토큰 합계입니다. 서브에이전트의 턴은 e.agentId가 설정된 상태로 발생합니다. 관찰하거나, { text: 'Done in 12 seconds' }와 같은 text 필드가 있는 객체를 반환하여 답변 아래에 줄을 표시합니다

turn.step 훅을 비동기 생성기로 작성하세요. 이벤트가 스트림되기 때문입니다. yield* next(e)는 응답을 스트림할 때 전달하고 완료된 결과로 평가됩니다. 이 훅은 각 요청에서 Claude API가 프롬프트 캐시에서 제공한 양을 기록합니다:

// function*는 훅을 생성기로 만들어 응답을 조각별로 전달할 수 있음
on('turn.step', async function* ($, e, next) {
  // 요청을 보내고, 각 조각이 도착할 때 전달하고, 완료된 결과를 유지
  const result = yield* next(e)
  // 토큰 개수를 보고하지 않는 결과를 건너뜀
  if (result.usage) {
    $.ui.log('cache read ' + result.usage.cache_read_input_tokens + ' · wrote ' + result.usage.cache_creation_input_tokens)
  }
  // 결과를 변경하지 않고 반환하므로 턴이 평소대로 계속됨
  return result
})

Claude의 응답은 모드 없이 하는 것처럼 화면으로 스트림됩니다. 각 요청이 완료된 후 트랜스크립트의 흐릿한 줄이 캐시에서 읽은 토큰 수와 쓴 토큰 수를 제공합니다. 도구 호출이 있는 턴은 여러 요청을 가지므로 여러 줄을 추가합니다.

result.usage는 Claude API가 요청에 대해 보고하는 네 가지 토큰 개수와 응답한 model을 보유합니다: input_tokens, output_tokens, cache_read_input_tokens, 그리고 cache_creation_input_tokens. 훅은 서브에이전트의 요청에 대해서도 실행되므로 주 대화만 원할 때 e.agentId를 확인하세요.

설정 훅 이벤트 훅하기

설정 훅은 설정 파일에서 구성하는 명령, HTTP, 프롬프트, 그리고 에이전트 훅입니다. 각 설정 훅 이벤트, 예를 들어 Stop, SessionEnd, 또는 PostToolUse는 또한 classic. 다음에 설정 훅 이벤트의 이름이 오는 이벤트입니다. 예를 들어 classic.Stop. e는 설정 훅이 stdin에서 받는 JSON이며, transcript_path를 포함합니다.

이 훅은 Claude가 응답을 마칠 때 발생하는 Stop을 사용하여 세션의 트랜스크립트가 저장되는 위치를 기록합니다:

on('classic.Stop', async ($, e, next) => {
  // e는 설정 파일의 Stop 훅이 stdin에서 읽는 것과 같은 필드를 가짐
  $.ui.log('Transcript saved at ' + e.transcript_path)
  // 이벤트를 전달하므로 설정 파일의 Stop 훅이 여전히 실행됨
  return next(e)
})

Claude가 응답을 마칠 때마다 트랜스크립트의 흐릿한 줄이 트랜스크립트 파일의 경로를 제공합니다. 훅은 next(e)를 반환하므로 이벤트를 관찰하고 턴이 끝나는 방식에 대해 아무것도 변경하지 않습니다.

다른 모드와 함께 실행

여러 모드가 동일한 이벤트를 후킹할 수 있으며, 그 중 하나가 실패할 수 있습니다. 모드가 도구 호출을 차단하는 경우, 체인에서의 위치와 후크가 실패할 때 발생하는 상황을 확인하십시오.

모드가 실행되는 순서

동일한 이벤트의 후킹은 하나의 미들웨어 체인을 형성합니다. 각 모드의 next는 다음 모드의 후크를 호출하고, 마지막 next는 Claude Code의 자체 동작에 도달합니다. 첫 번째 모드는 가장 바깥쪽입니다. 즉, 다른 모드보다 먼저 이벤트를 보고 그 후에 결과를 보며, 다른 모드가 실행될지 여부를 결정합니다. 나중의 모드는 이전 모드가 이벤트를 보는 것을 막을 수 없습니다.

Claude Code는 각 모드의 출처에 따라 체인을 정렬합니다.

  1. 내장 가드 sec-default@builtin은 Claude Code에 내장된 모드로, /plugin에서 cc-plugin-sec-default로 나열되며, 여기서 로드되고, 조직이 prependPlugins에 나열한 모드, 그리고 조직의 것으로 간주되며 appendPlugins에 없는 다른 모드
  2. 설치한 모드
  3. 조직이 appendPlugins에 나열한 모드
  4. Claude Code에 내장된 다른 모드

설치한 모드 중에서, 모드는 매니페스트의 dependencies 아래에 나열한 모드보다 먼저 실행됩니다. 하나의 모듈 내에서, 후킹은 register가 on을 호출한 순서대로 실행됩니다.

설정 후킹이 순서대로 실행되는 위치

설정 파일에서 구성된 PreToolUse 후킹도 도구 호출 중에 실행되며, 모드 체인의 고정된 지점에서 실행됩니다.

  • 관리되는 설정의 PreToolUse 후킹: 첫 번째 모드의 tool.call 후킹 전에 실행되며, 그 중 하나의 차단은 최종적이므로 모드가 호출을 보지 못합니다.
  • 다른 모든 설정 파일 및 플러그인의 hooks/hooks.json의 PreToolUse 후킹: 마지막 모드가 next를 호출한 후, Claude Code의 자체 동작의 일부로 실행됩니다. next를 호출하지 않고 tool.call에 응답하는 모드는 이들이 실행되는 것을 방지하고, next를 호출하는 모드는 반환하는 결과에서 이들의 결정을 봅니다.

tool.check는 Claude Code가 도구 호출 실행 여부를 결정하는 이벤트입니다. 이는 해당 후킹과 권한 규칙이 결정한 후에 발생하며, next(e)는 해당 결정으로 해석됩니다. tool.check의 후킹은 { decision: 'allow' }와 같은 다른 결정을 반환할 수 있으므로, 두 번째 그룹의 후킹이 차단한 호출을 승인할 수 있습니다. 후킹으로 권한 확장은 어떤 결정이 모드보다 우선하는지 나열합니다.

실패한 후킹 처리

실패한 후킹은 세션을 중단하지 않으며, 대신 발생하는 상황을 결정할 수 있습니다. .catch 핸들러가 없는 후킹이 throw되거나, 시간 초과되거나, 잘못된 형태의 결과를 반환할 때, 다음에 발생하는 상황은 next를 호출했는지 여부에 따라 달라집니다.

  • next를 호출하기 전에 실패함: Claude Code는 이를 건너뛰고, 다음 핸들러가 그 자리에서 실행됩니다.
  • next가 해석된 후에 실패함: 해당 결과가 유지되고, 아무것도 두 번 실행되지 않습니다.

한 줄은 모드, 이벤트, 그리고 이유를 이름 지으며, 예를 들어 my-mod: tool.call hook skipped: threw Error: boom입니다. 이를 읽는 위치는 세션에 따라 달라지며, 모드가 아무것도 하지 않는 이유 알아내기에 나열되어 있습니다. 그리기가 유효성 검사를 통과하지 못하는 ui.render 후킹은 요소에서 트리 구축에서 설명하는 대로 다르게 보고됩니다.

호출을 차단하는 후킹이 실패하도록 닫히게 하려면, 그 자리에 응답하는 .catch 오류 핸들러를 추가하십시오. 여기서 guard는 후킹 함수입니다.

// on은 등록을 반환하고, .catch는 해당 하나의 후킹에 핸들러를 첨부합니다.
on('tool.call', { tool: 'Bash' }, guard).catch(async ($, e, next) => {
  // next.error.kind는 'throw' 또는 'timeout'이며, guard가 어떻게 실패했는지를 나타냅니다.
  return { deny: 'The command guard failed, so this command was not run: ' + next.error.kind }
})

guard가 작동하는 동안, 핸들러는 실행되지 않습니다. guard가 Bash 호출에서 throw되거나 시간 초과될 때, Claude Code는 동일한 이벤트로 핸들러를 호출합니다. 핸들러는 { deny }를 반환하므로, 명령이 실행되지 않으며, Claude는 끝에 throw 또는 timeout이 있는 텍스트를 읽습니다. 핸들러가 없으면, Claude Code는 guard를 건너뛰고 명령을 실행합니다. 핸들러는 1초 내에 응답해야 합니다.

다음 단계

  • mods API 사용: 명령과 도구를 추가하고, 모델을 호출하고, 타이머에서 작업을 실행합니다
  • 인터페이스에 그리기: 훅이 수집한 것을 창이나 프롬프트 위에 표시합니다
  • 모드 테스트: 테스트에서 이 이벤트 중 하나를 발생시킵니다
  • Mods 참조: 모든 이벤트, 모든 mods API 메서드, 그리고 제한