본문 바로가기

개발/Claude Code

[Claude Code] 스킬(Skill) (7)

실습 목표: 매번 길게 입력하던 지시를 /<스킬 이름> 하나로 부를 수 있게 만든다.

 

Step 1. 스킬이란 무엇인가?

스킬은 자주 쓰는 지시를 파일로 저장해둔 것이다. 

폴더 하나와 그 안의 SKILL.md 파일 하나로 이루어져 있고, 폴더 이름이 곧 스킬 이름이 된다.

.claude/skills/tdd/SKILL.md   →   /tdd 로 실행

 

 

Step 2. 스킬 만들기

다음 명령어를 터미널에 입력하여 실습에 사용할 스킬을 만든다.

cd ~/shop-api && mkdir -p .claude/skills/tdd
cat > .claude/skills/tdd/SKILL.md <<'EOF'
---
description: TDD 순서로 기능을 추가한다. 실패하는 테스트를 먼저 작성하고, 구현으로 통과시킨다.
argument-hint: [추가할 기능 설명]
disable-model-invocation: true
---

$ARGUMENTS 기능을 아래 순서로 추가한다.

1. tests/ 에 실패하는 테스트를 먼저 작성한다. 구현 코드(app/)는 이 단계에서 건드리지 않는다.
2. `pytest -q` 를 실행해서 새 테스트가 실제로 실패하는지 확인하고, 그 결과를 보고한다.
3. 여기서 멈추고 사용자의 승인을 기다린다.
4. 승인을 받으면 구현 코드를 수정한다. 테스트 파일은 수정하지 않는다.
5. 전부 통과할 때까지 pytest 실행과 코드 수정을 반복한다.
EOF

 

이제 SKILL.md 파일의 구조를 살펴보자.

 

--- 로 둘러싸인 부분을 프론트매터(frontmatter) 라고 한다. 
스킬 자체에 대한 설정을 적는 곳이고, 클로드에게 주는 지시가 아니다.

항목 뜻
description 이 스킬이 무엇을 하는지.
클로드가 자동으로 스킬을 부를지 판단할 때 씀
argument-hint 입력창에서 자동완성될 때 보여줄 안내 문구
disable-model-invocation: true 클로드가 스킬을 알아서 부르지 못하게 막음. 
사용자가 /tdd를 직접 입력할 때만 실행

 

--- 아래가 본문이고, 이 부분이 실제로 클로드에게 전달되는 지시이다.

 

disable-model-invocation을 활성화한 이유는 default 값으로 두면 클로드가 "지금 이 스킬이 필요하겠다"고 판단해서 스스로 실행할 수 있다. 
따라서 TDD 절차처럼 시작 시점을 사용자가 정해야 하는 작업에는 맞지 않기 때문에 해당 옵션을 활성화 한다.

 

Step 3. 스킬 실행해보기

이제 프롬프트 박스에 /tdd를 입력하면 tdd 스킬이 보일 것이다.

 

이제 다음 프롬프트를 클로드에게 보낸다.

/tdd 주문 금액이 0원 이하이면 ValueError를 발생시키는 검증

 

SKILL.md의 $ARGUMENTS는 명령 뒤에 입력한 텍스트로 바뀌는 자리표시자이다. 
위 프롬프트를 보내면 클로드는 이런 지시를 받는다.

주문 금액이 0원 이하이면 ValueError를 발생시키는 검증 기능을 아래 순서로 추가한다.

1. tests/ 에 실패하는 테스트를 먼저 작성한다. 구현 코드(app/)는 이 단계에서 건드리지 않는다.
...

 

클로드의 답변을 확인해 보면

스킬 본문의 내용대로 구현으로 넘어가기 전에 사용자에게 승인을 요청하는 것을 볼 수 있다.

 

Step 4. 명령 실행 결과를 프롬프트에 넣기

본문에 다음과 같은 형태로 작성하면, 클로드가 프롬프트 내용을 읽기 전에 그 명령이 먼저 실행되고 출력이 그 자리에 채워진다.

!`명령어`

 

두 번째 스킬을 만들어 확인해 보자.

 

다음 명령어를 터미널에 입력하여 실습에 사용할 두 번째 스킬을 만든다.

cd ~/shop-api && mkdir -p .claude/skills/changes
cat > .claude/skills/changes/SKILL.md <<'EOF'
---
description: 아직 커밋하지 않은 변경사항을 요약한다.
allowed-tools: Bash(git diff *) Bash(git status *)
---

## 현재 변경사항

!`git diff HEAD`

## 지시

위 변경사항을 두세 개의 항목으로 요약한다.
변경사항이 없으면 없다고만 답한다.
EOF

 

그 다음 예를 들어, 다음과 같이 pricing.py 코드 밑에 다음과 같은 주석을 달아 커밋하지 않은 변경을 만든 뒤 

 

다음 프롬프트를 클로드에게 보낸다.

/changes

 

그러면

 

git diff HEAD 명령에 대한 출력이 이미 프롬프트 내용 안에 들어간 채로 클로드에 전달됐기 때문에 클로드는 파일을 읽기 위한 READ 도구를 호출하지 않고 답변을 한다. 

 

여기서 allowed-tools는 무엇인가?

다음과 같은 스킬 파일의 설정이 있다고 하면

allowed-tools: Bash(git diff *) Bash(git status *)

이 스킬(changes)을 실행하는 동안 git diff와 git status를 승인 없이 쓸 수 있도록 해준다.

이 스킬을 부른 그 순간에만 적용되고, 다음 메시지를 보낼때는 해제된다.

 

주의할 점은 작성한 !`명령어`가 허용되지 않은 명령어라면 사용자의 승인 자체를 물어보지 않고 그냥 스킬 실행 자체가 중단된다. 
그래서 allowed-tools로 미리 허용해두는 것이다.

 

Step 5. 스킬 적용 범위

위치 범위
~/.claude/skills/<스킬 이름>/SKILL.md 내 모든 프로젝트에서 사용
.claude/skills/<스킬 이름>/SKILL.md 이 프로젝트에서만 사용

 

 

Step 6. CLAUDE.md와 스킬의 차이

둘 다 지시를 파일에 저장하는 것이지만 쓰임이 다르다.

  CLAUDE.md 스킬
언제 전달되나 모든 대화에 자동으로 /이름 을 입력했을 때만
담는 내용 항상 지켜야 할 규칙 특정 작업의 절차
컨텍스트 비용 항상 차지함 부를 때만 차지함

 

판단 기준: 항상 필요한가, 그 작업을 할 때만 필요한가.

 

 

핵심 정리

1. 스킬은 자주 쓰는 지시를 저장한 파일이다.
폴더 하나와 그 안의 SKILL.md. 폴더 이름이 스킬 이름이 된다.

2. 파일은 두 부분으로 나뉜다.
--- 사이의 프론트매터는 스킬 설정, 그 아래 본문은 클로드에게 전달되는 지시.

3. disable-model-invocation: true는 실행 시점을 사용자가 정하게 한다.
클로드가 알아서 부르지 못하게 막는다. 배포, 커밋, 절차 시작처럼 시점이 중요한 작업에 쓴다.

4. $ARGUMENTS는 명령 뒤에 입력한 텍스트로 바뀐다.
같은 절차를 다른 대상에 반복 적용할 수 있다.

5. !`명령어`는 명령 실행 결과를 프롬프트에 미리 채워 넣는다.
클로드는 명령어가 아니라 출력을 받는다. 부를 때마다 최신 결과가 들어간다.

6. !`명령어`는 승인을 묻지 않고, 막히면 스킬 전체가 중단된다.
그래서 allowed-tools로 미리 허용해둔다.

7. 스킬 위치가 사용 범위를 정한다.
~/.claude/skills/는 모든 프로젝트, .claude/skills/는 그 프로젝트만. 후자는 git으로 팀과 공유된다.

8. CLAUDE.md와의 구분 기준은 "항상 필요한가"이다.
항상 지킬 규칙은 CLAUDE.md, 특정 작업의 절차는 스킬.