AI 코딩 에이전트를 쓰다 보면 반복되는 패턴이 생긴다.
커밋 메시지를 특정 포맷으로 쓰거나, PR 올리기 전에 린트를 돌리거나, 배포 스크립트를 실행하는 식이다.
Claude Code에는 이런 반복 작업을 자동화하는 두 가지 시스템이 있다.
하나는 스킬(Skills), 다른 하나는 훅(Hooks)이다.
스킬은 “무엇을 할지”를 마크다운 파일로 정의하는 것이고
훅은 “어떤 조건에서 자동으로 개입할지”를 설정 파일로 정의하는 것이다.
복잡한 플러그인 개발 없이 파일 몇 개로 에이전트의 행동을 커스터마이징할 수 있다는 점이 핵심이다.
이 글에서는 두 시스템의 구조, 주요 설정, 그리고 실무 활용 패턴을 정리해본다.

1. Skills이란
스킬은 .claude/skills/ 디렉토리에 SKILL.md 파일로 존재한다.
- YAML 프론트매터 — 이름, 설명, 호출 조건 등 메타데이터
- 마크다운 본문 — Claude가 따르는 실제 지침
예를 들어 커밋 자동화 스킬은 이렇게 생겼다.
---
name: commit
description: 변경 사항을 분석하고 커밋 메시지를 생성합니다
disable-model-invocation: true
---
git diff를 확인하고, 변경 내용을 요약하여
Conventional Commits 형식으로 커밋 메시지를 작성하세요.
name: commit으로 정의하면 /commit이라는 슬래시 커맨드가 자동 생성된다.
터미널에서 /commit만 입력하면 Claude가 diff를 분석하고 커밋을 수행한다.
참고로 Claude Code에는 /batch, /simplify, /debug, /loop, /claude-api 같은 번들 스킬이 기본 탑재되어 있다.
이것들도 내부적으로는 같은 SKILL.md 구조로 되어 있다.
번들 스킬이 빌트인 명령어(/help, /compact 등)와 다른 점은
프롬프트 기반이라 상황에 따라 유연하게 동작한다는 것이다.
2. 스킬 디렉토리 구조
스킬은 단일 SKILL.md 파일만으로도 동작하지만 디렉토리 안에 참조 파일을 함께 둘 수 있다.
my-skill/
├── SKILL.md # 메인 지침 (필수)
├── template.md # Claude가 채울 템플릿
├── examples/
│ └── sample.md # 예시 출력
└── scripts/
└── validate.sh # Claude가 실행할 스크립트
SKILL.md는 500줄 이내로 유지하고 상세한 레퍼런스는 별도 파일로 분리하는 것이 권장된다.
SKILL.md 안에서 참조 파일을 언급해두면 Claude가 필요할 때 읽어들인다.
저장 위치에 따라 적용 범위가 달라진다.
글로벌: ~/.claude/skills/<name>/SKILL.md → 모든 프로젝트
프로젝트: .claude/skills/<name>/SKILL.md → 해당 프로젝트만
플러그인: <plugin>/skills/<name>/SKILL.md → 플러그인 활성화 시
엔터프라이즈: 관리자 설정 → 조직 전체
모노레포 환경이라면 packages/frontend/.claude/skills/ 같은 하위 디렉토리에도 스킬을 둘 수 있다. Claude Code가 해당 디렉토리에서 작업할 때 자동으로 탐색한다.
기존의 .claude/commands/ 디렉토리에 만들어둔 커스텀 명령어가 있다면 그대로 동작한다.
commands와 skills가 통합되었기 때문이다. 같은 이름이 충돌하면 skills가 우선한다.
3. 프론트매터 전체 옵션
스킬의 동작 방식은 프론트매터로 제어한다.
전체 필드를 정리하면 이렇다.
---
name: my-skill
description: 이 스킬의 용도와 언제 쓸지
disable-model-invocation: true
user-invocable: true
allowed-tools: Read, Grep, Glob
argument-hint: [filename] [format]
model: opus
effort: high
context: fork
agent: Explore
---
name — 슬래시 커맨드 이름. 소문자, 숫자, 하이픈만 가능 (최대 64자)
description — 스킬 용도. Claude가 자동 호출 여부를 판단하는 기준
disable-model-invocation — true면 사용자만 /name으로 호출 가능. Claude가 임의 실행 안 함
user-invocable — false면 슬래시 메뉴에서 숨김. Claude만 자동 호출 가능
allowed-tools — 스킬 실행 중 사용 가능한 도구 제한
argument-hint — 자동완성 시 표시되는 인자 힌트
model — 특정 모델로 실행 (opus, sonnet 등)
effort — 추론 강도 (low, medium, high, max)
context — fork으로 설정하면 서브에이전트에서 실행
agent — context: fork 시 사용할 에이전트 타입
hooks — 이 스킬 실행 중에만 적용되는 훅 정의

호출 제어가 중요한 이유
기본적으로 모든 스킬은 사용자와 Claude 양쪽에서 호출 가능하다.
사용자가 /name으로 직접 실행할 수도 있고 Claude가 대화 맥락에서 관련성을 판단해 자동으로 로드할 수도 있다.
문제는 사이드 이펙트가 있는 스킬이다.
배포, 슬랙 메시지 전송, 데이터 삭제 같은 작업을 Claude가 “코드가 준비된 것 같으니 배포하겠습니다”라고 자동 실행하면 곤란하다.
이때 disable-model-invocation: true를 쓴다.
Claude의 컨텍스트에서 완전히 제거되어 자동 트리거가 불가능해진다.
반드시 사용자가 /deploy를 직접 입력해야만 실행된다.
반대로 user-invocable: false는 배경 지식 용도다.
팀의 레거시 시스템 구조나 코딩 컨벤션을 정리해둔 스킬에 쓴다.
사용자가 /legacy-system-context를 실행하는 건 의미가 없지만
Claude가 관련 코드를 수정할 때 자동으로 참조하면 유용하다.
정리하면 이렇다.
기본값: 사용자 호출 O / Claude 호출 O / description 항상 로드
disable-model-invocation: true: 사용자 호출 O / Claude 호출 X / 로드 안 됨
user-invocable: false: 사용자 호출 X / Claude 호출 O / description 항상 로드
4. 인자 전달과 동적 컨텍스트
스킬에 인자를 전달할 수 있다.
$ARGUMENTS 플레이스홀더가 실행 시 실제 값으로 치환된다.
---
name: fix-issue
description: GitHub 이슈를 수정합니다
disable-model-invocation: true
---
GitHub 이슈 $ARGUMENTS를 코딩 스탠다드에 맞춰 수정하세요.
1. 이슈 설명 읽기
2. 요구사항 파악
3. 수정 구현
4. 테스트 작성
5. 커밋 생성
/fix-issue 123을 실행하면 $ARGUMENTS가 123으로 치환된다.
인자가 여러 개면 $ARGUMENTS[0], $ARGUMENTS[1] 또는 축약형 $0, $1으로 접근할 수 있다.
동적 컨텍스트 주입
더 강력한 기능은 !`<command>` 문법이다.
셸 커맨드를 실행하고 그 출력을 스킬 본문에 삽입한다.
Claude가 실행하는 게 아니라 스킬 로드 시 전처리로 실행되는 것이다.
---
name: pr-summary
description: PR 요약을 생성합니다
context: fork
agent: Explore
allowed-tools: Bash(gh *)
---
## PR 컨텍스트
- PR diff: !`gh pr diff`
- PR 코멘트: !`gh pr view --comments`
- 변경 파일: !`gh pr diff --name-only`
## 작업
위 내용을 기반으로 PR을 요약하세요.
스킬이 실행될 때 gh pr diff 등이 먼저 실행되고 그 결과가 Claude에게 전달된다.
Claude는 실제 PR 데이터가 포함된 완성된 프롬프트를 받게 된다.
5. 서브에이전트와의 조합
프론트매터에 context: fork를 설정하면 스킬이 메인 대화와 분리된 서브에이전트에서 실행된다.
서브에이전트는 독립된 컨텍스트를 가지며 중간 과정의 도구 호출은 내부에서만 처리되고
최종 결과만 메인으로 돌아온다.
---
name: deep-research
description: 코드베이스를 심층 조사합니다
context: fork
agent: Explore
---
$ARGUMENTS를 조사하세요:
1. Glob과 Grep으로 관련 파일 탐색
2. 코드 분석
3. 파일 경로를 포함한 결과 요약
agent 필드에는 빌트인 에이전트 타입(Explore, Plan, general-purpose)이나
.claude/agents/에 정의한 커스텀 에이전트를 지정할 수 있다.
생략하면 general-purpose가 기본값이다.
주의할 점은 context: fork는 명확한 작업 지시가 있는 스킬에만 의미가 있다는 것이다.
“이 API 컨벤션을 따르세요” 같은 가이드라인만 있고 구체적인 태스크가 없으면
서브에이전트가 할 일을 찾지 못해 빈 결과를 반환한다.
코드 리뷰 시 스타일 체커, 보안 스캐너, 테스트 커버리지 체커를 각각
context: fork로 병렬 실행하면 순차 처리보다 훨씬 빠르다.

6. Hooks — 이벤트 기반 자동화
여기서부터는 두 번째 시스템인 훅(Hooks) 이야기다.
훅은 Claude Code의 라이프사이클 특정 시점에 자동으로 실행되는 셸 커맨드(또는 HTTP 요청, LLM 프롬프트)다.
스킬이 “Claude에게 무엇을 시킬지”를 정의한다면
훅은 “특정 이벤트가 발생했을 때 자동으로 무엇을 할지”를 정의한다.
설정 파일(settings.json)에 이벤트와 핸들러를 등록하는 방식이다.
훅 이벤트 종류
주요 이벤트를 정리하면 이렇다.
SessionStart — 세션 시작/재개 시 (차단 불가)
UserPromptSubmit — 사용자 프롬프트 처리 전 (차단 가능)
PreToolUse — 도구 실행 전 (차단 가능)
PostToolUse — 도구 실행 성공 후 (차단 불가)
PostToolUseFailure — 도구 실행 실패 후 (차단 불가)
PermissionRequest — 권한 요청 다이얼로그 표시 시 (차단 가능)
Stop — Claude 응답 완료 시 (차단 가능)
SubagentStart — 서브에이전트 생성 시 (차단 불가)
SubagentStop — 서브에이전트 종료 시 (차단 가능)
TaskCompleted — 태스크 완료 표시 시 (차단 가능)
PreCompact — 컨텍스트 압축 전 (차단 불가)
PostCompact — 컨텍스트 압축 후 (차단 불가)
SessionEnd — 세션 종료 시 (차단 불가)
“차단 가능”이라는 건 훅이 exit code 2를 반환하면 해당 동작을 중단시킬 수 있다는 뜻이다.
예를 들어 PreToolUse 훅에서 exit 2를 반환하면 그 도구 호출 자체가 차단된다.
설정 구조
~/.claude/settings.json 또는 .claude/settings.json에 다음과 같이 설정한다.
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": ".claude/hooks/block-dangerous.sh",
"timeout": 600
}
]
}
]
}
}
matcher는 이벤트를 필터링하는 정규식이다.
PreToolUse와 PostToolUse에서는 도구 이름에 매칭된다.
Bash로 설정하면 Bash 도구 호출 시에만 훅이 실행된다.
Edit|Write처럼 여러 도구를 OR로 묶을 수도 있고
MCP 도구는 mcp__memory__.* 같은 패턴을 쓴다.
훅 타입
4가지 타입이 있다.
command — 셸 커맨드 실행. stdin으로 JSON 입력을 받음
http — 지정된 URL로 POST 요청 전송
prompt — 단일 턴 LLM 평가
agent — 도구 접근이 가능한 서브에이전트 검증
대부분은 command 타입을 쓰게 된다.
7. 훅 실전 예제
위험한 명령어 차단
rm -rf가 포함된 Bash 명령을 자동으로 차단하는 훅이다.
.claude/hooks/block-dangerous.sh:
#!/bin/bash
COMMAND=$(jq -r '.tool_input.command')
if echo "$COMMAND" | grep -q 'rm -rf'; then
jq -n '{
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "deny",
permissionDecisionReason: "rm -rf 명령이 차단되었습니다"
}
}'
else
exit 0
fi
settings.json 설정:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": ".claude/hooks/block-dangerous.sh"
}
]
}
]
}
}
훅 스크립트는 stdin으로 JSON 데이터를 받는다.
tool_input.command에 실행하려는 명령어가 들어있다.
exit 0이면 통과, exit 2면 차단이다. JSON 출력으로 세부 제어도 가능하다.
파일 수정 후 자동 린트
파일을 쓰거나 수정한 뒤 자동으로 린트를 실행하는 훅이다.
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": ".claude/hooks/lint-check.sh"
}
]
}
]
}
}
PostToolUse는 이미 실행된 후이므로 차단은 못하지만, 린트 결과를 Claude에게 전달하여 자동 수정을 유도할 수 있다.
세션 시작 시 컨텍스트 주입
세션을 시작할 때 최근 git 변경 사항을 자동으로 Claude에게 전달하는 훅이다.
#!/bin/bash
RECENT=$(git log --oneline -5 2>/dev/null)
jq -n --arg changes "$RECENT" '{
hookSpecificOutput: {
hookEventName: "SessionStart",
additionalContext: "최근 커밋:\n\($changes)"
}
}'
exit 0
additionalContext 필드에 넣은 내용이 Claude의 컨텍스트에 추가된다.
매 세션 시작마다 “최근에 뭘 했는지” 자동으로 알려줄 수 있다.
태스크 완료 전 테스트 게이트
태스크를 완료 처리하기 전에 테스트 통과 여부를 확인하는 훅이다.
#!/bin/bash
if ! npm test 2>&1; then
echo "테스트가 실패했습니다. 수정 후 완료하세요." >&2
exit 2
fi
exit 0
TaskCompleted 이벤트에 걸면 된다. 테스트가 실패하면 exit 2로 태스크 완료를 차단한다.

8. 훅 설정 위치와 우선순위
훅도 스킬과 마찬가지로 여러 위치에 설정할 수 있다.
글로벌: ~/.claude/settings.json → 모든 프로젝트
프로젝트 (공유): .claude/settings.json → 팀 전체
프로젝트 (로컬): .claude/settings.local.json → 나만
엔터프라이즈: 관리자 정책 설정 → 조직 전체 (비활성화 불가)
프로젝트 레벨의 .claude/settings.json에 훅을 넣으면 팀원 모두에게 적용된다.
위험한 명령어 차단이나 린트 자동화 같은 훅은 여기 두는 게 좋다.
개인적인 훅(세션 시작 시 환경 설정 등)은 ~/.claude/settings.json에 넣으면 된다.
모든 훅을 비활성화하려면 설정에 "disableAllHooks": true를 넣으면 되지만
엔터프라이즈 관리자가 설정한 정책 레벨 훅은 비활성화할 수 없다.
현재 설정된 훅 목록은 Claude Code에서 /hooks를 입력하면 확인할 수 있다.
9. 스킬 안에서 훅 정의하기
스킬 프론트매터에 훅을 직접 정의할 수도 있다.
이 훅은 해당 스킬이 실행 중일 때만 활성화되고 스킬 종료 시 자동으로 정리된다.
---
name: secure-operations
description: 보안 검사가 포함된 운영 작업
hooks:
PreToolUse:
- matcher: "Bash"
hooks:
- type: command
command: "./scripts/security-check.sh"
---
운영 환경 작업을 수행하세요.
모든 Bash 명령은 보안 검사를 거칩니다.
글로벌 훅과의 차이는 스코프다.
글로벌 훅은 항상 실행되지만 스킬 내 훅은 해당 스킬의 라이프타임에만 적용된다.
10. 공식 스킬 저장소와 오픈 스탠다드
Anthropic은 GitHub에 공식 스킬 저장소(anthropics/skills)를 운영하고 있다. 레퍼런스 스킬들이 Apache 2.0 라이선스로 공개되어 있다.
skill-creator — 새로운 스킬을 대화형으로 만들어주는 메타 스킬
frontend-design — UI 컴포넌트 설계 지침
algorithmic-art — 알고리즘 기반 아트 생성
docx, pdf, pptx, xlsx — 문서 생성·편집 스킬 (source-available)
특히 주목할 만한 것은 Agent Skills 오픈 스탠다드다.
Anthropic이 처음 개발하고 오픈 표준으로 공개한 이 포맷은
Claude Code 외에도 Cursor, VS Code, GitHub Copilot, Gemini CLI, OpenAI Codex, JetBrains Junie, Roo Code 등 30개 이상의 AI 도구에서 호환된다.
SKILL.md 하나 만들어두면 여러 도구에서 동시에 쓸 수 있다는 뜻이다.
마무리
정리하면
스킬은 SKILL.md 파일 하나로 Claude의 행동을 정의한다.
슬래시 커맨드로 직접 호출하거나,
Claude가 맥락에 맞춰 자동으로 로드하거나,
서브에이전트로 분리 실행할 수 있다.
훅은 settings.json에 이벤트-핸들러를 등록하여
도구 실행 전후, 세션 시작/종료, 태스크 완료 등 특정 시점에 자동으로 개입한다.
위험한 명령 차단, 자동 린트, 테스트 게이트 같은 가드레일을 걸 수 있다.
둘 다 복잡한 SDK 없이 마크다운 파일과 JSON 설정만으로 동작한다는 게 포인트다.
AI 코딩 에이전트를 코드 생성 도구가 아니라 자신만의 워크플로우 자동화 도구로 쓰고 싶다면
이 두 시스템을 한번 설정해보는 것을 권한다. 한번 세팅해두면 꽤 편하다.

참고 자료:
– Claude Code 공식 문서 — Skills: https://code.claude.com/docs/en/skills
– Claude Code 공식 문서 — Hooks: https://code.claude.com/docs/en/hooks
– Anthropic 공식 스킬 저장소: https://github.com/anthropics/skills
– Agent Skills 오픈 스탠다드: https://agentskills.io
함께 읽으면 좋은 글
- Claude Code Agent Teams: 코드 리뷰부터 디버깅까지, AI 팀을 조율하는 법
- Agent에게 Tool을 열어줄 때 내가 세운 3가지 원칙
- Agent를 관측하는 3가지 도구 살펴보기 ft. LLM Token
글쓴이 · Plutojoshua
핀테크에서 LLM과 AI 에이전트를 실제 서비스에 적용하는 개발자다. 카카오 AI 앰배서더로 Kanana 모델을 앱에 직접 연동해 검증하고, 비전공자로 시작해 실제 코드와 측정값을 근거로 “왜 그렇게 설계했는지”를 1인칭으로 기록한다. 운영자 소개는 About, 코드는 GitHub에서 볼 수 있다.
“Claude Code의 Skills과 Hooks — AI 코딩 에이전트를 내 방식대로 쓰는 법 2가지”에 대한 1개의 생각