- Published on
Claude Code Skills 직접 만들기 — SKILL.md 한 장으로 에이전트의 새 도구를 빚는 실전 핸즈온 (2026)
- Authors

- Name
- Youngju Kim
- @fjvbn20031
프롤로그 — "이 절차 또 붙여넣고 있네?"라는 순간
Claude Code를 한두 달 쓰다 보면 누구든 같은 깨달음에 도달한다.
매번 같은 지시를 채팅에 붙여넣고 있다. "PR 만들 때는 conventional commits 따라줘", "릴리스 노트는 우리 팀 포맷으로", "테스트 돌리고 빌드 통과한 다음에만 머지해줘". 처음 한두 번은 컨텍스트에 넣어두면 되지만, 같은 절차를 다섯 번째 반복하는 순간 의문이 든다 — 이걸 매번 입력하는 게 맞나?
CLAUDE.md에 넣으면 되지 않냐고? 부분적으로 맞다. 그런데 CLAUDE.md는 전역으로 항상 로드되는 컨텍스트라, 모든 작업에 절차가 따라붙는다. 토큰이 아깝고, 무엇보다 상황과 무관한 절차가 모델의 주의를 분산시킨다. PR 만들 때만 필요한 70줄짜리 체크리스트가 단순한 typo 수정 세션에도 매번 메모리에 올라간다.
Anthropic은 2025년 10월에 이 문제에 답을 냈다. Agent Skills. 이름은 거창해 보이지만 본질은 단순하다 — 디렉터리 하나에 SKILL.md 한 장. 프론트매터에 description을 쓰면 모델이 "지금 이 작업에 이 Skill이 어울리는지" 스스로 판단해서 invoke한다. 항상 로드되는 게 아니라, 필요할 때만 메모리에 올라간다. 그리고 같은 형식을 git에 체크인하면 팀 전체가 공유할 수 있다.
2025년 12월 Anthropic은 한 발 더 나아갔다. Skills를 오픈 표준으로 풀어버렸다. 같은 SKILL.md 포맷이 Claude.ai, Claude Code, Agent SDK, API 어디서나 동작하고, OpenAI Codex CLI와 일부 서드파티 도구도 같은 스펙을 채택했다. 사실상 Markdown + YAML로 표현되는 "에이전트 능력 단위"의 공용어가 된 셈이다.
2026년 5월 현재, 잘 만든 팀은 30~50개의 Skill 카탈로그를 가지고 있다. 배포는 git에 push하거나 plugin marketplace를 통한다. 이 글은 Skill을 처음 만드는 사람을 위해, 정확히 무엇이 어떻게 동작하는지를 펼친다 — SKILL.md의 모든 필드, 호출 모델, 디렉터리 레이아웃, 패키징, 그리고 release-notes-from-git-log Skill을 처음부터 끝까지 만들어보는 핸즈온까지.
1장 · Skill이란 정확히 무엇인가
한 줄 정의: YAML 프론트매터 + 마크다운 지시문을 담은 SKILL.md 한 장과, 그 옆에 선택적으로 놓이는 스크립트/레퍼런스 파일들의 묶음.
가장 작은 Skill은 이렇게 생겼다.
---
name: pr-summary
description: 현재 PR의 변경사항을 요약하고 위험 요소를 표시한다. 사용자가 PR을 리뷰하거나 머지 전 점검을 요청할 때 사용.
---
## 작업
현재 PR diff를 읽고 다음 형식으로 요약하라:
1. 변경의 의도 (2~3문장)
2. 새로 추가된 의존성/설정
3. 위험 영역 (오류 처리 누락, 하드코딩, 테스트 갱신 필요 등)
마지막에 "머지해도 좋음 / 검토 필요 / 보류 권장" 한 줄로 결론을 낸다.
이게 전부다. ~/.claude/skills/pr-summary/SKILL.md에 저장하면, 다음 세션부터 사용자가 "PR 한번 봐줘" 같은 말을 할 때 Claude가 description을 보고 자동으로 invoke한다. 아니면 사용자가 직접 /pr-summary라고 입력해도 같은 결과.
Skill이 풀어주는 것
- 반복되는 절차의 캡슐화. 같은 지시를 매번 붙여넣지 않는다.
- 선택적 로딩. description만 항상 카탈로그에 보이고, 본문은 invoke 시점에만 컨텍스트에 들어간다 — 토큰이 싸다.
- 이름으로 명시 호출.
/skill-name으로 사용자가 직접 트리거할 수도 있다. - 공유 가능성. git에 체크인 → 팀 전체가 같은 절차로 동작.
Skill이 아닌 것
- MCP 서버가 아니다. 외부 프로세스도 아니고, JSON-RPC도 없다. 그냥 텍스트 파일이다.
- 모델 fine-tune이 아니다. 모델은 그대로, 컨텍스트 주입 방식만 바뀐다.
- 하드코딩된 함수가 아니다. Skill 본문은 자연어 지시문이고, 모델이 해석한다. 그래서 같은 Skill이 매번 약간 다르게 행동할 수 있다.
Claude Code 안에서의 위치
Claude Code에는 원래부터 몇 가지 확장 메커니즘이 있었다 — Custom Commands(슬래시 명령), Subagents(.claude/agents/), MCP 서버, Plugins, CLAUDE.md. Skills는 Custom Commands를 흡수하면서 등장했고, 지금은 가장 자주 쓰이는 확장 단위가 됐다. .claude/commands/foo.md와 .claude/skills/foo/SKILL.md가 둘 다 /foo를 만든다 — 같은 슬롯에서 경쟁한다. Skill 쪽이 더 풍부한 기능(디렉터리, 자동 invoke, 스크립트 포함)을 가지므로 신규 개발은 Skill로 한다.
2장 · SKILL.md 포맷 — 모든 필드를 펼친다
가장 자주 헷갈리는 부분이라 모든 필드를 한 번에 정리한다. 모든 필드는 선택이지만, description만은 사실상 필수다.
---
name: my-skill
description: 무엇을 하는 Skill인지, 그리고 언제 사용해야 하는지 한 문장으로.
when_to_use: description으로 부족할 때, 추가 트리거 문구나 예시 요청을 적는다.
argument-hint: "[issue-number]"
arguments: [issue, branch]
disable-model-invocation: false
user-invocable: true
allowed-tools: Read Grep Bash(git *)
model: inherit
effort: high
context: fork
agent: Explore
paths: ["src/**/*.py", "tests/**/*.py"]
shell: bash
hooks:
PreToolUse:
- matcher: "Bash"
command: "echo running bash"
---
본문은 마크다운으로 자유롭게 작성. 이 본문이 invoke 시점에 통째로 컨텍스트에 들어간다.
각 필드의 의미를 풀어두면:
| 필드 | 의미 | 자주 쓰나 |
|---|---|---|
name | 표시명. 생략하면 디렉터리명. 소문자·숫자·하이픈, 64자 이내. | 가끔 |
description | 무엇을 하고 언제 쓰는지. 모델이 invoke를 결정할 때 가장 중요한 신호. | 거의 항상 |
when_to_use | description에 못 담은 트리거 문구·예시. | 가끔 |
argument-hint | 자동완성에 보이는 인자 힌트. [name] 같은 표시. | 종종 |
arguments | 명명된 위치 인자. arguments: [a, b]면 본문에서 $a, $b로 참조. | 종종 |
disable-model-invocation | true면 사용자만 invoke 가능. 부작용 있는 명령(/deploy, /commit)에 권장. | 자주 |
user-invocable | false면 / 메뉴에서 숨김. 백그라운드 지식용. | 가끔 |
allowed-tools | 이 Skill이 활성일 때 자동 승인되는 도구 목록. | 자주 |
model | 이 Skill 동작 동안 쓸 모델. inherit이 안전. | 가끔 |
effort | reasoning effort 수준 (low~max). 정밀 작업에는 high 이상. | 가끔 |
context: fork | 별도 서브에이전트 컨텍스트에서 실행. 대화 히스토리 격리. | 종종 |
agent | context: fork일 때 어떤 서브에이전트 유형을 쓸지 (Explore, Plan, general-purpose). | 종종 |
paths | 특정 파일 패턴에서 작업할 때만 자동 invoke 후보가 됨. | 가끔 |
shell | bash 또는 powershell. Windows에서만 의미. | 거의 안 씀 |
hooks | 이 Skill 동안만 활성화되는 hook 들. | 가끔 |
description 작성법 — 가장 중요한 한 줄
description은 사용자 발화와 매칭되는 검색 키다. 좋은 description의 특징:
- 무엇을 하는지 — "PR 변경사항을 요약하고 위험을 표시한다"
- 언제 사용하는지 — "사용자가 변경사항을 묻거나, 커밋 메시지를 요청하거나, diff 리뷰를 부탁할 때"
- 사용자가 실제로 쓸 만한 키워드 — "PR", "변경사항", "diff", "리뷰"
나쁜 예: description: 좋은 도구입니다. 모델이 언제 써야 할지 모른다.
좋은 예: description: 코드를 conventional commit 규칙에 맞춰 커밋한다. 사용자가 커밋, commit, 변경사항 저장을 요청할 때 사용.
description + when_to_use를 합쳐 1,536자까지 카탈로그에 노출된다. 그 안쪽에 핵심 키워드를 앞쪽에 배치해야 길이 제한이 걸려도 잘려 나가지 않는다.
문자열 치환 — $ARGUMENTS와 친구들
본문 안에서 동적 값을 끼워 넣을 수 있는 자리표시자가 몇 가지 있다.
$ARGUMENTS— invoke 시 따라온 인자 전체.$ARGUMENTS[0]/$0— 첫 번째 위치 인자.$name—arguments: [name]으로 선언된 명명 인자.${CLAUDE_SESSION_ID}— 현재 세션 ID.${CLAUDE_EFFORT}— 현재 effort 수준.${CLAUDE_SKILL_DIR}— 이 SKILL.md가 위치한 디렉터리. 스크립트 경로 만들 때 필수.
동적 컨텍스트 주입 — 셸 명령을 미리 실행
본문에 백틱-느낌표-백틱 문법(!로 시작하는 인라인 코드)을 쓰면, Claude가 보기 전에 셸이 실행되고 그 출력이 본문에 인라인된다. 멀티라인은 !를 붙인 코드 펜스를 쓴다.
## 현재 변경사항
!`git diff HEAD`
## PR 정보
```!
gh pr view --json title,body,labels
gh pr diff --name-only
```
## 작업
위 정보로 릴리스 노트를 작성하라.
이건 매우 강력하다 — 모델이 "diff를 좀 보여줘"라고 도구를 부르지 않아도 되고, 항상 사실 기반으로 시작한다. invoke 시점의 실제 상태가 본문에 들어가기 때문에.
3장 · 호출 모델 — Claude는 언제 Skill을 부르는가
가장 자주 묻는 질문. 답은 두 가지 경로다.
경로 1: 사용자가 명시적으로 invoke. /skill-name [args]. 메뉴에서 골라도 같다. 이 경로는 항상 동작한다.
경로 2: 모델이 자동으로 invoke. 세션 시작 시 모든 Skill의 name + description (+ when_to_use)이 모델 컨텍스트에 카탈로그로 들어간다. 사용자가 어떤 발화를 했을 때, 모델은 카탈로그를 훑고 매칭되는 Skill이 있으면 그걸 트리거한다.
자동 invoke는 다음 조건을 만족해야 한다:
- Skill에
disable-model-invocation: true가 없어야 함. - description이 사용자 발화와 의미적으로 매칭되어야 함.
paths가 설정된 경우, 현재 작업 파일이 패턴에 맞아야 함.
"Skill이 안 불려요" 디버깅
겪을 가능성이 가장 높은 문제다. 체크리스트:
- description에 사용자가 쓸 법한 키워드가 있는가?
What skills are available?명령으로 카탈로그에 보이는가?- 카탈로그가 budget overflow로 잘렸는가?
/doctor로 확인. - 충돌하는 다른 Skill이 더 매칭 점수가 높지는 않은가?
- 이름이
.claude/commands/의 옛 명령과 겹치지 않는가?
"Skill이 너무 자주 불려요"
반대 문제도 흔하다. description이 너무 일반적이면 모든 발화에 후보로 떠오른다.
- description을 더 구체적으로.
- 부작용 있는 명령은
disable-model-invocation: true로 막아라. paths로 트리거 범위를 좁혀라.
4장 · 디렉터리 레이아웃과 거주 위치
Skill은 디렉터리 하나가 단위다. 거주 위치는 네 곳.
| 위치 | 경로 | 적용 범위 |
|---|---|---|
| Enterprise | managed settings로 배포 | 조직 전체 |
| Personal | ~/.claude/skills/<name>/SKILL.md | 내 모든 프로젝트 |
| Project | .claude/skills/<name>/SKILL.md | 이 프로젝트만 |
| Plugin | <plugin>/skills/<name>/SKILL.md | 이 plugin이 활성인 곳 |
이름이 겹치면 Enterprise > Personal > Project 순서. Plugin Skill은 plugin-name:skill-name 네임스페이스로 격리되어 충돌 안 함.
디렉터리 안의 파일들
가장 작은 Skill은 SKILL.md 한 파일이다. 하지만 본문이 길어지거나 도우미 자원이 필요하면 같은 디렉터리에 더 둘 수 있다.
release-notes/
├── SKILL.md # 필수. 진입점.
├── template.md # 출력 템플릿. SKILL.md가 참조.
├── examples/
│ ├── good.md # 예시 출력 1
│ └── bad.md # 예시 출력 2 (반면교사)
├── references/
│ └── changelog-spec.md # Keep a Changelog 규약 등 상세 레퍼런스
└── scripts/
└── collect.sh # SKILL.md에서 호출하는 셸 스크립트
SKILL.md 본문에서 다른 파일을 참조하려면 명시적으로 적어줘야 모델이 알아본다.
## 추가 자료
- 출력 형식 전체는 `template.md` 참조.
- 좋은 예시는 `examples/good.md`, 피해야 할 예시는 `examples/bad.md`.
- 변경 로그 규약 상세는 `references/changelog-spec.md`.
## 데이터 수집
```!
bash ${CLAUDE_SKILL_DIR}/scripts/collect.sh
```
핵심: SKILL.md는 500줄 이내로 유지하고, 길어지면 references/로 빼라. SKILL.md 본문은 invoke되면 통째로 컨텍스트에 들어가서 세션 내내 머문다 — 매 턴 토큰 비용이다.
5장 · 핸즈온 — release-notes-from-git-log Skill 만들기
이제 실제로 하나를 만들어본다. 목표는 명료하다 — 마지막 태그 이후의 git 로그를 보고 Keep a Changelog 형식의 릴리스 노트를 생성하는 Skill. 단순한 PR 요약보다 한 단계 깊이가 있어, 인자 처리·동적 컨텍스트·도우미 스크립트·템플릿까지 한 번에 다룬다.
1단계: 디렉터리 생성
mkdir -p ~/.claude/skills/release-notes/{scripts,references,examples}
cd ~/.claude/skills/release-notes
2단계: 도우미 스크립트 — 마지막 태그 이후의 커밋 수집
scripts/collect.sh에 저장한다.
#!/usr/bin/env bash
set -euo pipefail
LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
if [[ -z "$LAST_TAG" ]]; then
echo "## 마지막 태그 없음 — 전체 로그"
git log --pretty=format:"- %h %s (%an)" --no-merges
else
echo "## 마지막 태그: $LAST_TAG"
echo ""
echo "## 그 이후의 커밋"
git log "${LAST_TAG}..HEAD" --pretty=format:"- %h %s (%an)" --no-merges
echo ""
echo "## 그 이후의 머지 커밋"
git log "${LAST_TAG}..HEAD" --merges --pretty=format:"- %h %s"
echo ""
echo "## 변경된 파일 (요약)"
git diff --stat "${LAST_TAG}..HEAD" | tail -1
fi
실행 권한을 준다.
chmod +x scripts/collect.sh
3단계: 출력 템플릿
references/template.md에 저장한다. Keep a Changelog 1.1 규약에 맞춘 골격이다.
## [VERSION] - YYYY-MM-DD
### Added
- 새 기능, 외부 가시적 추가만.
### Changed
- 기존 기능의 변경. 호환 깨지지 않는 한 여기.
### Deprecated
- 다음 메이저에서 제거 예정.
### Removed
- 이번에 제거됨.
### Fixed
- 버그 수정. 영향 범위 한 줄.
### Security
- 보안 패치. CVE 있으면 링크.
4단계: 좋은 예시 / 나쁜 예시
examples/good.md.
## [1.4.0] - 2026-05-10
### Added
- OAuth2 디바이스 플로우 지원 (#234).
- 환경 변수 `RATE_LIMIT_PER_MIN`으로 토큰 버킷 조절.
### Fixed
- 동시 1만 연결에서 발생하던 메모리 누수 (#241).
- 윈도우에서 경로 구분자 처리 오류.
### Security
- `axios` 1.7.0으로 업그레이드 (CVE-2025-12345).
examples/bad.md.
## v1.4.0
- 이것저것 수정함.
- 버그 잡음.
- 성능 좋아짐.
- 리팩토링.
- 코드 정리.
5단계: SKILL.md — 본체
이제 진입점을 적는다. 위에서 만든 자원을 모두 묶는다.
---
name: release-notes
description: 마지막 git 태그 이후의 커밋과 머지를 분석해 Keep a Changelog 형식의 릴리스 노트를 작성한다. 사용자가 릴리스 노트, 체인지로그, changelog, release notes 작성을 요청할 때 사용.
when_to_use: "다음 릴리스 노트를 써줘", "이번 버전 changelog 좀 만들어줘", "v1.5.0 릴리스 노트", 같은 발화에서 트리거.
argument-hint: "[version]"
arguments: [version]
allowed-tools: Bash(git *) Read
effort: high
---
# Release Notes — Keep a Changelog
목표 버전: `$version` (지정 없으면 적절한 다음 버전을 SemVer 규칙으로 추정).
## 입력 데이터
```!
bash ${CLAUDE_SKILL_DIR}/scripts/collect.sh
```
## 출력 형식
`${CLAUDE_SKILL_DIR}/references/template.md`의 골격을 따른다. 카테고리는
Added / Changed / Deprecated / Removed / Fixed / Security 여섯 개로 한정.
좋은 예시: `${CLAUDE_SKILL_DIR}/examples/good.md`
피해야 할 예시: `${CLAUDE_SKILL_DIR}/examples/bad.md`
## 분류 규칙
1. conventional commit prefix가 있으면 우선 신뢰:
- `feat:` → Added
- `fix:` → Fixed
- `refactor:` / `perf:` / `chore:` → 사용자 가시 변경이 있을 때만 Changed
- `security:` / `sec:` → Security
2. prefix가 없거나 애매하면 커밋 메시지와 변경 통계로 추정.
3. 단순 리팩토링·테스트·CI 변경은 **사용자 가시 영향이 없으면 제외**.
## 톤과 길이
- 각 항목 한 줄. 사용자가 무엇이 달라졌는지 즉시 안다.
- 내부 함수명·파일 경로는 쓰지 않는다.
- 이슈/PR 번호가 있으면 끝에 `(#123)`로.
- 마크다운 ASCII만. 이모지 금지.
## 결과 검증
작성 후 다음을 확인:
- 모든 머지 커밋이 어딘가에 반영됐는가?
- "기타", "잡다한 변경" 같은 카테고리를 만들지 않았는가?
- Security 항목에 CVE 링크가 빠지지 않았는가?
문제가 있으면 사용자에게 "이 커밋을 어디로 분류할까요?"라고 묻고 진행한다.
6단계: 테스트
세션을 시작하고 두 가지 방식 다 시도한다.
cd /path/to/your/repo
claude
# 1) 자동 invoke
> v1.5.0 릴리스 노트 좀 만들어줘
# 2) 명시 invoke
> /release-notes 1.5.0
두 경로 모두 같은 결과로 이어져야 한다. 안 불리면 description에 키워드가 부족한 것이고, 너무 일반적으로 불리면 description을 좁혀라.
7단계: 팀에 공유
개인용으로 확인했으면 프로젝트 또는 plugin으로 옮긴다.
# 프로젝트 단위 공유
mv ~/.claude/skills/release-notes /path/to/repo/.claude/skills/
git add .claude/skills/release-notes
git commit -m "skill: add release-notes generator (Keep a Changelog)"
이제 같은 리포에서 누가 Claude Code를 켜든 이 Skill을 쓸 수 있다.
6장 · 패키징과 배포
Skill을 다른 사람과 공유하는 길은 세 갈래다.
6-1. Git에 그대로 — 가장 단순
.claude/skills/를 리포에 체크인. clone → claude 실행이면 끝. 이게 90% 케이스에 답이다.
장점: 별도 인프라 필요 없음, 버전 관리 자동, 코드 리뷰 자연스럽게 됨. 단점: 다른 리포에서 쓰려면 복붙. plugin이나 dotfiles 동기화로 보완.
6-2. Plugin — 여러 Skill·subagent·hook을 함께 묶을 때
Claude Code Plugin은 Skill·subagent·hook·command를 한 패키지로 묶는 단위다. <plugin>/skills/<name>/SKILL.md 구조로 plugin 안에 Skill을 둔다. plugin은 marketplace를 통해 설치된다.
언제 plugin인가:
- 관련된 Skill 5개 이상을 한 묶음으로 배포할 때.
- Skill에 더해 custom subagent나 hook도 같이 필요할 때.
- 외부 사용자가 한 번의 설치 명령으로 받게 하고 싶을 때.
6-3. Anthropic Skills Marketplace — 공개 카탈로그
2025년 12월에 공개된 파트너 빌트 Skill 디렉터리. Atlassian, Figma, Canva, Stripe, Notion, Zapier 등이 자사 워크플로우용 Skill을 올려뒀다. 자기 Skill을 공개 배포하고 싶으면 이 경로를 검토.
보안 고려
allowed-tools로 권한을 미리 승인하는 Skill을 git에 체크인하면, 그 리포를 clone하는 모두에게 같은 권한이 부여된다. Claude Code는 처음 신뢰할 때 workspace trust 다이얼로그를 띄우니까 한 번은 검토 기회가 있지만, 남의 Skill을 무비판적으로 활성화하지 말 것. SKILL.md 본문, scripts/, allowed-tools를 반드시 읽어본다.
7장 · Skills vs MCP vs Subagent vs Plugin — 결정 트리
가장 자주 헷갈리는 부분이다. 네 가지 메커니즘은 겹치지 않는 영역이 있다.
| 메커니즘 | 무엇 | 언제 |
|---|---|---|
| Skill | YAML+마크다운 한 파일. invoke 시 컨텍스트에 인라인. | 절차·체크리스트·반복 지시. 코드는 셸 스크립트 정도. |
| MCP 서버 | 외부 프로세스, JSON-RPC, 도구를 노출. | 외부 API·DB·툴체인과 상호작용. 다른 에이전트도 같은 도구를 쓰게 하고 싶을 때. |
| Subagent | 자체 시스템 프롬프트를 가진 격리된 컨텍스트. | 컨텍스트 격리가 필요한 큰 작업(코드베이스 탐색, 깊은 리서치). |
| Plugin | 위 셋을 묶는 배포 단위. | 다수의 Skill/Subagent/Hook를 한 패키지로. |
결정 트리
질문 1: 외부 시스템과 통신해야 하는가? (DB, 외부 API, 파일 시스템의 특수 도구)
- 예 → MCP 서버. 새 도구가 필요하면 MCP. Skill은 도구를 만드는 게 아니라 기존 도구를 어떻게 쓸지 지시한다.
- 아니오 → 질문 2.
질문 2: 별도 컨텍스트에서 격리 실행이 필요한가? (긴 탐색, 별도 권한)
- 예 → Subagent, 또는
context: fork가 붙은 Skill. - 아니오 → 질문 3.
질문 3: 여러 Skill·Subagent·Hook를 한 묶음으로 배포해야 하는가?
- 예 → Plugin. 단일 Skill이라도 marketplace 배포면 plugin.
- 아니오 → Skill.
구체 예시로 보면
| 상황 | 선택 |
|---|---|
| Jira 티켓 자동 조회·업데이트 | MCP (Jira API 필요) |
| PR 요약 절차 | Skill |
| 깊은 코드베이스 탐색 | Subagent (or Skill with context: fork) |
| "릴리스 워크플로우" 패키지 (Skill 3개 + hook 2개) | Plugin |
| 매 커밋마다 자동 실행될 검사 | Hook (Skill 아님) |
핵심: Skill은 도구를 만드는 게 아니라 도구 사용법을 가르치는 것. "새 도구가 필요해" = MCP. "있는 도구를 어떻게 쓸지 매번 다시 설명하기 싫어" = Skill.
8장 · 고급 패턴
8-1. context: fork로 서브에이전트에 위임
큰 작업은 메인 대화 컨텍스트를 오염시킨다. context: fork를 쓰면 Skill 본문이 새 격리된 컨텍스트의 task가 되고, 결과만 메인으로 돌아온다.
---
name: deep-research
description: 주어진 주제를 코드베이스에서 깊게 조사. 사용자가 "이 기능 어디서 구현됐어?", "왜 이렇게 짜여졌어?"를 물을 때.
context: fork
agent: Explore
---
$ARGUMENTS를 코드베이스에서 깊게 조사:
1. Glob과 Grep으로 관련 파일을 찾는다.
2. 핵심 파일을 읽고 호출 그래프를 만든다.
3. 발견을 구체적인 파일:줄 참조와 함께 요약한다.
장점: 메인 대화에 200개 파일 전체가 들어오지 않는다. 단점: 결과만 받으니, 중간에 사람이 끼어들 여지가 적다.
8-2. allowed-tools로 마찰 줄이기
매번 "Bash 실행해도 될까요?"를 묻지 않게 하려면 미리 승인한다. 단, 범위를 좁게.
allowed-tools: Bash(git add *) Bash(git commit *) Bash(git status *)
Bash(*)로 모든 셸을 미리 승인하지 마라. Skill이 의도치 않게 위험한 명령을 실행할 여지가 생긴다.
8-3. paths로 자동 invoke 범위 좁히기
특정 파일에서만 의미 있는 Skill은 paths로 트리거를 좁힌다.
paths: ["src/**/*.py", "tests/**/*.py"]
작업 중 파일이 패턴에 안 맞으면 모델 자동 invoke 후보에서 빠진다. 사용자 직접 invoke는 여전히 가능.
8-4. 동적 컨텍스트로 사실 기반 시작
가장 강력한 패턴 중 하나. invoke 시점에 셸 명령이 실행되고 출력이 본문에 인라인된다.
## 환경
```!
node --version
npm --version
git status --short
```
## 최근 변경
!`git log --oneline -10`
## 작업
위 환경에서 ...
모델이 "환경 좀 알려줘"라고 도구 호출을 하지 않아도 되고, 항상 실제 데이터로 시작한다.
8-5. hooks로 결정론적 끼어들기
Skill 활성 동안만 동작하는 hook를 frontmatter에 둘 수 있다. PostToolUse로 lint를 강제하거나, PreToolUse로 위험 명령을 차단하거나.
8-6. ultrathink로 깊은 추론 한 번
본문 어디든 ultrathink라는 단어를 넣으면 그 Skill 동안 모델이 더 깊은 추론 모드로 들어간다. 복잡한 의사결정이 끼는 Skill(예: 마이그레이션 계획)에서 유용. 모든 Skill에 남발하면 비용·지연 폭증.
9장 · 실제 예시 — 사람들이 만들고 있는 Skill들
2026년 5월 기준, 자주 보이는 패턴들.
PR Summary — diff와 PR 본문을 받아 한 화면 요약 + 위험 표시. 가장 흔한 Skill.
Conventional Commit — disable-model-invocation: true. /commit으로만 트리거. 스테이지 → 메시지 작성 → 커밋. allowed-tools: Bash(git add *) Bash(git commit *).
Release Notes — 위에서 만든 그것. 회사마다 포맷이 달라서 직접 만들기 좋은 종류.
Code Review Checklist — 자사 코딩 규약에 맞춘 체크리스트. references/에 보안·성능·접근성 가이드를 두고 SKILL.md가 진입점.
Runbook Executor — 운영 절차 자동화. "배포 롤백해줘"가 들어오면 정확한 순서로 헬름 차트 롤백, 슬랙 알림, 메모리 정리.
Bug Triage — 이슈 본문을 읽고 라벨·우선순위·담당자 추천. GitHub MCP와 짝.
Migration Guide — 코드베이스 일부를 React 16 → 19로 옮기는 등. arguments: [from, to, target].
Content Drafting — 블로그 초안, 트윗 스레드, 변경 공지. 회사 톤 가이드를 references/에.
Security Review — 새 의존성·새 API 엔드포인트가 들어왔을 때 체크리스트. CWE 매핑.
Database Migration — 스키마 변경 절차. dry-run → diff → 승인 → 배포. PreToolUse hook로 prod 보호.
Postmortem Drafter — 인시던트 후 회고 초안. 5 whys, blameless 톤.
Docs Sync — 코드 변경 후 README, API 문서, 변경 로그를 함께 갱신. paths 활용.
Cost Reporter — 마지막 PR이 클라우드 비용에 어떤 영향을 주는지 추정. terraform plan + 가격 표.
이 목록은 단지 흔히 보이는 모양일 뿐, 본인 팀 절차를 캡슐화한 Skill이 가장 가치 있다. "이걸 또 입력하고 있네?"가 떠오를 때마다 새 Skill 후보가 하나 생긴 셈이다.
10장 · 안티패턴 — 흔히 망가지는 방식
수십 개의 Skill을 만들고 본 패턴들.
- description이 모호하다. "좋은 도구입니다" — 모델이 언제 부를지 못 정한다.
- description이 너무 일반적이다. "코드를 작성한다" — 거의 모든 발화에 매칭되어 매번 invoke된다.
- 본문이 500줄을 넘는다. 매 턴 토큰 비용. references/로 빼라.
allowed-tools: Bash(*). 모든 셸 명령을 미리 승인. 사고 나기 좋다. 범위 좁혀라.- 부작용 있는 명령에
disable-model-invocation: false. 모델이 멋대로/deploy를 부른다. 부작용 있는 건 항상 사용자만. - CLAUDE.md와 중복. 같은 지시를 양쪽에 적으면 충돌·혼선. CLAUDE.md는 항상 적용되는 사실, Skill은 상황별 절차.
- MCP로 풀어야 할 걸 Skill로 푼다. 외부 API 호출 로직을 마크다운 지시로 우회. MCP 서버를 만들어라.
- 테스트가 없다. Skill도 코드다. 자동 invoke와 명시 invoke 둘 다 통과하는지 매번 확인.
- 버전 관리 안 함. Skill을 바꾸면 동작이 바뀐다. git 히스토리가 답.
- 이름 충돌. Personal·Project·Plugin에 같은 이름 Skill. 우선순위 규칙은 있지만 헷갈린다. 충돌하지 않게 이름을 짜라.
11장 · Skill 콘텐츠 생명주기 — 토큰 측면
이건 자주 빠뜨리는 디테일이다. Skill이 invoke되면 본문이 한 메시지로 컨텍스트에 들어가고, 세션 끝까지 머문다. 매 턴 다시 읽지 않는다.
오토 컴팩션이 일어나면 가장 최근에 invoke된 Skill들이 일부 유지된다. 각 Skill의 첫 5,000 토큰까지 보존되고, 모든 Skill 합쳐서 25,000 토큰 예산 안에서 가장 최근 것부터 채워진다. 옛 Skill은 컴팩션 후 사라질 수 있다.
영향이 사라진 것 같으면 — 사실 본문은 거의 항상 컨텍스트에 있고, 모델이 다른 접근을 선택했을 가능성이 더 크다. description과 본문 첫 줄에 행동 강제 표현(must, never)을 더 넣어보거나, hook로 결정론적으로 강제.
에필로그 — Skill을 의식하라
Skill은 "에이전트가 무엇을 할 수 있나"를 한 줄씩 늘리는 가장 싼 방법이다. 새 모델을 기다릴 필요 없고, 새 MCP 서버를 만들 필요도 없다. 절차를 한 디렉터리에 적고 git에 push하면, 다음 세션부터 팀 전체가 그 절차를 공유한다.
9개 항목 체크리스트
- description은 무엇·언제·키워드를 모두 담았는가?
- 본문 500줄 이내, 긴 자료는 references/로 뺐는가?
- 부작용 있는 명령은
disable-model-invocation: true인가? allowed-tools는 좁게 잡았는가?- 동적 컨텍스트(
!)로 사실 기반 시작이 되어 있는가? - 자동 invoke와 명시 invoke 둘 다 테스트했는가?
- 이름이 다른 Skill·command와 충돌하지 않는가?
- Personal/Project/Plugin 중 어디 둘지 의식적으로 골랐는가?
- 비슷한 능력을 MCP·Subagent로 해결해야 하는 건 아닌가?
안티패턴 빠른 회상
- 모호한 description / 과한 description / 길게 늘어진 본문 / 넓은 allowed-tools / 자동 invoke된 위험 명령 / CLAUDE.md 중복 / MCP로 풀어야 할 걸 Skill로 / 테스트 없음 / 버전 관리 없음 / 이름 충돌.
다음 글 예고
다음 글에서는 MCP 서버를 직접 처음부터 만들기 — TypeScript SDK로 30분 만에 사내 API 노출하기를 다룬다. Skill로 절차를 캡슐화했다면, MCP로는 진짜 새 도구를 만들 차례다.
그 다음은 Plugin marketplace에 자기 plugin 올리기, 그리고 Claude Code Hooks 패턴북 — 결정론적 안전망을 깔아 에이전트에게 더 큰 권한을 넘기는 방법.
이 글에서 만든 release-notes Skill처럼, 작은 한 장의 마크다운이 팀 절차를 영원히 바꾼다. "이거 또 입력하고 있네"가 떠오를 때마다, 그게 다음 Skill의 후보다.
참고 / References
- Anthropic — Extend Claude with skills (Claude Code 공식 문서)
- GitHub — anthropics/skills (공식 예제 Skill 리포)
- Anthropic — The Complete Guide to Building Skills for Claude (PDF)
- Agent Skills 오픈 표준 사이트
- Anthropic — Subagents (Claude Code)
- Anthropic — Plugins (Claude Code)
- Anthropic — Hooks (Claude Code)
- Anthropic — Memory / CLAUDE.md
- Anthropic — Permissions
- The New Stack — Agent Skills: Anthropic's Next Bid to Define AI Standards
- VentureBeat — Anthropic launches enterprise Agent Skills and opens the standard
- Keep a Changelog 1.1 규약
- Model Context Protocol 공식 사이트