Claude Code Hooks·Skills·슬래시 명령어 차이와 사용 예제
반복할 작업 절차는 스킬에 담고, 직접 시작하려면 /스킬이름으로 호출합니다. 특정 도구 실행 전후에 검사를 붙이려면 훅을 씁니다. 커스텀 명령어와 스킬의 통합부터 호출 제어, 권한의 범위, 작은 예제의 성공 판단까지 확인할 수 있습니다.
목차

Claude Code에서 반복할 방법을 저장하려면 Skills, 특정 이벤트가 발생할 때 검사를 실행하려면 Hooks를 선택합니다. 슬래시 명령어는 그 작업을 호출하는 입력 방식입니다. 따라서 스킬을 만들고 /review-note로 직접 실행하는 것은 자연스러운 조합입니다. “명령어는 수동, 스킬은 자동, 훅은 정확한 판단”이라는 구분만으로는 현재 동작을 설명할 수 없습니다.
2026년 10월 4일 확인한 공식 Skills 문서에 따르면, 커스텀 명령어는 스킬로 통합되었습니다. 예전 .claude/commands/review-note.md와 .claude/skills/review-note/SKILL.md는 모두 /review-note를 만들며 같은 방식으로 동작합니다. 기존 명령 파일을 모두 옮길 필요는 없습니다. 새 작업에 참고 문서나 스크립트가 필요해졌다면 스킬 디렉터리로 묶는 편이 관리하기 좋습니다.
지금 하려는 작업으로 고르기
| 하고 싶은 일 | 먼저 선택할 것 | 시작과 성공 판단 |
|---|---|---|
| 모델을 바꾸거나 세션 상태를 확인하기 | 해당 내장 명령어 | /help에서 현재 환경의 명령을 확인하고, 명령이 바꾸는 상태를 확인합니다. |
| 같은 기준으로 코드 설명이나 검토를 반복하기 | 사용자 정의 스킬 | 기본값은 직접 호출과 Claude의 자동 호출을 모두 허용합니다. 결과가 저장한 기준을 따르는지 봅니다. |
| 내가 원할 때만 검토나 배포 준비를 시작하기 | 수동 호출 스킬 | disable-model-invocation: true를 지정하고 /이름으로 시작합니다. 실제 쓰기·배포 권한은 따로 관리합니다. |
Edit나 Write 직전에 특정 파일 경로를 검사하기 | PreToolUse 훅 | 도구 호출 전에 이벤트 입력을 검사합니다. 차단 여부는 그 이벤트의 출력 규칙으로 결정됩니다. |
| 파일 수정 뒤 포맷 검사나 기록을 실행하기 | PostToolUse 훅 | 도구가 실행된 뒤 검사합니다. 검사 실패가 이미 끝난 편집을 되돌려 주지는 않습니다. |
스킬은 실행 파일 자체가 아니라 Claude에게 전달할 지침과 자료를 묶은 패키지입니다. 훅은 이벤트에 연결한 처리기를 실행합니다. 훅 처리기가 셸 스크립트라면 규칙을 코드로 검사할 수 있고, 모델 기반이라면 모델의 판단이 개입합니다. 어떤 방식을 쓰든 “검사를 실행했다”와 “검사가 충분하다”는 별개의 문제입니다. 훅 동작 설명

그림은 호출 방식과 저장 위치를 이해하는 보조 자료입니다. 현재 호출·권한·처리기 종류는 아래 설정 설명을 기준으로 확인하세요.
/help와 /claude-api는 같은 종류의 명령인가요?
둘 다 /로 시작하지만 내부 동작은 다릅니다. 대부분의 내장 명령어는 CLI에 구현된 고정 로직을 실행합니다. 반면 /claude-api, /code-review, /debug 같은 번들 스킬은 Claude에게 작업 지침을 전달하고 도구를 이용해 수행하도록 합니다. 슬래시로 입력한다고 해서 모두 모델 호출이나 토큰 사용이 없는 명령은 아닙니다. 공식 명령어 목록
Claude API나 Managed Agents 관련 개발을 시작할 때 쓰는 번들 스킬은 /claude-api입니다. 다음과 같이 Claude Code의 대화 입력란에서 호출합니다.
/claude-api기존 API 코드의 모델 전환 작업에는 /claude-api migrate 같은 하위 명령도 있습니다. 코드가 anthropic 또는 @anthropic-ai/sdk를 가져오는 경우 자동 활성화될 수 있습니다. 이는 API 키를 발급하거나 외부 접근 권한을 자동으로 주는 기능은 아닙니다. 번들 기능과 하위 명령의 제공 범위는 버전·플랫폼·환경에 따라 달라지므로 /help와 /skills에서 현재 목록을 확인하세요. Claude API 프로젝트용 스킬
직접 호출할 스킬을 하나 만들어 보기
가장 작은 시작점은 파일을 고치지 않고 검토 의견만 받는 스킬입니다. 아래는 설치·인증을 마친 Claude Code CLI에서 프로젝트 파일을 읽을 수 있는 환경을 전제로 한 작성 예제입니다. Claude Code 대화 입력과 일반 터미널 명령을 구분하세요. 여기서는 실제 Claude 호출 결과를 제공하지 않습니다.
프로젝트 안에 다음 두 파일을 준비합니다. 파일은 편집기로 작성해도 됩니다. 진입 파일 이름은 정확히 SKILL.md여야 합니다.
.claude/skills/review-note/SKILL.md
src/example.pysrc/example.py의 예제 내용입니다. 실행하지 않고 읽기만 해도 검토할 수 있습니다.
def average(values):
return sum(values) / len(values)SKILL.md에는 YAML 설정을 먼저 쓰고 그 뒤에 작업 지침을 둡니다.
---
name: review-note
description: 지정한 파일을 읽고 재현 가능한 문제와 확인 방법을 검토합니다.
argument-hint: "[파일 경로]"
disable-model-invocation: true
---
검토 대상은 $ARGUMENTS입니다.
파일 경로가 없으면 경로를 요청하고, 파일을 찾지 못하면 그 사실을 알립니다.
대상 파일을 읽고 호출자나 테스트가 필요하면 관련 파일을 확인합니다.
파일을 수정하거나 명령을 실행하거나 외부 서비스에 접근하지 마세요.
문제가 있으면 다음을 설명합니다.
- 문제가 발생하는 입력이나 조건
- 해당 코드 위치와 예상되는 결과
- 확인할 수 있는 테스트 입력
문제가 확인되지 않으면 그렇게 말하고, 확인하지 못한 조건을 구분합니다.
실행하지 않은 테스트가 통과했다고 말하지 마세요.이제 프로젝트에서 연 Claude Code 세션의 대화 입력란에 다음을 입력합니다.
/review-note src/example.py$ARGUMENTS는 명령 이름 뒤의 문자열로 치환됩니다. 이 경우 대상은 src/example.py입니다. 성공 판단은 “스킬 이름이 보인다”에서 끝나지 않습니다. 대상 파일을 근거로 검토하는지, 수정 없이 의견을 주는지, 실행하지 않은 검증을 구분하는지 확인합니다. 위 함수라면 빈 목록에서 len(values)가 0이 되는 조건을 설명할 수 있습니다. 실제 응답 문장이나 발견하는 문제 수는 보장되지 않습니다. 스킬 시작 방법, 인수 전달
검토 기준이 길어지면 같은 디렉터리에 reference.md나 examples.md를 두고 SKILL.md에서 언제 읽을지 안내하면 됩니다. 스크립트를 넣는다면 필요한 런타임, 입력 인수, 출력, 실패 처리도 함께 적으세요. 보조 파일이 있다는 이유만으로 자동 실행되는 것은 아닙니다.
자동 호출을 허용하려면 무엇을 바꾸나요?
기본 설정에서는 사용자와 Claude가 모두 스킬을 호출할 수 있습니다. 위 예제에서 disable-model-invocation: true를 제거하면 Claude도 설명을 보고 관련 작업에 스킬을 불러올 수 있습니다. 다만 특정 요청마다 반드시 자동 호출된다는 뜻은 아닙니다.
| 설정 | 사용자의 /이름 호출 | Claude의 자동 호출 |
|---|---|---|
| 두 제어 필드 생략 | 가능 | 가능 |
disable-model-invocation: true | 가능 | 불가. 모델용 목록에 설명도 포함되지 않습니다. |
user-invocable: false | 불가. 메뉴에서 숨겨지고 직접 입력해도 실행되지 않습니다. | 가능 |
user-invocable: false는 메뉴만 숨기는 옵션이 아닙니다. 반대로 배포·게시처럼 시작 시점을 통제하려는 작업에는 disable-model-invocation: true가 맞습니다. 이 옵션은 호출 주체를 정할 뿐, 이후 모든 단계의 권한이나 결과를 승인하지는 않습니다. 호출 주체 제어
allowed-tools: Read면 읽기만 가능한가요?
아닙니다. 현재 Claude Code에서 allowed-tools는 그 스킬을 호출한 턴에 나열된 도구를 사전 승인하는 필드입니다. 다른 도구를 없애지 않습니다. 나열되지 않은 도구는 기존 권한 설정에 따라 사용할 수 있습니다. 따라서 위 예제는 allowed-tools를 추가하지 않았으며, “수정하지 말라”는 지침과 런타임에서 쓰기를 막는 권한 규칙을 구분해야 합니다.
도구를 활성 목록에서 제외하는 필드는 disallowed-tools입니다. 이 제한과 allowed-tools의 승인 모두 다음 사용자 메시지가 오면 해제됩니다. 전체 대화에 지속할 제한은 권한 설정의 deny 규칙으로 관리해야 합니다. 스킬 본문은 대화에 남아 이후 턴에도 영향을 줄 수 있지만, 도구 승인 수명은 그와 다릅니다. 스킬 도구 승인, 본문의 수명
조직이 allowManagedPermissionRulesOnly를 설정한 경우에는 해당 출처의 스킬에 있는 allowed-tools가 무시될 수 있습니다. 이 동작은 Claude Code v2.1.282 이상에 해당합니다. 예제가 기대대로 사전 승인되지 않는다면 조직 정책과 버전을 확인해야 하며, 정책을 우회해 해결할 문제는 아닙니다. 관리형 권한 정책의 적용
Hooks는 이벤트·조건·처리기를 연결합니다
훅 설정에서는 먼저 이벤트를 고르고, matcher로 해당 이벤트에서 검사할 대상을 좁힌 뒤, hooks 배열에 처리기를 넣습니다. 예를 들어 PreToolUse는 도구 사용 직전, Edit|Write는 도구 이름에 대한 정규식, command 처리기는 로컬 프로그램 실행을 뜻합니다. matcher가 모든 이벤트에서 파일 경로를 검사하는 필드는 아닙니다. 입력 구조와 매칭 대상은 이벤트마다 다릅니다. 공식 Hooks 참조
현재 처리기 종류는 다섯 가지입니다.
type | 처리 방식 | 선택할 때 확인할 점 |
|---|---|---|
command | 셸 명령 또는 프로그램 실행 | 설치된 런타임, 경로, 표준 입력과 종료 코드 |
http | 이벤트 데이터를 HTTP POST로 전송 | 전송할 데이터, 서버 접근 권한, 응답 형식 |
mcp_tool | 설정된 MCP 서버의 도구 호출 | 서버와 도구가 실제로 구성되어 있는지, 쓰기 등 부작용 |
prompt | 한 번의 모델 호출로 판단 | 입력만으로 판단 가능한지, 비용·지연·판단 변동 |
agent | 도구를 쓰는 여러 턴의 검증 | 필요한 조사 범위와 비용. 현재 실험적 기능입니다. |
이벤트가 설정에 따라 발생한다는 것과 처리 결과가 결정적이라는 것은 다릅니다. prompt·agent 훅에는 모델의 판단이 개입합니다. 코드 검토나 완료 판단을 훅에 넣는 것 자체가 금지된 것은 아니지만, 같은 입력에 언제나 같은 판단을 내린다고 보장할 수는 없습니다. 또한 모든 처리기를 모든 이벤트에 사용할 수 있는 것은 아닙니다. 사용할 조합은 이벤트별 참조에서 확인해야 합니다. 훅 처리기 종류, 모델 기반 훅
PreToolUse로 파일 편집 전 검사하기
다음 예제는 Edit와 Write가 프로젝트의 docs/policy.md를 대상으로 할 때 그 호출을 거부합니다. 다른 파일을 편집하는 경우에는 아무 결정도 내리지 않습니다. macOS·Linux·WSL의 셸과 Python 3를 전제로 하며 추가 Python 패키지는 필요 없습니다. 스크립트는 이벤트 입력만 읽고 파일을 수정하지 않습니다.
먼저 프로젝트 루트에 scripts/guard-policy.py를 저장합니다.
import json
import sys
from pathlib import Path
def main():
if len(sys.argv) != 2:
print("프로젝트 루트 인수가 필요합니다.", file=sys.stderr)
return 1
try:
data = json.load(sys.stdin)
if not isinstance(data, dict):
raise ValueError("이벤트 입력은 JSON 객체여야 합니다.")
if data.get("hook_event_name") != "PreToolUse":
return 0
if data.get("tool_name") not in ("Edit", "Write"):
return 0
tool_input = data.get("tool_input")
if not isinstance(tool_input, dict):
raise ValueError("tool_input 객체가 필요합니다.")
file_path = tool_input.get("file_path")
if not isinstance(file_path, str) or not file_path:
raise ValueError("file_path 문자열이 필요합니다.")
root = Path(sys.argv[1]).resolve()
cwd = data.get("cwd", str(root))
if not isinstance(cwd, str):
raise ValueError("cwd는 문자열이어야 합니다.")
target = Path(file_path)
if not target.is_absolute():
target = Path(cwd) / target
if target.resolve() == (root / "docs" / "policy.md").resolve():
print("docs/policy.md 편집은 담당자의 확인이 필요합니다.",
file=sys.stderr)
return 2
return 0
except (ValueError, OSError, RuntimeError) as error:
print(f"입력 검사 실패: {error}", file=sys.stderr)
return 1
if __name__ == "__main__":
sys.exit(main())설정에 넣기 전에 프로젝트 루트의 일반 터미널에서 합성 입력으로 분기를 확인할 수 있습니다. 이 명령은 실제 편집을 요청하지 않습니다.
printf '%s\n' '{"hook_event_name":"PreToolUse","tool_name":"Edit","tool_input":{"file_path":"docs/policy.md"}}' |
python3 scripts/guard-policy.py "$PWD"
echo "$?"이 입력에서는 표준 오류에 이유가 출력되고 종료 코드 2가 나와야 합니다. file_path를 docs/notes.md로 바꾸면 출력 없이 0이 나와야 합니다. 여기서는 입력 JSON, 상대 경로 처리, 출력과 종료 코드의 연결을 확인하는 것입니다. Claude Code가 이벤트를 실제로 발생시켰는지는 별도로 확인해야 합니다.
프로젝트에 연결할 때는 기존 .claude/settings.json의 다른 설정과 훅을 보존하면서 아래 PreToolUse 항목을 병합합니다. 이 JSON은 새 설정 파일일 때의 최소 예제이며, 기존 파일 전체를 덮어쓰라는 뜻이 아닙니다.
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "python3 \"$CLAUDE_PROJECT_DIR/scripts/guard-policy.py\" \"$CLAUDE_PROJECT_DIR\""
}
]
}
]
}
}CLAUDE_PROJECT_DIR는 Claude Code가 전달하는 프로젝트 루트입니다. 훅이 다른 현재 디렉터리에서 실행되어도 스크립트 위치를 찾을 수 있게 경로를 따옴표로 감쌌습니다. 실제로 연결한 환경에서는 /hooks로 PreToolUse 등록과 처리기 경로를 확인하고, 중요 파일 대신 테스트 프로젝트의 파일로 차단을 확인하세요. 설정 파일 변경은 보통 파일 감시 기능이 반영하며, 등록이 갱신되지 않았다면 세션을 재시작해 확인합니다. 개인 전체에 적용할 설정은 ~/.claude/settings.json, 프로젝트의 로컬 설정은 .claude/settings.local.json입니다. 설정 위치
이 예제는 Edit·Write를 통한 한 파일의 편집만 검사합니다. Bash에서 파일을 쓰는 명령, 다른 도구, 외부 프로그램까지 차단하는 보안 경계는 아닙니다. 입력 파싱 오류에서 반환하는 1도 차단 코드가 아닙니다. 더 강한 보호가 필요하면 도구 권한, 파일 시스템 권한, 저장소 검사 등을 함께 설계해야 합니다.
이 글의 로컬 확인에서는 합성 JSON으로 위 스크립트의 보호 경로·일반 경로·잘못된 입력 분기와 설정 JSON 및 스킬 YAML의 문법을 검사했습니다. 실제 Claude Code 이벤트, 도구 차단, 스킬 호출이나 모델 응답을 시험한 결과는 아닙니다.
종료 코드 0, 2, 1은 어떻게 다르나요?
위 예제는 stdout에 구조화된 JSON을 출력하지 않으므로, 다음처럼 해석할 수 있습니다.
PreToolUse에서 반환한 값 | 이 예제의 의미 |
|---|---|
0, 출력 없음 | 훅은 이의를 제기하지 않습니다. 도구 호출을 사전 승인한 것은 아니며 기존 권한 검사가 계속 적용됩니다. |
2와 stderr의 이유 | 해당 도구 호출을 차단하고 Claude에 이유를 전달합니다. |
1과 stderr의 오류 | 입력 검사 오류입니다. 이 출력 방식에서는 비차단 오류로 처리되며 보호 성공으로 볼 수 없습니다. |
이 규칙을 모든 이벤트에 그대로 적용하면 안 됩니다. SessionStart처럼 종료 코드 2로도 이벤트 자체를 막을 수 없는 경우가 있고, PostToolUse는 이미 끝난 동작을 취소하지 못합니다. 유효한 구조화 JSON을 반환하면 종료 코드와의 우선순위가 달라지는 경우도 있으며, WorktreeCreate 같은 이벤트에는 별도 예외가 있습니다. 처음 작성할 때는 예제처럼 하나의 반환 방식을 고르고 사용하려는 이벤트의 규칙을 확인하세요. 종료 코드와 이벤트별 동작
스킬과 훅을 함께 쓸 때 확인할 세 가지 수명

수동 호출 스킬이 배포 준비 절차를 안내하고, 별도 훅이 특정 도구 호출을 검사하는 조합은 가능합니다. 하지만 세 계층을 항상 다 만들 필요는 없습니다. 검토 의견을 정리하는 일은 스킬 하나로 충분할 수 있고, 정해진 파일 경로를 검사하는 일은 스크립트 훅만으로 시작할 수 있습니다.
조합한다면 수명을 구분해야 합니다. 현재 공식 문서에서 스킬 본문은 호출 뒤 대화에 남고, 스킬의 도구 승인은 다음 사용자 메시지 때 해제되며, 스킬 frontmatter의 훅은 호출 시 등록되어 나머지 세션 동안 실행됩니다. 스킬이 한 번 답변했다고 그 훅이 모두 사라지는 것은 아닙니다. 처리기에 once: true를 지정하면 첫 성공 실행 뒤 제거할 수 있습니다. 서브에이전트 frontmatter의 훅은 해당 에이전트가 실행 중일 때만 적용됩니다. 스킬 본문의 수명, 스킬·에이전트의 훅
같은 이벤트에 매칭되는 훅은 병렬로 실행되고 결과를 합칩니다. PreToolUse의 권한 결정은 deny, defer, ask, allow 순으로 더 제한적인 결과가 우선합니다. 한 훅의 거부가 다른 훅의 로그 기록이나 외부 전송을 취소하지는 않습니다. 또한 비동기 훅의 나중 결과로 이미 실행한 도구 동작을 소급 차단할 수 없습니다. 여러 훅의 결과 결합
모델 기반 Stop 훅이 작업 미완료라고 판단하면 Claude가 계속 작업할 수 있습니다. 완료 조건이 만족될 수 있는지, 같은 판단을 반복하지 않도록 어떻게 종료할지 정해야 합니다. “리뷰 품질을 항상 보장한다”는 넓은 기준을 붙이기보다, 확인할 항목과 실패 시 다음 행동을 구체적으로 정하는 편이 좋습니다. 프롬프트 기반 훅
설정이 늘어나기 전에 확인할 것
새 확장에는 시작 조건, 실행하는 일, 실패가 보이는 위치, 제거 방법을 남기세요. 스킬에서는 언제 호출하고 어떤 근거를 읽을지, 훅에서는 어떤 이벤트·도구·입력을 검사하고 무엇을 거부할지 적으면 됩니다. 한 번만 쓸 요청을 반드시 스킬로 만들 필요도 없습니다.
문제가 외부 서비스의 데이터나 도구 접근이라면 스킬 본문을 길게 쓰는 것으로 해결되지 않습니다. Claude Code의 MCP 통합 선택 가이드에서 실제로 필요한 접근부터 구분할 수 있습니다. 이미 제공되는 스킬로 충분한지, 반복되는 팀 절차를 직접 묶어야 하는지 판단하려면 스킬을 추가할 시점과 워크플로 선택을 함께 보세요.
자주 묻는 질문
기존 .claude/commands 파일을 전부 옮겨야 하나요?
아닙니다. 기존 커스텀 명령 파일은 계속 동작합니다. 현재는 스킬과 같은 호출 체계로 통합되어 있으며, 지원 파일을 묶고 호출 설정을 관리할 때 디렉터리형 스킬이 유용합니다. 명령 파일에서는 스킬 frontmatter 필드 중 name·paths를 사용할 수 없다는 차이도 확인하세요. 스킬 파일과 기존 명령 파일
스킬을 직접 호출하면 자동 호출도 막히나요?
아닙니다. 기본값에서는 두 호출 방식이 모두 가능합니다. 자동 호출을 막으려면 disable-model-invocation: true를 지정해야 합니다. 직접 호출을 막는 필드는 user-invocable: false로, 두 필드의 대상이 다릅니다. 호출 제어
훅이 실행되지 않을 때 무엇부터 확인하나요?
/hooks에서 등록 여부와 이벤트를 확인하고, matcher가 도구 이름 등 해당 이벤트의 매칭 대상과 맞는지 보세요. 다음으로 처리기 경로, Python 등 런타임, 입력 필드와 반환 방식을 점검합니다. 합성 입력에서 스크립트가 성공하는 것과 실제 이벤트에 연결되는 것은 서로 다른 확인 단계입니다. 훅 설정과 문제 해결
Hooks가 Skills보다 더 정확한가요?
검사를 실행하는 시점을 설정으로 고정할 수 있다는 장점은 있습니다. 하지만 prompt·agent 훅의 판단에는 모델이 개입하고, command 훅도 작성한 검사 범위 밖의 문제를 자동으로 막지는 못합니다. 반복 방법을 설명할지, 이벤트에서 정해진 검사를 실행할지로 선택해야 합니다. 훅 동작 원리
참고 자료4
이 글이 링크한 외부 페이지를 본문에 나온 순서대로 정리했습니다. 마지막 업데이트: 2026년 10월 5일.
참고 자료4
이 글이 링크한 외부 페이지를 본문에 나온 순서대로 정리했습니다. 마지막 업데이트: 2026년 10월 5일.





