CPN 한국어 자습서 · 러닝패스 1 / 4 — Agent Skills
3장
Introduction to agent skills · Configuration and multi-file skills
스킬은 이름과 설명만 있어도 작동합니다. 하지만 스킬이 커지고 더 민감한 일을 맡게 되면, 세 가지 고급 설정이 필요해집니다. 쓸 수 있는 도구를 제한하고(allowed-tools), 설명을 더 잘 써서 제때 발동하게 하고, 파일이 비대해지지 않게 나눠 두는 것입니다. 이 장에서 하나씩 살펴봅니다.
이 장에서 배우는 것What you'll learn
약 20분고급 메타데이터 필드 — allowed-tools와 model까지 다루기
제때 발동하는 효과적인 description 쓰는 법
allowed-tools로 스킬이 켜졌을 때 할 수 있는 일 제한하기
점진적 공개·멀티파일로 복잡한 스킬 구조 잡기
이 자습서를 보는 법
영어 영상을 먼저 본 뒤, 여기서 한국어로 따라 읽고 손으로 익히는 교재입니다. 점선 친 단어는 올리거나 탭하면 뜻이 나오고, 아래쪽엔 스킬이 작동하는 모습을 직접 눌러 보는 시뮬레이터가 있습니다. 읽은 만큼 ‘완료’를 누르면 위 진도 바가 찹니다.
--- 사이에 적는 요약 정보입니다. 스킬의 이름·설명, 그리고 아래 옵션들이 여기에 들어갑니다.Read(읽기), Edit(수정), Write(쓰기), Bash(명령 실행) 등.SKILL.md에 두고, 자세한 자료는 따로 두어 필요할 때만 불러오는 방식입니다.이름과 설명만 있는 기본 스킬도 잘 작동합니다. 하지만 스킬을 많이 쓰고 키우다 보면 세 가지 고민이 생깁니다.
이 장의 고급 설정은 정확히 이 셋을 해결합니다. 좋은 설명, allowed-tools, 그리고 점진적 공개입니다.
먼저 영상을 보세요. 영어가 어렵다면 아래 한국어를 같이 읽으면 됩니다. 자동 번역과 달리, 낯선 용어를 풀어서 옮겼습니다.
영상 대본 — 영어 영상을 보며 같이 읽으세요 (타임스탬프 기준).
name과 description만 있어도 작동하지만, 여기에 몇 가지 고급 기법을 더하면 Claude Code에서 훨씬 강력해집니다.name은 스킬을 가리키는 이름으로, 소문자·숫자·하이픈만 쓰고 최대 64자, 폴더 이름과 같게 맞춥니다.description도 필수이며, Claude에게 언제 이 스킬을 쓸지 알려줍니다. 최대 1,024자이고, 가장 중요한 필드입니다 — Claude가 매칭에 이걸 씁니다.allowed-tools는 스킬이 켜져 있을 때 쓸 수 있는 도구를 제한하고, model은 그 스킬에 어떤 Claude 모델을 쓸지 지정합니다.allowed-tools가 이를 가능하게 합니다. 켜져 있으면 거기 적힌 도구만 (권한 묻지 않고) 쓸 수 있고, 수정·쓰기·bash는 막힙니다. 비워 두면 아무것도 제한하지 않습니다.SKILL.md에, 자세한 참고 자료는 별도 파일에 두어 필요할 때만 읽게 합니다.scripts, 문서용 references, 이미지·템플릿용 assets 폴더를 권합니다.SKILL.md에서 보조 파일로 링크를 겁니다. 그러면 시스템 설계를 물을 때만 architecture.md를 읽고, “어디에 컴포넌트를 넣지?” 같은 질문엔 아예 안 불러옵니다. 문서 전체 대신 목차만 두는 셈입니다.SKILL.md는 500줄 아래로 유지하세요. 넘으면 내용을 나눌지 고민해 보세요.name·description은 필수, allowed-tools는 도구 제한, model은 모델 지정입니다.SKILL.md는 500줄 아래, 보조 파일은 필요할 때만. 스크립트는 내용을 안 올리고 실행돼 컨텍스트를 아낍니다.스킬 맨 위 프론트매터(--- 사이)에는 여러 필드를 적을 수 있습니다. 둘은 필수, 나머지는 선택입니다. 아래는 네 가지를 다 쓴 예시입니다. (원문은 영어입니다.)
1 2 3 4 5 6 7 8
--- name: codebase-onboarding description: Helps new developers understand how the system works. allowed-tools: Read, Grep, Glob, Bash model: sonnet --- # Codebase Guide
선택 필드를 켜고 끄면, 오른쪽 SKILL.md 머리말이 실시간으로 바뀝니다. 필수 필드는 끌 수 없습니다.
---name: codebase-onboardingdescription: Helps new developers understand how the system works.allowed-tools: Read, Grep, Glob, Bashmodel: sonnet---
allowed-tools · 스킬이 켜져 있을 때 쓸 수 있는 도구를 제한합니다. 끄면 제한이 없어져 평소 권한대로 동작합니다.
name·description은 항상 있어야 합니다. allowed-tools·model은 필요할 때만 더하면 됩니다.
설명은 구체적으로 적어야 합니다. 누군가에게 “당신 일은 문서를 돕는 거예요”라고만 하면 막막하겠죠. Claude도 똑같습니다. 좋은 설명은 두 질문에 답합니다.
스킬이 제때 안 불려 오면, 평소 쓰는 말투의 키워드를 설명에 더 넣어 보세요. 예: “PR 리뷰” 외에 “코드 변경 점검”, “수정 사항 확인”처럼요. 설명의 표현이 곧 발동 정확도입니다.
때로는 파일을 읽기만 하고 고치지는 못하게 하고 싶습니다. 보안이 민감한 작업, 읽기 전용 점검처럼 가드레일이 필요할 때죠. 위 예시처럼 allowed-tools: Read, Grep, Glob, Bash로 두면, 그 스킬이 켜져 있는 동안 Claude는 그 도구만 (권한 묻지 않고) 쓸 수 있습니다. 수정·쓰기는 막힙니다.
allowed-tools를 아예 비워 두면 아무것도 제한하지 않고, Claude의 평소 권한 방식대로 동작합니다.
그럼 allowed-tools가 실제로 어떻게 막을까요? 아래에서 직접 도구를 켜고 끄며, 읽기·수정 요청이 어떻게 처리되는지 확인해 보세요. 기준은 allowed-tools스킬이 켜져 있을 때 쓸 수 있는 도구를 정해진 것만으로 제한하는 설정.가 걸린 codebase-onboarding 스킬입니다.
권한 시뮬레이터 — allowed-tools에 어떤 도구를 넣는지에 따라 요청이 통과되거나 막힙니다.
스킬에 넣을 도구를 켜고 끈 다음, 요청을 골라 [실행]하세요. 요청이 필요로 하는 도구가 목록에 없으면 막힙니다.
allowed-tools에 넣을 도구
allowed-tools: Read, Grep, Glob, Bash
요청
팁. Edit를 켜고 ‘수정’ 요청을 다시 실행해 보세요. 막히던 요청이 통과됩니다.
기본 상태에선 수정 요청이 막힙니다 — Edit가 목록에 없으니까요. 이렇게 스킬마다 ‘할 수 있는 일의 범위’를 미리 정해 둘 수 있습니다.
읽기 전용 스킬은 실수로라도 파일을 건드리지 않습니다. 권한을 좁혀 두는 것만으로 안전장치가 됩니다.
스킬의 프론트매터에 allowed-tools 줄을 넣어 두고, 수정이 필요한 요청을 해보세요.
그 스킬이 켜진 동안에는 수정·쓰기 도구가 막혀, 읽기 작업만 권한 없이 진행됩니다.
스킬은 PC(Claude Code) 전용이라 모바일에서는 발동하지 않습니다. 위 시뮬레이터로 흐름을 익혀 두고, PC에서 직접 확인해 보세요.
스킬이 켜지면 그 SKILL.md 내용이 통째로 컨텍스트Claude가 한 대화에서 한 번에 다루는 정보의 양. 가득 찰수록 효율이 떨어집니다.로 들어옵니다. 그런데 참고 자료·예시·스크립트까지 한 파일에 다 넣으면 — 2만 줄짜리 파일을 떠올려 보세요 — 공간을 너무 많이 차지하고 관리도 힘듭니다.
점진적 공개가 해법입니다. 핵심 지침만 SKILL.md에 두고, 자세한 자료는 별도 파일로 빼서 필요할 때만 읽게 합니다. 폴더는 보통 이렇게 나눕니다.
멀티파일 스킬 구조 — SKILL.md는 목차, 나머지는 필요할 때만.
codebase-onboarding/ ├─ SKILL.md ← 핵심 지침 · 목차 ├─ references/ ← 자세한 문서 (필요할 때만) │ ├─ architecture-guide.md │ └─ deep-dive-guide.md ├─ scripts/ ← 실행 코드 └─ assets/ ← 이미지·템플릿
그리고 SKILL.md 안에서, 언제 그 파일을 읽을지 조건과 함께 링크를 겁니다.
1 2 3 4 5 6 7 8 9 10
# Codebase Onboarding ## Progressive Disclosure Levels ### Level 2: Architecture Overview **Only load when user requests more detail.** See [architecture-guide.md](references/architecture-guide.md). ### Level 3: Deep Dives See [deep-dive-guide.md](references/deep-dive-guide.md).
이렇게 해 두면 시스템 설계를 물을 때만 architecture-guide.md를 읽고, “어디에 컴포넌트를 넣지?” 같은 질문엔 아예 불러오지 않습니다.
질문을 골라 [보내기]를 누르면, 그 질문에 필요한 참고 파일만 컨텍스트로 들어옵니다. 나머지는 목차로만 남습니다.
스킬 폴더SKILL.md는 항상, 참고 파일은 필요할 때만
SKILL.md
핵심 지침 · 목차 (항상 로드)
references/architecture-guide.md
시스템 설계 · 구조
필요할 때만 로드
references/deep-dive-guide.md
특정 주제 심화
필요할 때만 로드
컨텍스트 윈도우지금 작업 기억에 올라온 것
‘어디에 추가하지?’는 목차(SKILL.md)만으로 답할 수 있어, 참고 파일을 아예 안 불러옵니다. 깊은 질문일 때만 해당 파일이 로드돼 컨텍스트가 가볍게 유지됩니다.
두꺼운 설명서를 통째로 들고 다니는 대신, 목차만 들고 다니다 필요한 장만 펴 보는 것입니다. 기준은 간단해요 — SKILL.md는 500줄 아래로.
스킬 폴더에 둔 스크립트정해진 일을 자동으로 처리하는 작은 프로그램(코드).는, 내용을 컨텍스트에 올리지 않고도 실행할 수 있습니다. 스크립트가 실행되고 그 결과(출력)만 토큰을 씁니다. 그래서 SKILL.md에는 “이 스크립트를 읽지 말고 실행하라”고 적어 둡니다.
이 방식은 다음에 특히 좋습니다.
name·description은 필수, allowed-tools·model은 선택.allowed-tools는 스킬이 켜진 동안 쓸 수 있는 도구를 제한한다 — 읽기 전용·보안 작업의 안전장치.SKILL.md(500줄 아래)에 두고, 자세한 건 별도 파일로 필요할 때만 불러온다.정답을 먼저 떠올려 본 뒤 골라 보세요. 맞히면 설명이 나옵니다.
Q1스킬 프론트매터에서 ‘필수’ 필드는 무엇인가요?
name과 description이 필수예요. allowed-tools와 model은 강력하지만 선택입니다.
Q2allowed-tools: Read, Grep, Glob으로 설정하면 어떻게 되나요?
맞아요. allowed-tools는 ‘허용 목록’이라, 적힌 도구만 권한 없이 쓰고 나머지(수정·쓰기 등)는 막습니다.
Q3스킬이 커질 때 ‘점진적 공개’의 핵심은?
핵심만 SKILL.md(500줄 아래)에 두고 나머지는 references·scripts·assets로 빼서, 필요할 때만 읽게 합니다.
SKILL.md에 남기고, 무엇을 참고 파일로 뺄까요?allowed-tools로 권한을 좁혀 두면 더 안전해질 곳은 어디인가요?SKILL.md 맨 위 라벨의 이름·설명·도구 항목이 agentskills.io 공개 표준에 맞는지 점검하고, 규칙을 벗어난 곳을 항목별로 짚어 봅니다.
// SKILL.md 검사기 — SKILL.md 맨 위 라벨(name·description·allowed-tools·model)이
// agentskills.io 공개 표준 규칙에 맞는지 점검한다. 규칙은 3장에서 배운 것 그대로다.
// (a) 맨 위 라벨 블록을 잘라 읽는다. 여는 --- 와 닫는 --- 는 각자 제 줄에 있어야 한다.
// 한 줄로 붕괴하면(---name: ... model: ... ---) 라벨을 읽지 못한다.
function parseFrontmatter(src) {
const lines = src.replace(/\r\n/g, "\n").split("\n");
const first = lines[0].trim();
if (first !== "---") {
if (first.indexOf("---") === 0) {
return { ok: false, reason: "여는 --- 뒤에 내용이 붙어 라벨이 한 줄로 붕괴했습니다." };
}
return { ok: false, reason: "맨 위 라벨이 --- 로 시작하지 않습니다." };
}
let end = -1;
for (let i = 1; i < lines.length; i++) {
if (lines[i].trim() === "---") { end = i; break; }
}
if (end === -1) {
return { ok: false, reason: "닫는 --- 가 제 줄에 없습니다." };
}
const fm = {};
for (let i = 1; i < end; i++) {
const c = lines[i].indexOf(":");
if (c === -1) continue;
fm[lines[i].slice(0, c).trim()] = lines[i].slice(c + 1).trim();
}
return { ok: true, fm: fm, body: lines.slice(end + 1).join("\n").trim() };
}
// (b) 라벨과 본문을 규칙대로 점검한다.
function validate(parsed) {
const problems = [];
if (!parsed.ok) { problems.push(parsed.reason); return problems; }
const fm = parsed.fm;
// name — 필수 · 소문자·숫자·하이픈만 · 최대 64자
if (!fm.name) {
problems.push("name 이 없습니다(필수).");
} else {
if (!/^[a-z0-9-]+$/.test(fm.name)) {
problems.push("name 은 소문자·숫자·하이픈만 됩니다: " + fm.name);
}
if (fm.name.length > 64) {
problems.push("name 이 64자를 넘습니다(" + fm.name.length + "자).");
}
}
// description — 필수 · 최대 1,024자 · 매칭에 가장 중요한 항목
if (!fm.description) {
problems.push("description 이 없습니다(필수 · 매칭에 가장 중요).");
} else if (fm.description.length > 1024) {
problems.push("description 이 1,024자를 넘습니다(" + fm.description.length + "자).");
}
// allowed-tools — 있으면 쉼표로 나눈 목록이어야 한다
const at = fm["allowed-tools"];
if (at && at.indexOf(",") === -1 && at.split(/\s+/).length > 1) {
problems.push("allowed-tools 는 쉼표로 나눈 목록이어야 합니다.");
}
// 라벨 아래 본문(지침) 존재
if (!parsed.body) {
problems.push("라벨 아래 본문(지침)이 없습니다.");
}
return problems;
}
// ── 점검할 SKILL.md 세 벌(전부 3장 예시에서 가져옴) ──
const GOOD = [
"---",
"name: codebase-onboarding",
"description: Helps new developers understand how the system works.",
"allowed-tools: Read, Grep, Glob, Bash",
"model: sonnet",
"---",
"",
"# Codebase Guide",
].join("\n");
// 여닫는 --- 가 제 줄을 잃고 한 줄로 붕괴한 라벨
const COLLAPSED =
"---name: codebase-onboardingdescription: Helps new developers " +
"understand how the system works.allowed-tools: Read, Grep, Glob, Bashmodel: sonnet---";
// 이름에 대문자·공백이 섞이고 description 이 빠진 라벨
const BAD = [
"---",
"name: PR Review",
"model: sonnet",
"---",
"",
"When writing a PR description, run git diff first.",
].join("\n");
[
["통과 · codebase-onboarding", GOOD],
["위반A · 한 줄로 붕괴한 라벨", COLLAPSED],
["위반B · 이름 규칙 위반 + 설명 누락", BAD],
].forEach(function (pair) {
const problems = validate(parseFrontmatter(pair[1]));
console.log(pair[0] + " → " + (problems.length ? problems.join(" / ") : "표준과 일치"));
});
다음 장에서는 스킬을 Claude Code의 다른 조정 방법들 — CLAUDE.md, 서브에이전트(subagents), 훅(hooks), MCP 서버 — 과 비교합니다. 상황마다 어떤 도구를 고르면 좋을지 정리합니다.