Source reviewed8a1541c4a3ff
스킬 크리에이터
스크립트, 참조 및 자산이 포함된 재사용 가능한 기술의 범위 지정, 구조화 및 패키징을 위한 상담원 기술 수명 주기 가이드입니다.
Anthropic · Skill Creator
Existing editorial guidance is preserved. The current pinned official reference is separately labelled in English; translated editorial is not a new translation of the full source.
This is the existing editorial translation. The latest full official reference, where available, is provided separately in English.
The navigation uses English labels. Article languages are shown separately; the interface is not a full translation of the documentation.
Source text is documentation. These workflows have not been executed or tested by this site.
On this page
새로운 기술을 창출하고 이를 반복적으로 향상시키는 기술입니다.
높은 수준에서 기술을 만드는 과정은 다음과 같습니다.
- 기술로 수행할 작업과 대략적인 수행 방법을 결정합니다.
- 스킬 초안 작성
- 몇 가지 테스트 프롬프트를 만들고 여기에 clude-with-access-to-the-skill을 실행하세요.
- 사용자가 결과를 정성적, 정량적으로 평가할 수 있도록 지원
- 실행이 백그라운드에서 수행되는 동안 정량적 평가가 없는 경우 몇 가지 정량적 평가 초안을 작성합니다(있는 경우 있는 그대로 사용하거나 변경이 필요하다고 생각되면 수정할 수 있습니다). 그런 다음 사용자에게 설명합니다(또는 이미 존재하는 경우 이미 존재하는 것을 설명).
eval-viewer/generate_review.py스크립트를 사용하여 사용자가 볼 수 있는 결과를 보여주고 정량적 측정항목도 볼 수 있도록 하세요.
- 사용자의 결과 평가 피드백을 기반으로 스킬을 다시 작성합니다(또한 정량적 벤치마크에서 명백하게 드러나는 결함이 있는 경우).
- 만족할 때까지 반복하세요.
- 테스트 세트를 확장하고 더 큰 규모로 다시 시도하세요.
이 기술을 사용할 때 귀하의 임무는 사용자가 이 프로세스의 어느 위치에 있는지 파악한 다음 뛰어들어 이러한 단계를 진행하도록 돕는 것입니다. 예를 들어, "X를 위한 스킬을 만들고 싶어요"와 같은 것일 수도 있습니다. 의미를 좁히고, 초안을 작성하고, 테스트 사례를 작성하고, 평가 방법을 파악하고, 모든 프롬프트를 실행하고, 반복하는 데 도움을 줄 수 있습니다.
반면에 그들은 이미 기술 초안을 가지고 있을 수도 있습니다. 이 경우 루프의 평가/반복 부분으로 바로 이동할 수 있습니다.
물론, 항상 유연해야 하며 사용자가 "많은 평가를 실행할 필요가 없습니다. 그냥 저와 함께 느낌을 주세요"와 같은 경우 대신 그렇게 할 수 있습니다.
그런 다음 스킬이 완료된 후(순서는 유연함) 스킬 트리거를 최적화하기 위해 완전히 별도의 스크립트가 있는 스킬 설명 개선 프로그램을 실행할 수도 있습니다.
멋지나요? 시원한.
사용자와의 소통
스킬 크리에이터는 코딩 전문 용어에 대해 폭넓게 익숙한 사람들이 사용할 수 있습니다. 아직 들어보지 못했다면(어떻게 그럴 수 있었는지, 시작된 지 아주 최근에야) Claude의 힘이 배관공에게 터미널을 열도록 영감을 주고 부모와 조부모가 Google에서 "npm 설치 방법"을 검색하는 추세가 있습니다. 반면에, 대부분의 사용자는 아마도 컴퓨터에 능숙할 것입니다.
따라서 의사소통 방법을 이해하려면 상황 신호에 주의를 기울이십시오! 기본 사례에서는 몇 가지 아이디어를 제공합니다.
- '평가'와 '벤치마크'는 경계선이지만 OK
- "JSON" 및 "어설션"의 경우 설명 없이 사용하기 전에 해당 항목이 무엇인지 알고 있다는 사용자의 심각한 단서를 보고 싶습니다.
의심스러운 경우 용어를 간략하게 설명해도 괜찮고, 사용자가 이해할 수 있을지 확실하지 않은 경우 짧은 정의로 용어를 명확하게 설명해도 됩니다.
스킬 만들기
캡처 의도
사용자의 의도를 이해하는 것부터 시작하세요. 현재 대화에는 사용자가 캡처하려는 워크플로가 이미 포함되어 있을 수 있습니다(예: "이것을 기술로 전환"이라고 말합니다). 그렇다면 먼저 대화 기록에서 답변(사용된 도구, 단계 순서, 사용자가 수정한 사항, 관찰된 입력/출력 형식)을 추출하세요. 사용자는 공백을 메워야 할 수 있으며 다음 단계를 진행하기 전에 확인해야 합니다.
- 이 기술을 통해 Claude는 무엇을 할 수 있습니까?
- 이 스킬은 언제 발동해야 합니까? (사용자 문구/컨텍스트)
- 예상되는 출력 형식은 무엇입니까?
- 기술이 작동하는지 확인하기 위해 테스트 사례를 설정해야 합니까? 객관적으로 검증 가능한 출력(파일 변환, 데이터 추출, 코드 생성, 고정된 워크플로 단계)을 갖춘 기술은 테스트 사례의 이점을 얻습니다. 주관적인 결과물(작문 스타일, 예술)을 갖춘 기술에는 종종 이러한 기술이 필요하지 않습니다. 기술 유형에 따라 적절한 기본값을 제안하되 결정은 사용자에게 맡기십시오.
인터뷰 및 연구
극단적인 사례, 입력/출력 형식, 예제 파일, 성공 기준 및 종속성에 대해 사전에 질문하세요. 이 부분이 해결될 때까지 테스트 프롬프트 작성을 기다리십시오.
사용 가능한 MCP 확인 - 연구에 유용한 경우(문서 검색, 유사한 기술 찾기, 모범 사례 검색), 가능한 경우 하위 에이전트를 통해 병렬로 연구하고, 그렇지 않으면 인라인으로 연구합니다. 사용자의 부담을 줄이기 위해 컨텍스트를 준비하세요.
SKILL.md를 작성하세요.
사용자 인터뷰를 기반으로 다음 구성 요소를 작성합니다.
- 이름: 스킬 식별자
- 설명: 트리거 시기 및 수행 작업. 이것이 기본 트리거 메커니즘입니다. 스킬이 수행하는 작업과 스킬을 언제 사용해야 하는지에 대한 특정 컨텍스트를 모두 포함합니다. 모든 "사용 시기" 정보는 본문이 아닌 여기에 있습니다. 참고: 현재 Claude는 스킬이 유용할 때 사용하지 않는 "미발동" 경향이 있습니다. 이 문제를 해결하려면 스킬 설명을 약간 "강제"하게 만드세요. 따라서 예를 들어 "내부 인류 데이터를 표시하기 위해 간단하고 빠른 대시보드를 구축하는 방법" 대신 "내부 인류 데이터를 표시하기 위해 간단하고 빠른 대시보드를 구축하는 방법"이라고 쓸 수 있습니다. 사용자가 대시보드, 데이터 시각화, 내부 지표를 언급하거나 '대시보드'를 명시적으로 요청하지 않더라도 모든 종류의 회사 데이터를 표시하고 싶을 때마다 이 기술을 사용하세요."
- 호환성: 필수 도구, 종속성(선택 사항, 거의 필요하지 않음)
- 나머지 스킬:)
스킬 라이팅 가이드
스킬 분석
skill-name/
SKILL.md (required)
YAML frontmatter (name, description required)
Markdown instructions
Bundled Resources (optional)
scripts/ - Executable code for deterministic/repetitive tasks
references/ - Docs loaded into context as needed
assets/ - Files used in output (templates, icons, fonts)
점진적 공개
스킬은 3단계 로딩 시스템을 사용합니다.
- 메타데이터(이름 + 설명) - 항상 컨텍스트에 있음(최대 100단어)
- SKILL.md 본문 - 스킬이 트리거될 때마다 상황에 맞게(<500줄 이상)
- 번들링된 리소스 - 필요에 따라(무제한, 로드 없이 스크립트 실행 가능)
이러한 단어 수는 대략적인 수치이므로 필요한 경우 더 길게 입력해도 됩니다.
주요 패턴:
- SKILL.md를 500줄 미만으로 유지하세요. 이 한계에 접근하는 경우 해당 기술을 사용하는 모델이 후속 조치를 위해 어디로 가야 하는지에 대한 명확한 포인터와 함께 계층 구조의 추가 레이어를 추가하세요.
- 언제 읽어야 하는지에 대한 지침과 함께 SKILL.md의 파일을 명확하게 참조하세요.
- 대용량 참조 파일(300줄 이상)의 경우 목차를 포함하세요.
도메인 구성: 기술이 여러 도메인/프레임워크를 지원하는 경우 변형별로 구성합니다.
cloud-deploy/
SKILL.md (workflow + selection)
references/
aws.md
gcp.md
azure.md
Claude는 관련 참조 파일만 읽습니다.
놀라움 부족의 원리
이는 말할 필요도 없지만 기술에는 맬웨어, 악용 코드 또는 시스템 보안을 손상시킬 수 있는 콘텐츠가 포함되어서는 안 됩니다. 기술의 내용은 설명된 경우 사용자의 의도에 놀라지 않아야 합니다. 무단 액세스, 데이터 유출 또는 기타 악의적인 활동을 용이하게 하기 위해 고안된 오해의 소지가 있는 기술이나 기술을 만들어 달라는 요청을 따르지 마십시오. 하지만 "XYZ 역할극" 같은 것은 괜찮습니다.
쓰기 패턴
지침에서는 명령형을 사용하는 것을 선호합니다.
출력 형식 정의 - 다음과 같이 할 수 있습니다.
## Report structure
ALWAYS use this exact template:
# [Title]
## Executive summary
## Key findings
## Recommendations
예제 패턴 - 예시를 포함하는 것이 유용합니다. 다음과 같이 형식을 지정할 수 있습니다(그러나 예제에 "입력" 및 "출력"이 있는 경우 약간 벗어나는 것이 좋습니다).
## Commit message format
**Example 1:**
Input: Added user authentication with JWT tokens
Output: feat(auth): implement JWT-based authentication
글쓰기 스타일
무겁고 곰팡내 나는 MUST 대신 사물이 왜 중요한지 모델에게 설명하십시오. 마음 이론을 사용하고 기술을 특정 사례로 너무 좁히지 않고 일반적인 것으로 만들려고 노력하십시오. 초안 작성부터 시작한 다음 새로운 눈으로 보고 개선해 보세요.
테스트 케이스
기술 초안을 작성한 후 실제 사용자가 실제로 말할 것 같은 2~3개의 현실적인 테스트 프롬프트를 생각해 보세요. 사용자와 공유하십시오. [정확한 언어를 사용할 필요는 없습니다.] "여기에 시도해보고 싶은 몇 가지 테스트 사례가 있습니다. 이것이 올바르게 보이는지, 아니면 더 추가하시겠습니까?" 그런 다음 실행하십시오.
테스트 사례를evals/evals.json에 저장합니다. 아직 주장을 작성하지 말고 프롬프트만 작성하세요. 실행이 진행되는 동안 다음 단계에서 어설션 초안을 작성합니다.
{
"skill_name": "example-skill",
"evals": [
{
"id": 1,
"prompt": "User's task prompt",
"expected_output": "Description of expected result",
"files": []
}
]
}
전체 스키마(나중에 추가할assertions필드 포함)는references/schemas.md를 참조하세요.
테스트 케이스 실행 및 평가
이 섹션은 하나의 연속적인 시퀀스입니다. 중간에 멈추지 마세요./skill-test또는 기타 테스트 기술을 사용하지 마십시오.
<skill-name>-workspace/에 결과를 기술 디렉터리의 형제로 넣습니다. 작업 공간 내에서 반복(iteration-1/,iteration-2/등)별로 결과를 구성하고 그 내에서 각 테스트 사례에 디렉터리(eval-0/,eval-1/등)가 제공됩니다. 이 모든 것을 미리 만들지 말고 진행하면서 디렉터리를 만드십시오.
1단계: 같은 턴에 모든 실행(스킬 포함 및 기준선 포함) 생성
각 테스트 사례에 대해 동일한 턴에 두 개의 하위 에이전트를 생성합니다. 하나는 스킬이 있고 다른 하나는 스킬이 없습니다. 이는 중요합니다. 스킬이 있는 실행을 먼저 생성한 다음 나중에 기준선을 위해 다시 돌아오지 마십시오. 모든 것을 한 번에 실행하면 거의 같은 시간에 완료됩니다.
스킬 달리기:
Execute this task:
- Skill path: <path-to-skill>
- Task: <eval prompt>
- Input files: <eval files if any, or "none">
- Save outputs to: <workspace>/iteration-<N>/eval-<ID>/with_skill/outputs/
- Outputs to save: <what the user cares about - e.g., "the .docx file", "the final CSV">
기준 실행(동일한 프롬프트이지만 기준은 상황에 따라 다름):
- 새 스킬 만들기: 스킬이 전혀 없습니다. 동일한 프롬프트, 기술 경로 없음,
without_skill/outputs/에 저장합니다. - 기존 스킬 개선: 이전 버전. 편집하기 전에 스킬(
cp -r <skill-path> <workspace>/skill-snapshot/)의 스냅샷을 찍은 다음 스냅샷에서 기준 하위 에이전트를 가리킵니다.old_skill/outputs/에 저장합니다.
각 테스트 케이스에 대해eval_metadata.json를 작성합니다(지금은 어설션이 비어 있을 수 있음). 단순히 "eval-0"이 아닌 테스트 대상을 기반으로 각 평가에 설명적인 이름을 지정합니다. 디렉토리에도 이 이름을 사용하십시오. 이 반복에서 새 평가 프롬프트나 수정된 평가 프롬프트를 사용하는 경우 각각의 새 평가 디렉터리에 대해 이러한 파일을 생성하세요. 이전 반복에서 가져온다고 가정하지 마세요.
{
"eval_id": 0,
"eval_name": "descriptive-name-here",
"prompt": "The user's task prompt",
"assertions": []
}
2단계: 실행이 진행되는 동안 초안 어설션
실행이 끝날 때까지 기다리지 마십시오. 이 시간을 생산적으로 사용할 수 있습니다. 각 테스트 케이스에 대한 정량적 주장 초안을 작성하고 이를 사용자에게 설명합니다.evals/evals.json에 어설션이 이미 존재하는 경우 이를 검토하고 무엇을 확인하는지 설명하세요.
좋은 주장은 객관적으로 검증 가능하며 설명적인 이름을 가지고 있습니다. 결과를 보는 사람이 각 주장이 무엇을 확인하는지 즉시 이해할 수 있도록 벤치마크 뷰어에서 명확하게 읽어야 합니다. 주관적인 기술(작문 스타일, 디자인 품질)은 질적으로 더 잘 평가됩니다. 인간의 판단이 필요한 것에 대해 주장을 강요하지 마십시오.
초안이 작성된 어설션으로eval_metadata.json파일과evals/evals.json를 업데이트합니다. 또한 시청자에게 무엇이 표시되는지(정성적 결과와 정량적 벤치마크 모두) 사용자에게 설명합니다.
3단계: 실행이 완료되면 타이밍 데이터 캡처
각 하위 에이전트 작업이 완료되면total_tokens및duration_ms가 포함된 알림을 받습니다. 이 데이터를 실행 디렉터리의timing.json에 즉시 저장합니다.
{
"total_tokens": 84852,
"duration_ms": 23332,
"total_duration_seconds": 23.3
}
이는 이 데이터를 캡처할 수 있는 유일한 기회입니다. 이는 작업 알림을 통해 제공되며 다른 곳에는 유지되지 않습니다. 각 알림을 일괄 처리하는 대신 도착하는 대로 처리하세요.
4단계: 뷰어 채점, 집계 및 실행
모든 실행이 완료되면:
-
각 실행 평가 -
agents/grader.md를 읽고 출력에 대해 각 어설션을 평가하는 그레이더 하위 에이전트(또는 인라인 등급)를 생성합니다. 각 실행 디렉터리의grading.json에 결과를 저장합니다. grading.json 기대 배열은text,passed및evidence필드(name/met/details또는 기타 변형 아님)를 사용해야 합니다. 뷰어는 이러한 정확한 필드 이름에 따라 달라집니다. 프로그래밍 방식으로 확인할 수 있는 어설션의 경우 눈으로 확인하기보다는 스크립트를 작성하고 실행하세요. 스크립트는 더 빠르고 안정적이며 반복 전반에 걸쳐 재사용할 수 있습니다. -
벤치마크로 집계 - Skill-creator 디렉터리에서 집계 스크립트를 실행합니다.
python -m scripts.aggregate_benchmark <workspace>/iteration-N --skill-name <name>이는 평균 stddev 및 델타와 함께 각 구성에 대한 pass_rate, 시간 및 토큰을 포함하는
benchmark.json및benchmark.md를 생성합니다. benchmark.json을 수동으로 생성하는 경우 뷰어가 기대하는 정확한 스키마는references/schemas.md를 참조하세요. 각 with_skill 버전을 기준 버전 앞에 놓으십시오. -
분석가 통과 - 벤치마크 데이터를 읽고 집계 통계가 숨길 수 있는 패턴을 찾아보세요. 찾아야 할 내용은
agents/analyzer.md("벤치마크 결과 분석" 섹션)를 참조하세요. 기술(비차별), 높은 분산 평가(불안정할 수 있음) 및 시간/토큰 트레이드오프에 관계없이 항상 통과하는 어설션과 같은 것입니다. -
정성적 결과와 정량적 데이터가 모두 포함된 뷰어 실행:
nohup python <skill-creator-path>/eval-viewer/generate_review.py \ <workspace>/iteration-N \ --skill-name "my-skill" \ --benchmark <workspace>/iteration-N/benchmark.json \ > /dev/null 2>&1 & VIEWER_PID=$!2회 이상 반복의 경우
--previous-workspace <workspace>/iteration-<N-1>도 전달합니다.Cowork/headless 환경:
webbrowser.open()를 사용할 수 없거나 환경에 디스플레이가 없는 경우 서버를 시작하는 대신--static <output_path>를 사용하여 독립형 HTML 파일을 작성합니다. 사용자가 "모든 리뷰 제출"을 클릭하면 피드백이feedback.json파일로 다운로드됩니다. 다운로드 후 다음 반복을 위해feedback.json를 작업 공간 디렉터리에 복사합니다.
참고: 뷰어를 생성하려면 generate_review.py를 사용하세요. 사용자 정의 HTML을 작성할 필요가 없습니다.
- 사용자에게 다음과 같이 말하세요. "브라우저에서 결과를 열었습니다. 두 개의 탭이 있습니다. '출력'을 사용하면 각 테스트 사례를 클릭하고 피드백을 남길 수 있고, '벤치마크'를 사용하면 정량적 비교가 표시됩니다. 완료되면 여기로 돌아와 알려주세요."
사용자가 뷰어에서 보는 것
"출력" 탭에는 한 번에 하나의 테스트 사례가 표시됩니다.
- 프롬프트: 주어진 작업
- 출력: 기술이 생성하고 가능한 경우 인라인으로 렌더링된 파일
- 이전 출력(반복 2+): 마지막 반복의 출력을 표시하는 축소된 섹션
- 공식 성적(채점이 실행된 경우): 어설션 통과/실패를 표시하는 축소된 섹션
- 피드백: 입력과 동시에 자동 저장되는 텍스트 상자
- 이전 피드백(반복 2+): 지난번 댓글이 텍스트 상자 아래에 표시됩니다.
"벤치마크" 탭에는 평가별 분석 및 분석가 관찰과 함께 각 구성의 합격률, 타이밍 및 토큰 사용량과 같은 통계 요약이 표시됩니다.
탐색은 이전/다음 버튼이나 화살표 키를 통해 이루어집니다. 완료되면 "모든 리뷰 제출"을 클릭하여 모든 피드백을feedback.json에 저장합니다.
5단계: 피드백 읽기
사용자가 완료되었다고 말하면feedback.json를 읽어보세요.
{
"reviews": [
{"run_id": "eval-0-with_skill", "feedback": "the chart is missing axis labels", "timestamp": "..."},
{"run_id": "eval-1-with_skill", "feedback": "", "timestamp": "..."},
{"run_id": "eval-2-with_skill", "feedback": "perfect, love this", "timestamp": "..."}
],
"status": "complete"
}
빈 피드백은 사용자가 괜찮다고 생각했다는 의미입니다. 사용자가 특정 불만을 제기한 테스트 사례에 개선점을 집중하세요.
작업이 끝나면 뷰어 서버를 종료합니다.
kill $VIEWER_PID 2>/dev/null
스킬 향상
이것이 루프의 핵심입니다. 테스트 사례를 실행했고 사용자가 결과를 검토했으며 이제 피드백을 기반으로 기술을 개선해야 합니다.
개선을 생각하는 방법
-
피드백을 통해 일반화합니다. 여기서 일어나는 큰 그림은 우리가 다양한 프롬프트에서 백만 번(문자 그대로, 어쩌면 더 많이) 사용할 수 있는 기술을 만들려고 노력하고 있다는 것입니다. 여기에서는 더 빠르게 진행하는 데 도움이 되기 때문에 귀하와 사용자는 몇 가지 예만 반복해서 반복하고 있습니다. 사용자는 이러한 예를 안팎으로 알고 있으며 새로운 출력을 빠르게 평가할 수 있습니다. 그러나 당신과 사용자가 공동 개발하는 기술이 해당 예제에만 작동한다면 그것은 쓸모가 없습니다. 까다로운 문제가 있는 경우 지나치게 과적합된 변경을 적용하거나 억압적으로 제한하는 MUST를 적용하는 대신 다른 은유를 사용하거나 다른 작업 패턴을 권장해 볼 수 있습니다. 시도하는 것은 상대적으로 저렴하며 아마도 뭔가 훌륭한 일을 할 수 있을 것입니다.
-
즉시 간결하게 유지하세요. 무게를 끌지 못하는 것들을 제거하세요. 최종 출력뿐만 아니라 기록도 읽어야 합니다. 기술로 인해 모델이 비생산적인 작업을 수행하는 데 많은 시간을 낭비하게 만드는 것처럼 보이면 해당 기술의 일부를 제거하고 무슨 일이 일어나는지 확인할 수 있습니다.
-
이유를 설명하세요. 모델에게 요청하는 모든 것 뒤에 있는 이유를 설명하기 위해 열심히 노력하세요. 오늘날의 LLM은 스마트합니다. 그들은 좋은 마음 이론을 가지고 있으며, 좋은 도구가 제공되면 기계적인 지시를 뛰어넘어 실제로 일을 실현할 수 있습니다. 사용자의 피드백이 간결하거나 답답하더라도 실제로 작업을 이해하고 사용자가 작성한 내용을 왜 작성하는지, 실제로 작성한 내용을 이해하도록 노력한 다음 이러한 이해를 지침에 전달하십시오. ALWAYS 또는 NEVER를 모두 대문자로 쓰거나 매우 견고한 구조를 사용하는 경우 이는 노란색 플래그입니다. 가능하다면 모델이 요청하는 사항이 왜 중요한지 이해할 수 있도록 추론을 재구성하고 설명하세요. 이는 보다 인도적이고 강력하며 효과적인 접근 방식입니다.
-
테스트 사례 전체에서 반복되는 작업을 찾아보세요. 테스트 실행의 기록을 읽고 하위 에이전트가 모두 독립적으로 유사한 도우미 스크립트를 작성했는지 또는 무언가에 대해 동일한 다단계 접근 방식을 취했는지 확인합니다. 3가지 테스트 사례 모두 하위 에이전트가
create_docx.py또는build_chart.py를 작성하는 결과를 가져온 경우 이는 기술이 해당 스크립트를 번들로 묶어야 한다는 강력한 신호입니다. 한번 작성해서scripts/에 넣고 스킬에게 사용하라고 알려주세요. 이렇게 하면 향후 모든 호출에서 바퀴를 재발명하지 않아도 됩니다.
이 작업은 매우 중요하며(우리는 여기서 연간 수십억 달러의 경제적 가치를 창출하려고 노력하고 있습니다!) 생각하는 시간이 방해가 되지 않습니다. 시간을 갖고 정말 곰곰이 생각해 보세요. 초안 개정판을 작성한 다음 다시 살펴보고 개선하는 것이 좋습니다. 사용자의 머리 속으로 들어가 그들이 원하고 필요한 것이 무엇인지 이해하기 위해 최선을 다하십시오.
반복 루프
스킬을 향상시킨 후:
- 기술에 개선 사항을 적용하십시오.
- 기준 실행을 포함하여 모든 테스트 사례를 새로운
iteration-<N+1>/디렉터리로 다시 실행합니다. 새 기술을 생성하는 경우 기준은 항상without_skill(기술 없음)입니다. 이는 반복 전반에 걸쳐 동일하게 유지됩니다. 기존 기술을 개선하는 경우 기준으로 적합한 것이 무엇인지 판단하십시오(사용자가 사용한 원래 버전 또는 이전 반복). - 이전 반복을 가리키는
--previous-workspace를 사용하여 리뷰어를 시작합니다. - 사용자가 검토하고 완료되었다고 말할 때까지 기다립니다.
- 새로운 피드백을 읽고, 다시 개선하고, 반복하세요
다음까지 계속 진행하세요.
- 사용자가 행복하다고 말합니다.
- 피드백이 다 비어있습니다(다 괜찮아 보이네요)
- 의미 있는 진전을 이루지 못하고 있습니다.
고급: 블라인드 비교
두 가지 버전의 기술을 보다 엄격하게 비교하려는 경우(예: 사용자가 "새 버전이 실제로 더 나은가요?"라고 묻는 경우)에는 블라인드 비교 시스템이 있습니다. 자세한 내용은agents/comparator.md및agents/analyzer.md를 읽어보세요. 기본 아이디어는 어느 것이 어느 것인지 알려주지 않고 독립 에이전트에 두 개의 출력을 제공하고 품질을 판단하도록 하는 것입니다. 그런 다음 승자가 승리한 이유를 분석해 보세요.
이는 선택 사항이며 하위 에이전트가 필요하며 대부분의 사용자에게는 필요하지 않습니다. 일반적으로 사람의 검토 루프로 충분합니다.
설명 최적화
SKILL.md 앞부분의 설명 필드는 Claude가 스킬을 호출하는지 여부를 결정하는 기본 메커니즘입니다. 스킬을 생성하거나 개선한 후 더 나은 트리거 정확도를 위해 설명을 최적화하도록 제안하십시오.
1단계: 트리거 평가 쿼리 생성
트리거해야 하는 쿼리와 트리거하지 말아야 하는 쿼리를 혼합하여 20개의 평가 쿼리를 만듭니다. JSON으로 저장:
[
{"query": "the user prompt", "should_trigger": true},
{"query": "another prompt", "should_trigger": false}
]
쿼리는 현실적이어야 하며 Claude Code 또는 Claude.ai 사용자가 실제로 입력하는 내용이어야 합니다. 추상적인 요청이 아니라 구체적이고 구체적이며 상당한 양의 세부정보가 포함된 요청입니다. 예를 들어 파일 경로, 사용자의 직업이나 상황에 대한 개인적인 맥락, 열 이름과 값, 회사 이름, URL 등이 있습니다. 약간의 뒷이야기. 일부는 소문자이거나 약어, 오타 또는 일상적인 말이 포함되어 있을 수 있습니다. 다양한 길이를 혼합하여 사용하고 명확하게 만드는 대신 극단적인 사례에 집중하세요(사용자가 승인할 기회를 얻습니다).
불량:"Format this data","Extract text from PDF","Create a chart"
좋음:"ok so my boss just sent me this xlsx file (its in my downloads, called something like 'Q4 sales final FINAL v2.xlsx') and she wants me to add a column that shows the profit margin as a percentage. The revenue is in column C and costs are in column D i think"
트리거해야 함 쿼리(8-10)의 경우 적용 범위를 고려하세요. 동일한 의도를 가진 다른 표현을 원합니다. 일부는 격식을 차리고 일부는 캐주얼하게 표현합니다. 사용자가 기술이나 파일 형식의 이름을 명시적으로 지정하지 않지만 분명히 필요한 경우를 포함합니다. 이 기술이 다른 기술과 경쟁하지만 승리해야 하는 몇 가지 흔하지 않은 사용 사례와 사례를 던져보세요.
트리거해서는 안 되는 쿼리(8-10)의 경우 가장 가치 있는 쿼리는 기술과 키워드 또는 개념을 공유하지만 실제로는 다른 것이 필요한 쿼리인 아차 실패입니다. 인접한 도메인, 순진한 키워드 일치가 실행되지만 실행되어서는 안 되는 모호한 표현, 쿼리가 기술이 수행하는 작업을 다루지만 다른 도구가 더 적합한 상황에서 발생하는 경우를 생각해 보세요.
피해야 할 핵심 사항: 트리거하면 안 되는 쿼리를 분명히 관련성이 없게 만들지 마세요. PDF 기술에 대한 부정적인 테스트로서 "피보나치 함수 작성"은 너무 쉽습니다. 아무것도 테스트하지 않습니다. 부정적인 사례는 정말로 까다로워야 합니다.
2단계: 사용자와 함께 검토
HTML 템플릿을 사용하여 검토할 수 있도록 평가 세트를 사용자에게 제공합니다.
assets/eval_review.html에서 템플릿 읽기- 자리 표시자를 교체합니다.
__EVAL_DATA_PLACEHOLDER__-> 평가 항목의 JSON 배열(따옴표 없음 - JS 변수 할당)__SKILL_NAME_PLACEHOLDER__-> 스킬 이름__SKILL_DESCRIPTION_PLACEHOLDER__-> 스킬의 현재 설명
- 임시 파일(예:
/tmp/eval_review_<skill-name>.html)에 쓰고 엽니다:open /tmp/eval_review_<skill-name>.html - 사용자는 쿼리를 편집하고, 트리거해야 하는 항목을 전환하고, 항목을 추가/제거한 다음 "평가 세트 내보내기"를 클릭할 수 있습니다.
- 파일이
~/Downloads/eval_set.json에 다운로드됩니다. 파일이 여러 개인 경우(예:eval_set (1).json) 다운로드 폴더에서 최신 버전을 확인하세요.
이 단계는 중요합니다. 잘못된 평가 쿼리는 잘못된 설명으로 이어집니다.
3단계: 최적화 루프 실행
사용자에게 다음과 같이 말합니다. "시간이 좀 걸립니다. 백그라운드에서 최적화 루프를 실행하고 주기적으로 확인하겠습니다."
평가 세트를 작업 공간에 저장한 후 백그라운드에서 실행합니다.
python -m scripts.run_loop \
--eval-set <path-to-trigger-eval.json> \
--skill-path <path-to-skill> \
--model <model-id-powering-this-session> \
--max-iterations 5 \
--verbose
시스템 프롬프트(현재 세션을 지원하는 모델)의 모델 ID를 사용하여 트리거 테스트가 사용자가 실제로 경험하는 것과 일치하도록 합니다.
실행되는 동안 주기적으로 출력을 추적하여 반복이 진행 중인 것과 점수가 어떻게 보이는지에 대한 업데이트를 사용자에게 제공합니다.
이는 전체 최적화 루프를 자동으로 처리합니다. 평가 세트를 60% 학습 및 40% 유지 테스트로 분할하고 현재 설명을 평가한 다음(신뢰할 수 있는 트리거 속도를 얻기 위해 각 쿼리를 3번 실행) Claude를 호출하여 실패한 항목을 기반으로 개선 사항을 제안합니다. 학습과 테스트 모두에서 각각의 새로운 설명을 재평가하여 최대 5회 반복합니다. 완료되면 반복당 결과를 표시하는 HTML 보고서를 브라우저에서 열고best_description와 함께 JSON을 반환합니다. 이는 과적합을 방지하기 위해 훈련 점수가 아닌 테스트 점수로 선택됩니다.
스킬 발동 방식
트리거링 메커니즘을 이해하면 더 나은 평가 쿼리를 설계하는 데 도움이 됩니다. 기술은 이름 + 설명과 함께 Claude의available_skills목록에 표시되며 Claude는 해당 설명을 기반으로 기술을 참조할지 여부를 결정합니다. 알아야 할 중요한 점은 Claude가 자체적으로 쉽게 처리할 수 없는 작업에 대해서만 기술을 참조한다는 것입니다. "이 PDF 읽기"와 같은 간단한 1단계 쿼리는 설명이 완벽하게 일치하더라도 Claude가 기본 도구를 사용하여 직접 처리할 수 있기 때문에 기술을 트리거하지 않을 수 있습니다. 설명이 일치하면 복잡하거나 다단계 또는 특수 쿼리가 기술을 안정적으로 트리거합니다.
이는 평가 쿼리가 Claude가 실제로 기술 컨설팅을 통해 이익을 얻을 수 있을 만큼 충분히 실질적이어야 함을 의미합니다. "파일 X 읽기"와 같은 간단한 쿼리는 좋지 않은 테스트 사례입니다. 설명 품질에 관계없이 기술을 트리거하지 않습니다.
4단계: 결과 적용
JSON 출력에서best_description를 가져와 스킬의 SKILL.md 앞부분을 업데이트합니다. 사용자에게 전후를 보여주고 점수를 보고합니다.
패키지 및 선물(present_files도구를 사용할 수 있는 경우에만)
present_files도구에 대한 액세스 권한이 있는지 확인하세요. 그렇지 않은 경우 이 단계를 건너뛰세요. 그렇게 하는 경우 기술을 패키지하고.skill 파일을 사용자에게 제공합니다.
python -m scripts.package_skill <path/to/skill-folder>
패키징한 후 사용자가 설치할 수 있도록 결과.skill파일 경로를 안내합니다.
Claude.ai 관련 지침
Claude.ai의 핵심 워크플로는 동일하지만(초안 -> 테스트 -> 검토 -> 개선 -> 반복) Claude.ai에는 하위 에이전트가 없기 때문에 일부 메커니즘이 변경됩니다. 적응해야 할 사항은 다음과 같습니다.
테스트 사례 실행: 하위 에이전트가 없다는 것은 병렬 실행이 없음을 의미합니다. 각 테스트 사례에 대해 해당 기술의 SKILL.md를 읽은 다음 해당 지침에 따라 테스트 프롬프트를 직접 수행하세요. 한 번에 하나씩 수행하십시오. 이는 독립 하위 에이전트보다 덜 엄격하지만(스킬을 작성하고 실행하므로 전체 컨텍스트를 갖습니다) 유용한 온전성 검사이며 사람의 검토 단계가 보상합니다. 기준 실행을 건너뛰고 기술을 사용하여 요청한 대로 작업을 완료하세요.
결과 검토 중: 브라우저를 열 수 없는 경우(예: Claude.ai의 VM에 디스플레이가 없거나 원격 서버에 있는 경우) 브라우저 검토자를 완전히 건너뜁니다. 대신 대화에서 직접 결과를 제시하세요. 각 테스트 사례에 대해 프롬프트와 출력을 표시합니다. 출력이 사용자가 확인해야 하는 파일(예:.docx 또는.xlsx)인 경우 파일 시스템에 저장하고 사용자가 다운로드하고 검사할 수 있도록 위치를 알려줍니다. 인라인으로 피드백을 요청하세요. "이거 어때요? 변경할 사항이 있나요?"
벤치마킹: 정량적 벤치마킹을 건너뜁니다. 하위 에이전트 없이는 의미가 없는 기준 비교에 의존합니다. 사용자의 정성적인 피드백에 중점을 둡니다.
반복 루프: 이전과 동일합니다. 기술을 향상하고, 테스트 사례를 다시 실행하고, 피드백을 요청합니다. 중간에 브라우저 검토자가 없습니다. 결과가 있는 경우 파일 시스템의 반복 디렉터리에 결과를 구성할 수 있습니다.
설명 최적화: 이 섹션에는 Claude Code에서만 사용할 수 있는claudeCLI 도구(구체적으로claude -p)가 필요합니다. Claude.ai를 사용 중이라면 건너뛰세요.
블라인드 비교: 하위 에이전트가 필요합니다. 건너뛰세요.
패키징:package_skill.py스크립트는 Python 및 파일 시스템과 함께 어디서나 작동합니다. Claude.ai에서 이를 실행할 수 있으며 사용자는 결과.skill파일을 다운로드할 수 있습니다.
기존 기술 업데이트: 사용자가 새 기술을 만드는 것이 아니라 기존 기술을 업데이트하도록 요청할 수 있습니다. 이 경우:
- 원래 이름을 유지하세요. 스킬의 디렉터리 이름과
name머리말 필드를 기록해 두세요. 변경하지 않고 사용하세요. 예를 들어, 장착된 스킬이research-helper라면research-helper.skill(research-helper-v2아님)를 출력합니다. - 편집하기 전에 쓰기 가능한 위치에 복사하세요. 설치된 스킬 경로가 읽기 전용일 수 있습니다.
/tmp/skill-name/에 복사하고 거기에서 편집한 다음 복사본에서 패키지화합니다. - 수동으로 패키징하는 경우 먼저
/tmp/로 스테이지한 후 출력 디렉터리에 복사합니다. 권한으로 인해 직접 쓰기가 실패할 수 있습니다.
동료별 지침
Cowork를 사용하는 경우 알아야 할 주요 사항은 다음과 같습니다.
- 하위 에이전트가 있으므로 기본 워크플로(병렬로 테스트 사례 생성, 기준선 실행, 등급 지정 등)가 모두 작동합니다. (그러나 시간 초과로 인해 심각한 문제가 발생하는 경우 테스트 프롬프트를 병렬이 아닌 직렬로 실행하는 것이 좋습니다.)
- 브라우저나 디스플레이가 없으므로 평가 뷰어를 생성할 때 서버를 시작하는 대신
--static <output_path>를 사용하여 독립형 HTML 파일을 작성하세요. 그런 다음 사용자가 클릭하여 브라우저에서 HTML을 열 수 있는 링크를 제공합니다. - 어떤 이유로든 Cowork 설정은 Claude가 테스트 실행 후 평가 뷰어를 생성하는 것을 방해하는 것 같습니다. 따라서 다시 강조하자면 Cowork에 있든 Claude Code에 있든 테스트를 실행한 후
generate_review.py를 사용하여 기술을 직접 수정하고 수정을 시도하기 전에 항상 사람이 예제를 볼 수 있도록 평가 뷰어를 생성해야 합니다(자신의 부티크 HTML 코드를 작성하지 않음). 미리 죄송하지만 여기서는 대문자로 표시하겠습니다. 입력을 직접 평가하기 전에 평가자 뷰어를 생성하세요. 당신은 최대한 빨리 인간 앞에 그들을 데려오고 싶어합니다! - 피드백은 다르게 작동합니다. 실행 중인 서버가 없기 때문에 뷰어의 "모든 리뷰 제출" 버튼을 누르면
feedback.json가 파일로 다운로드됩니다. 그런 다음 거기에서 읽을 수 있습니다(먼저 액세스를 요청해야 할 수도 있음). - 패키징 작업 -
package_skill.py에는 Python과 파일 시스템만 필요합니다. - 설명 최적화(
run_loop.py/run_eval.py)는 브라우저가 아닌 하위 프로세스를 통해claude -p를 사용하므로 Cowork에서 제대로 작동해야 합니다. 하지만 스킬 만들기가 완전히 완료되고 사용자가 상태가 양호하다고 동의할 때까지 저장하세요. - 기존 기술 업데이트: 사용자가 새 기술을 만드는 것이 아니라 기존 기술을 업데이트하도록 요청할 수 있습니다. 위의 clude.ai 섹션에 있는 업데이트 지침을 따르세요.
참조 파일
Agents/ 디렉터리에는 특수 하위 에이전트에 대한 지침이 포함되어 있습니다. 관련 하위 에이전트를 생성해야 할 때 이를 읽으십시오.
agents/grader.md- 출력에 대한 어설션을 평가하는 방법agents/comparator.md- 두 출력 간의 블라인드 A/B 비교를 수행하는 방법agents/analyzer.md- 한 버전이 다른 버전보다 뛰어난 이유를 분석하는 방법
reference/ 디렉토리에는 추가 문서가 있습니다:
references/schemas.md- evals.json, grading.json 등에 대한 JSON 구조
강조하기 위해 여기서 핵심 루프를 한 번 더 반복합니다.
- 스킬이 무엇인지 알아보세요.
- 스킬 초안 작성 또는 편집
- 테스트 프롬프트에서 clude-with-access-to-the-skill 실행
- 사용자와 함께 출력을 평가합니다.
- benchmark.json을 만들고
eval-viewer/generate_review.py를 실행하여 사용자가 검토할 수 있도록 돕습니다. - 정량적 평가 실행
- benchmark.json을 만들고
- 귀하와 사용자가 만족할 때까지 반복하십시오.
- 최종 스킬을 패키징하여 사용자에게 반환합니다.
그런 일이 있으면 TodoList에 단계를 추가하여 잊지 않도록 하세요. Cowork를 사용하는 경우 TodoList에 "평가 JSON을 생성하고eval-viewer/generate_review.py를 실행하여 사람이 테스트 사례를 검토할 수 있도록"을 구체적으로 넣어서 이러한 일이 발생하는지 확인하세요.
행운을 빕니다!
리소스 파일
라이센스.txt
바이너리 리소스
에이전트/analyzer.md
바이너리 리소스
에이전트/비교기.md
바이너리 리소스
에이전트/grader.md
바이너리 리소스
자산/eval_review.html
바이너리 리소스
평가 뷰어/generate_review.py
eval-viewer/generate_review.py 다운로드
바이너리 리소스
평가-뷰어/viewer.html
바이너리 리소스
참조/schemas.md
바이너리 리소스
스크립트/init.py
바이너리 리소스
스크립트/aggregate_benchmark.py
스크립트 다운로드/aggregate_benchmark.py
바이너리 리소스
스크립트/generate_report.py
바이너리 리소스
스크립트/improve_description.py
스크립트 다운로드/improve_description.py
바이너리 리소스
스크립트/package_skill.py
#!/usr/bin/env python3
"""
Skill Packager - Creates a distributable .skill file of a skill folder
Usage:
python utils/package_skill.py <path/to/skill-folder> [output-directory]
Example:
python utils/package_skill.py skills/public/my-skill
python utils/package_skill.py skills/public/my-skill ./dist
"""
import fnmatch
import sys
import zipfile
from pathlib import Path
from scripts.quick_validate import validate_skill
# Patterns to exclude when packaging skills.
EXCLUDE_DIRS = {"__pycache__", "node_modules"}
EXCLUDE_GLOBS = {"*.pyc"}
EXCLUDE_FILES = {".DS_Store"}
# Directories excluded only at the skill root (not when nested deeper).
ROOT_EXCLUDE_DIRS = {"evals"}
def should_exclude(rel_path: Path) -> bool:
"""Check if a path should be excluded from packaging."""
parts = rel_path.parts
if any(part in EXCLUDE_DIRS for part in parts):
return True
# rel_path is relative to skill_path.parent, so parts[0] is the skill
# folder name and parts[1] (if present) is the first subdir.
if len(parts) > 1 and parts[1] in ROOT_EXCLUDE_DIRS:
return True
name = rel_path.name
if name in EXCLUDE_FILES:
return True
return any(fnmatch.fnmatch(name, pat) for pat in EXCLUDE_GLOBS)
def package_skill(skill_path, output_dir=None):
"""
Package a skill folder into a .skill file.
Args:
skill_path: Path to the skill folder
output_dir: Optional output directory for the .skill file (defaults to current directory)
Returns:
Path to the created .skill file, or None if error
"""
skill_path = Path(skill_path).resolve()
# Validate skill folder exists
if not skill_path.exists():
print(f"❌ Error: Skill folder not found: {skill_path}")
return None
if not skill_path.is_dir():
print(f"❌ Error: Path is not a directory: {skill_path}")
return None
# Validate SKILL.md exists
skill_md = skill_path / "SKILL.md"
if not skill_md.exists():
print(f"❌ Error: SKILL.md not found in {skill_path}")
return None
# Run validation before packaging
print("🔍 Validating skill...")
valid, message = validate_skill(skill_path)
if not valid:
print(f"❌ Validation failed: {message}")
print(" Please fix the validation errors before packaging.")
return None
print(f"✅ {message}\n")
# Determine output location
skill_name = skill_path.name
if output_dir:
output_path = Path(output_dir).resolve()
output_path.mkdir(parents=True, exist_ok=True)
else:
output_path = Path.cwd()
skill_filename = output_path / f"{skill_name}.skill"
# Create the .skill file (zip format)
try:
with zipfile.ZipFile(skill_filename, 'w', zipfile.ZIP_DEFLATED) as zipf:
# Walk through the skill directory, excluding build artifacts
for file_path in skill_path.rglob('*'):
if not file_path.is_file():
continue
arcname = file_path.relative_to(skill_path.parent)
if should_exclude(arcname):
print(f" Skipped: {arcname}")
continue
zipf.write(file_path, arcname)
print(f" Added: {arcname}")
print(f"\n✅ Successfully packaged skill to: {skill_filename}")
return skill_filename
except Exception as e:
print(f"❌ Error creating .skill file: {e}")
return None
def main():
if len(sys.argv) < 2:
print("Usage: python utils/package_skill.py <path/to/skill-folder> [output-directory]")
print("\nExample:")
print(" python utils/package_skill.py skills/public/my-skill")
print(" python utils/package_skill.py skills/public/my-skill ./dist")
sys.exit(1)
skill_path = sys.argv[1]
output_dir = sys.argv[2] if len(sys.argv) > 2 else None
print(f"📦 Packaging skill: {skill_path}")
if output_dir:
print(f" Output directory: {output_dir}")
print()
result = package_skill(skill_path, output_dir)
if result:
sys.exit(0)
else:
sys.exit(1)
if __name__ == "__main__":
main()
스크립트/quick_validate.py
#!/usr/bin/env python3
"""
Quick validation script for skills - minimal version
"""
import sys
import os
import re
import yaml
from pathlib import Path
def validate_skill(skill_path):
"""Basic validation of a skill"""
skill_path = Path(skill_path)
# Check SKILL.md exists
skill_md = skill_path / 'SKILL.md'
if not skill_md.exists():
return False, "SKILL.md not found"
# Read and validate frontmatter
content = skill_md.read_text()
if not content.startswith('---'):
return False, "No YAML frontmatter found"
# Extract frontmatter
match = re.match(r'^---\n(.*?)\n---', content, re.DOTALL)
if not match:
return False, "Invalid frontmatter format"
frontmatter_text = match.group(1)
# Parse YAML frontmatter
try:
frontmatter = yaml.safe_load(frontmatter_text)
if not isinstance(frontmatter, dict):
return False, "Frontmatter must be a YAML dictionary"
except yaml.YAMLError as e:
return False, f"Invalid YAML in frontmatter: {e}"
# Define allowed properties
ALLOWED_PROPERTIES = {'name', 'description', 'license', 'allowed-tools', 'metadata', 'compatibility'}
# Check for unexpected properties (excluding nested keys under metadata)
unexpected_keys = set(frontmatter.keys()) - ALLOWED_PROPERTIES
if unexpected_keys:
return False, (
f"Unexpected key(s) in SKILL.md frontmatter: {', '.join(sorted(unexpected_keys))}. "
f"Allowed properties are: {', '.join(sorted(ALLOWED_PROPERTIES))}"
)
# Check required fields
if 'name' not in frontmatter:
return False, "Missing 'name' in frontmatter"
if 'description' not in frontmatter:
return False, "Missing 'description' in frontmatter"
# Extract name for validation
name = frontmatter.get('name', '')
if not isinstance(name, str):
return False, f"Name must be a string, got {type(name).__name__}"
name = name.strip()
if name:
# Check naming convention (kebab-case: lowercase with hyphens)
if not re.match(r'^[a-z0-9-]+$', name):
return False, f"Name '{name}' should be kebab-case (lowercase letters, digits, and hyphens only)"
if name.startswith('-') or name.endswith('-') or '--' in name:
return False, f"Name '{name}' cannot start/end with hyphen or contain consecutive hyphens"
# Check name length (max 64 characters per spec)
if len(name) > 64:
return False, f"Name is too long ({len(name)} characters). Maximum is 64 characters."
# Extract and validate description
description = frontmatter.get('description', '')
if not isinstance(description, str):
return False, f"Description must be a string, got {type(description).__name__}"
description = description.strip()
if description:
# Check for angle brackets
if '<' in description or '>' in description:
return False, "Description cannot contain angle brackets (< or >)"
# Check description length (max 1024 characters per spec)
if len(description) > 1024:
return False, f"Description is too long ({len(description)} characters). Maximum is 1024 characters."
# Validate compatibility field if present (optional)
compatibility = frontmatter.get('compatibility', '')
if compatibility:
if not isinstance(compatibility, str):
return False, f"Compatibility must be a string, got {type(compatibility).__name__}"
if len(compatibility) > 500:
return False, f"Compatibility is too long ({len(compatibility)} characters). Maximum is 500 characters."
return True, "Skill is valid!"
if __name__ == "__main__":
if len(sys.argv) != 2:
print("Usage: python quick_validate.py <skill_directory>")
sys.exit(1)
valid, message = validate_skill(sys.argv[1])
print(message)
sys.exit(0 if valid else 1)
스크립트/run_eval.py
바이너리 리소스
스크립트/run_loop.py
바이너리 리소스
스크립트/utils.py
"""Shared utilities for skill-creator scripts."""
from pathlib import Path
def parse_skill_md(skill_path: Path) -> tuple[str, str, str]:
"""Parse a SKILL.md file, returning (name, description, full_content)."""
content = (skill_path / "SKILL.md").read_text()
lines = content.split("\n")
if lines[0].strip() != "---":
raise ValueError("SKILL.md missing frontmatter (no opening ---)")
end_idx = None
for i, line in enumerate(lines[1:], start=1):
if line.strip() == "---":
end_idx = i
break
if end_idx is None:
raise ValueError("SKILL.md missing frontmatter (no closing ---)")
name = ""
description = ""
frontmatter_lines = lines[1:end_idx]
i = 0
while i < len(frontmatter_lines):
line = frontmatter_lines[i]
if line.startswith("name:"):
name = line[len("name:"):].strip().strip('"').strip("'")
elif line.startswith("description:"):
value = line[len("description:"):].strip()
# Handle YAML multiline indicators (>, |, >-, |-)
if value in (">", "|", ">-", "|-"):
continuation_lines: list[str] = []
i += 1
while i < len(frontmatter_lines) and (frontmatter_lines[i].startswith(" ") or frontmatter_lines[i].startswith("\t")):
continuation_lines.append(frontmatter_lines[i].strip())
i += 1
description = " ".join(continuation_lines)
continue
else:
description = value.strip('"').strip("'")
i += 1
return name, description, content
GitHub에서 보기
Current official reference · English8a1541c4a3ff
The original English source comes from the pinned version above. It is shown as inert documentation. Related scripts and resources remain in the upstream repository; this text is not a complete installation package.
Skill Creator
A skill for creating new skills and iteratively improving them.
At a high level, the process of creating a skill goes like this:
- Decide what you want the skill to do and roughly how it should do it
- Write a draft of the skill
- Create a few test prompts and run claude-with-access-to-the-skill on them
- Help the user evaluate the results both qualitatively and quantitatively
- While the runs happen in the background, draft some quantitative evals if there aren't any (if there are some, you can either use as is or modify if you feel something needs to change about them). Then explain them to the user (or if they already existed, explain the ones that already exist)
- Use the
eval-viewer/generate_review.pyscript to show the user the results for them to look at, and also let them look at the quantitative metrics
- Rewrite the skill based on feedback from the user's evaluation of the results (and also if there are any glaring flaws that become apparent from the quantitative benchmarks)
- Repeat until you're satisfied
- Expand the test set and try again at larger scale
Your job when using this skill is to figure out where the user is in this process and then jump in and help them progress through these stages. So for instance, maybe they're like "I want to make a skill for X". You can help narrow down what they mean, write a draft, write the test cases, figure out how they want to evaluate, run all the prompts, and repeat.
On the other hand, maybe they already have a draft of the skill. In this case you can go straight to the eval/iterate part of the loop.
Of course, you should always be flexible and if the user is like "I don't need to run a bunch of evaluations, just vibe with me", you can do that instead.
Then after the skill is done (but again, the order is flexible), you can also run the skill description improver, which we have a whole separate script for, to optimize the triggering of the skill.
Cool? Cool.
Communicating with the user
The skill creator is liable to be used by people across a wide range of familiarity with coding jargon. If you haven't heard (and how could you, it's only very recently that it started), there's a trend now where the power of Claude is inspiring plumbers to open up their terminals, parents and grandparents to google "how to install npm". On the other hand, the bulk of users are probably fairly computer-literate.
So please pay attention to context cues to understand how to phrase your communication! In the default case, just to give you some idea:
- "evaluation" and "benchmark" are borderline, but OK
- for "JSON" and "assertion" you want to see serious cues from the user that they know what those things are before using them without explaining them
It's OK to briefly explain terms if you're in doubt, and feel free to clarify terms with a short definition if you're unsure if the user will get it.
Creating a skill
Capture Intent
Start by understanding the user's intent. The current conversation might already contain a workflow the user wants to capture (e.g., they say "turn this into a skill"). If so, extract answers from the conversation history first — the tools used, the sequence of steps, corrections the user made, input/output formats observed. The user may need to fill the gaps, and should confirm before proceeding to the next step.
- What should this skill enable Claude to do?
- When should this skill trigger? (what user phrases/contexts)
- What's the expected output format?
- Should we set up test cases to verify the skill works? Skills with objectively verifiable outputs (file transforms, data extraction, code generation, fixed workflow steps) benefit from test cases. Skills with subjective outputs (writing style, art) often don't need them. Suggest the appropriate default based on the skill type, but let the user decide.
Interview and Research
Proactively ask questions about edge cases, input/output formats, example files, success criteria, and dependencies. Wait to write test prompts until you've got this part ironed out.
Check available MCPs - if useful for research (searching docs, finding similar skills, looking up best practices), research in parallel via subagents if available, otherwise inline. Come prepared with context to reduce burden on the user.
Write the SKILL.md
Based on the user interview, fill in these components:
- name: Skill identifier
- description: When to trigger, what it does. This is the primary triggering mechanism - include both what the skill does AND specific contexts for when to use it. All "when to use" info goes here, not in the body. Note: currently Claude has a tendency to "undertrigger" skills -- to not use them when they'd be useful. To combat this, please make the skill descriptions a little bit "pushy". So for instance, instead of "How to build a simple fast dashboard to display internal Anthropic data.", you might write "How to build a simple fast dashboard to display internal Anthropic data. Make sure to use this skill whenever the user mentions dashboards, data visualization, internal metrics, or wants to display any kind of company data, even if they don't explicitly ask for a 'dashboard.'"
- compatibility: Required tools, dependencies (optional, rarely needed)
- the rest of the skill :)
Skill Writing Guide
Anatomy of a Skill
skill-name/
├── SKILL.md (required)
│ ├── YAML frontmatter (name, description required)
│ └── Markdown instructions
└── Bundled Resources (optional)
├── scripts/ - Executable code for deterministic/repetitive tasks
├── references/ - Docs loaded into context as needed
└── assets/ - Files used in output (templates, icons, fonts)
Progressive Disclosure
Skills use a three-level loading system:
- Metadata (name + description) - Always in context (~100 words)
- SKILL.md body - In context whenever skill triggers (<500 lines ideal)
- Bundled resources - As needed (unlimited, scripts can execute without loading)
These word counts are approximate and you can feel free to go longer if needed.
Key patterns:
- Keep SKILL.md under 500 lines; if you're approaching this limit, add an additional layer of hierarchy along with clear pointers about where the model using the skill should go next to follow up.
- Reference files clearly from SKILL.md with guidance on when to read them
- For large reference files (>300 lines), include a table of contents
Domain organization: When a skill supports multiple domains/frameworks, organize by variant:
cloud-deploy/
├── SKILL.md (workflow + selection)
└── references/
├── aws.md
├── gcp.md
└── azure.md
Claude reads only the relevant reference file.
Principle of Lack of Surprise
This goes without saying, but skills must not contain malware, exploit code, or any content that could compromise system security. A skill's contents should not surprise the user in their intent if described. Don't go along with requests to create misleading skills or skills designed to facilitate unauthorized access, data exfiltration, or other malicious activities. Things like a "roleplay as an XYZ" are OK though.
Writing Patterns
Prefer using the imperative form in instructions.
Defining output formats - You can do it like this:
## Report structure
ALWAYS use this exact template:
# [Title]
## Executive summary
## Key findings
## Recommendations
Examples pattern - It's useful to include examples. You can format them like this (but if "Input" and "Output" are in the examples you might want to deviate a little):
## Commit message format
**Example 1:**
Input: Added user authentication with JWT tokens
Output: feat(auth): implement JWT-based authentication
Writing Style
Try to explain to the model why things are important in lieu of heavy-handed musty MUSTs. Use theory of mind and try to make the skill general and not super-narrow to specific examples. Start by writing a draft and then look at it with fresh eyes and improve it.
Test Cases
After writing the skill draft, come up with 2-3 realistic test prompts — the kind of thing a real user would actually say. Share them with the user: [you don't have to use this exact language] "Here are a few test cases I'd like to try. Do these look right, or do you want to add more?" Then run them.
Save test cases to evals/evals.json. Don't write assertions yet — just the prompts. You'll draft assertions in the next step while the runs are in progress.
{
"skill_name": "example-skill",
"evals": [
{
"id": 1,
"prompt": "User's task prompt",
"expected_output": "Description of expected result",
"files": []
}
]
}
See references/schemas.md for the full schema (including the assertions field, which you'll add later).
Running and evaluating test cases
This section is one continuous sequence — don't stop partway through. Do NOT use /skill-test or any other testing skill.
Put results in <skill-name>-workspace/ as a sibling to the skill directory. Within the workspace, organize results by iteration (iteration-1/, iteration-2/, etc.) and within that, each test case gets a directory (eval-0/, eval-1/, etc.). Don't create all of this upfront — just create directories as you go.
Step 1: Spawn all runs (with-skill AND baseline) in the same turn
For each test case, spawn two subagents in the same turn — one with the skill, one without. This is important: don't spawn the with-skill runs first and then come back for baselines later. Launch everything at once so it all finishes around the same time.
With-skill run:
Execute this task:
- Skill path: <path-to-skill>
- Task: <eval prompt>
- Input files: <eval files if any, or "none">
- Save outputs to: <workspace>/iteration-<N>/eval-<ID>/with_skill/outputs/
- Outputs to save: <what the user cares about — e.g., "the .docx file", "the final CSV">
Baseline run (same prompt, but the baseline depends on context):
- Creating a new skill: no skill at all. Same prompt, no skill path, save to
without_skill/outputs/. - Improving an existing skill: the old version. Before editing, snapshot the skill (
cp -r <skill-path> <workspace>/skill-snapshot/), then point the baseline subagent at the snapshot. Save toold_skill/outputs/.
Write an eval_metadata.json for each test case (assertions can be empty for now). Give each eval a descriptive name based on what it's testing — not just "eval-0". Use this name for the directory too. If this iteration uses new or modified eval prompts, create these files for each new eval directory — don't assume they carry over from previous iterations.
{
"eval_id": 0,
"eval_name": "descriptive-name-here",
"prompt": "The user's task prompt",
"assertions": []
}
Step 2: While runs are in progress, draft assertions
Don't just wait for the runs to finish — you can use this time productively. Draft quantitative assertions for each test case and explain them to the user. If assertions already exist in evals/evals.json, review them and explain what they check.
Good assertions are objectively verifiable and have descriptive names — they should read clearly in the benchmark viewer so someone glancing at the results immediately understands what each one checks. Subjective skills (writing style, design quality) are better evaluated qualitatively — don't force assertions onto things that need human judgment.
Update the eval_metadata.json files and evals/evals.json with the assertions once drafted. Also explain to the user what they'll see in the viewer — both the qualitative outputs and the quantitative benchmark.
Step 3: As runs complete, capture timing data
When each subagent task completes, you receive a notification containing total_tokens and duration_ms. Save this data immediately to timing.json in the run directory:
{
"total_tokens": 84852,
"duration_ms": 23332,
"total_duration_seconds": 23.3
}
This is the only opportunity to capture this data — it comes through the task notification and isn't persisted elsewhere. Process each notification as it arrives rather than trying to batch them.
Step 4: Grade, aggregate, and launch the viewer
Once all runs are done:
-
Grade each run — spawn a grader subagent (or grade inline) that reads
agents/grader.mdand evaluates each assertion against the outputs. Save results tograding.jsonin each run directory. The grading.json expectations array must use the fieldstext,passed, andevidence(notname/met/detailsor other variants) — the viewer depends on these exact field names. For assertions that can be checked programmatically, write and run a script rather than eyeballing it — scripts are faster, more reliable, and can be reused across iterations. -
Aggregate into benchmark — run the aggregation script from the skill-creator directory:
python -m scripts.aggregate_benchmark <workspace>/iteration-N --skill-name <name>This produces
benchmark.jsonandbenchmark.mdwith pass_rate, time, and tokens for each configuration, with mean ± stddev and the delta. If generating benchmark.json manually, seereferences/schemas.mdfor the exact schema the viewer expects. Put each with_skill version before its baseline counterpart. -
Do an analyst pass — read the benchmark data and surface patterns the aggregate stats might hide. See
agents/analyzer.md(the "Analyzing Benchmark Results" section) for what to look for — things like assertions that always pass regardless of skill (non-discriminating), high-variance evals (possibly flaky), and time/token tradeoffs. -
Launch the viewer with both qualitative outputs and quantitative data:
nohup python <skill-creator-path>/eval-viewer/generate_review.py \ <workspace>/iteration-N \ --skill-name "my-skill" \ --benchmark <workspace>/iteration-N/benchmark.json \ > /dev/null 2>&1 & VIEWER_PID=$!For iteration 2+, also pass
--previous-workspace <workspace>/iteration-<N-1>.Cowork / headless environments: If
webbrowser.open()is not available or the environment has no display, use--static <output_path>to write a standalone HTML file instead of starting a server. Feedback will be downloaded as afeedback.jsonfile when the user clicks "Submit All Reviews". After download, copyfeedback.jsoninto the workspace directory for the next iteration to pick up.
Note: please use generate_review.py to create the viewer; there's no need to write custom HTML.
- Tell the user something like: "I've opened the results in your browser. There are two tabs — 'Outputs' lets you click through each test case and leave feedback, 'Benchmark' shows the quantitative comparison. When you're done, come back here and let me know."
What the user sees in the viewer
The "Outputs" tab shows one test case at a time:
- Prompt: the task that was given
- Output: the files the skill produced, rendered inline where possible
- Previous Output (iteration 2+): collapsed section showing last iteration's output
- Formal Grades (if grading was run): collapsed section showing assertion pass/fail
- Feedback: a textbox that auto-saves as they type
- Previous Feedback (iteration 2+): their comments from last time, shown below the textbox
The "Benchmark" tab shows the stats summary: pass rates, timing, and token usage for each configuration, with per-eval breakdowns and analyst observations.
Navigation is via prev/next buttons or arrow keys. When done, they click "Submit All Reviews" which saves all feedback to feedback.json.
Step 5: Read the feedback
When the user tells you they're done, read feedback.json:
{
"reviews": [
{"run_id": "eval-0-with_skill", "feedback": "the chart is missing axis labels", "timestamp": "..."},
{"run_id": "eval-1-with_skill", "feedback": "", "timestamp": "..."},
{"run_id": "eval-2-with_skill", "feedback": "perfect, love this", "timestamp": "..."}
],
"status": "complete"
}
Empty feedback means the user thought it was fine. Focus your improvements on the test cases where the user had specific complaints.
Kill the viewer server when you're done with it:
kill $VIEWER_PID 2>/dev/null
Improving the skill
This is the heart of the loop. You've run the test cases, the user has reviewed the results, and now you need to make the skill better based on their feedback.
How to think about improvements
-
Generalize from the feedback. The big picture thing that's happening here is that we're trying to create skills that can be used a million times (maybe literally, maybe even more who knows) across many different prompts. Here you and the user are iterating on only a few examples over and over again because it helps move faster. The user knows these examples in and out and it's quick for them to assess new outputs. But if the skill you and the user are codeveloping works only for those examples, it's useless. Rather than put in fiddly overfitty changes, or oppressively constrictive MUSTs, if there's some stubborn issue, you might try branching out and using different metaphors, or recommending different patterns of working. It's relatively cheap to try and maybe you'll land on something great.
-
Keep the prompt lean. Remove things that aren't pulling their weight. Make sure to read the transcripts, not just the final outputs — if it looks like the skill is making the model waste a bunch of time doing things that are unproductive, you can try getting rid of the parts of the skill that are making it do that and seeing what happens.
-
Explain the why. Try hard to explain the why behind everything you're asking the model to do. Today's LLMs are smart. They have good theory of mind and when given a good harness can go beyond rote instructions and really make things happen. Even if the feedback from the user is terse or frustrated, try to actually understand the task and why the user is writing what they wrote, and what they actually wrote, and then transmit this understanding into the instructions. If you find yourself writing ALWAYS or NEVER in all caps, or using super rigid structures, that's a yellow flag — if possible, reframe and explain the reasoning so that the model understands why the thing you're asking for is important. That's a more humane, powerful, and effective approach.
-
Look for repeated work across test cases. Read the transcripts from the test runs and notice if the subagents all independently wrote similar helper scripts or took the same multi-step approach to something. If all 3 test cases resulted in the subagent writing a
create_docx.pyor abuild_chart.py, that's a strong signal the skill should bundle that script. Write it once, put it inscripts/, and tell the skill to use it. This saves every future invocation from reinventing the wheel.
This task is pretty important (we are trying to create billions a year in economic value here!) and your thinking time is not the blocker; take your time and really mull things over. I'd suggest writing a draft revision and then looking at it anew and making improvements. Really do your best to get into the head of the user and understand what they want and need.
The iteration loop
After improving the skill:
- Apply your improvements to the skill
- Rerun all test cases into a new
iteration-<N+1>/directory, including baseline runs. If you're creating a new skill, the baseline is alwayswithout_skill(no skill) — that stays the same across iterations. If you're improving an existing skill, use your judgment on what makes sense as the baseline: the original version the user came in with, or the previous iteration. - Launch the reviewer with
--previous-workspacepointing at the previous iteration - Wait for the user to review and tell you they're done
- Read the new feedback, improve again, repeat
Keep going until:
- The user says they're happy
- The feedback is all empty (everything looks good)
- You're not making meaningful progress
Advanced: Blind comparison
For situations where you want a more rigorous comparison between two versions of a skill (e.g., the user asks "is the new version actually better?"), there's a blind comparison system. Read agents/comparator.md and agents/analyzer.md for the details. The basic idea is: give two outputs to an independent agent without telling it which is which, and let it judge quality. Then analyze why the winner won.
This is optional, requires subagents, and most users won't need it. The human review loop is usually sufficient.
Description Optimization
The description field in SKILL.md frontmatter is the primary mechanism that determines whether Claude invokes a skill. After creating or improving a skill, offer to optimize the description for better triggering accuracy.
Step 1: Generate trigger eval queries
Create 20 eval queries — a mix of should-trigger and should-not-trigger. Save as JSON:
[
{"query": "the user prompt", "should_trigger": true},
{"query": "another prompt", "should_trigger": false}
]
The queries must be realistic and something a Claude Code or Claude.ai user would actually type. Not abstract requests, but requests that are concrete and specific and have a good amount of detail. For instance, file paths, personal context about the user's job or situation, column names and values, company names, URLs. A little bit of backstory. Some might be in lowercase or contain abbreviations or typos or casual speech. Use a mix of different lengths, and focus on edge cases rather than making them clear-cut (the user will get a chance to sign off on them).
Bad: "Format this data", "Extract text from PDF", "Create a chart"
Good: "ok so my boss just sent me this xlsx file (its in my downloads, called something like 'Q4 sales final FINAL v2.xlsx') and she wants me to add a column that shows the profit margin as a percentage. The revenue is in column C and costs are in column D i think"
For the should-trigger queries (8-10), think about coverage. You want different phrasings of the same intent — some formal, some casual. Include cases where the user doesn't explicitly name the skill or file type but clearly needs it. Throw in some uncommon use cases and cases where this skill competes with another but should win.
For the should-not-trigger queries (8-10), the most valuable ones are the near-misses — queries that share keywords or concepts with the skill but actually need something different. Think adjacent domains, ambiguous phrasing where a naive keyword match would trigger but shouldn't, and cases where the query touches on something the skill does but in a context where another tool is more appropriate.
The key thing to avoid: don't make should-not-trigger queries obviously irrelevant. "Write a fibonacci function" as a negative test for a PDF skill is too easy — it doesn't test anything. The negative cases should be genuinely tricky.
Step 2: Review with user
Present the eval set to the user for review using the HTML template:
- Read the template from
assets/eval_review.html - Replace the placeholders:
__EVAL_DATA_PLACEHOLDER__→ the JSON array of eval items (no quotes around it — it's a JS variable assignment)__SKILL_NAME_PLACEHOLDER__→ the skill's name__SKILL_DESCRIPTION_PLACEHOLDER__→ the skill's current description
- Write to a temp file (e.g.,
/tmp/eval_review_<skill-name>.html) and open it:open /tmp/eval_review_<skill-name>.html - The user can edit queries, toggle should-trigger, add/remove entries, then click "Export Eval Set"
- The file downloads to
~/Downloads/eval_set.json— check the Downloads folder for the most recent version in case there are multiple (e.g.,eval_set (1).json)
This step matters — bad eval queries lead to bad descriptions.
Step 3: Run the optimization loop
Tell the user: "This will take some time — I'll run the optimization loop in the background and check on it periodically."
Save the eval set to the workspace, then run in the background:
python -m scripts.run_loop \
--eval-set <path-to-trigger-eval.json> \
--skill-path <path-to-skill> \
--model <model-id-powering-this-session> \
--max-iterations 5 \
--verbose
Use the model ID from your system prompt (the one powering the current session) so the triggering test matches what the user actually experiences.
While it runs, periodically tail the output to give the user updates on which iteration it's on and what the scores look like.
This handles the full optimization loop automatically. It splits the eval set into 60% train and 40% held-out test, evaluates the current description (running each query 3 times to get a reliable trigger rate), then calls Claude to propose improvements based on what failed. It re-evaluates each new description on both train and test, iterating up to 5 times. When it's done, it opens an HTML report in the browser showing the results per iteration and returns JSON with best_description — selected by test score rather than train score to avoid overfitting.
How skill triggering works
Understanding the triggering mechanism helps design better eval queries. Skills appear in Claude's available_skills list with their name + description, and Claude decides whether to consult a skill based on that description. The important thing to know is that Claude only consults skills for tasks it can't easily handle on its own — simple, one-step queries like "read this PDF" may not trigger a skill even if the description matches perfectly, because Claude can handle them directly with basic tools. Complex, multi-step, or specialized queries reliably trigger skills when the description matches.
This means your eval queries should be substantive enough that Claude would actually benefit from consulting a skill. Simple queries like "read file X" are poor test cases — they won't trigger skills regardless of description quality.
Step 4: Apply the result
Take best_description from the JSON output and update the skill's SKILL.md frontmatter. Show the user before/after and report the scores.
Package and Present (only if present_files tool is available)
Check whether you have access to the present_files tool. If you don't, skip this step. If you do, package the skill and present the .skill file to the user:
python -m scripts.package_skill <path/to/skill-folder>
After packaging, direct the user to the resulting .skill file path so they can install it.
Claude.ai-specific instructions
In Claude.ai, the core workflow is the same (draft → test → review → improve → repeat), but because Claude.ai doesn't have subagents, some mechanics change. Here's what to adapt:
Running test cases: No subagents means no parallel execution. For each test case, read the skill's SKILL.md, then follow its instructions to accomplish the test prompt yourself. Do them one at a time. This is less rigorous than independent subagents (you wrote the skill and you're also running it, so you have full context), but it's a useful sanity check — and the human review step compensates. Skip the baseline runs — just use the skill to complete the task as requested.
Reviewing results: If you can't open a browser (e.g., Claude.ai's VM has no display, or you're on a remote server), skip the browser reviewer entirely. Instead, present results directly in the conversation. For each test case, show the prompt and the output. If the output is a file the user needs to see (like a .docx or .xlsx), save it to the filesystem and tell them where it is so they can download and inspect it. Ask for feedback inline: "How does this look? Anything you'd change?"
Benchmarking: Skip the quantitative benchmarking — it relies on baseline comparisons which aren't meaningful without subagents. Focus on qualitative feedback from the user.
The iteration loop: Same as before — improve the skill, rerun the test cases, ask for feedback — just without the browser reviewer in the middle. You can still organize results into iteration directories on the filesystem if you have one.
Description optimization: This section requires the claude CLI tool (specifically claude -p) which is only available in Claude Code. Skip it if you're on Claude.ai.
Blind comparison: Requires subagents. Skip it.
Packaging: The package_skill.py script works anywhere with Python and a filesystem. On Claude.ai, you can run it and the user can download the resulting .skill file.
Updating an existing skill: The user might be asking you to update an existing skill, not create a new one. In this case:
- Preserve the original name. Note the skill's directory name and
namefrontmatter field -- use them unchanged. E.g., if the installed skill isresearch-helper, outputresearch-helper.skill(notresearch-helper-v2). - Copy to a writeable location before editing. The installed skill path may be read-only. Copy to
/tmp/skill-name/, edit there, and package from the copy. - If packaging manually, stage in
/tmp/first, then copy to the output directory -- direct writes may fail due to permissions.
Cowork-Specific Instructions
If you're in Cowork, the main things to know are:
- You have subagents, so the main workflow (spawn test cases in parallel, run baselines, grade, etc.) all works. (However, if you run into severe problems with timeouts, it's OK to run the test prompts in series rather than parallel.)
- You don't have a browser or display, so when generating the eval viewer, use
--static <output_path>to write a standalone HTML file instead of starting a server. Then proffer a link that the user can click to open the HTML in their browser. - For whatever reason, the Cowork setup seems to disincline Claude from generating the eval viewer after running the tests, so just to reiterate: whether you're in Cowork or in Claude Code, after running tests, you should always generate the eval viewer for the human to look at examples before revising the skill yourself and trying to make corrections, using
generate_review.py(not writing your own boutique html code). Sorry in advance but I'm gonna go all caps here: GENERATE THE EVAL VIEWER BEFORE evaluating inputs yourself. You want to get them in front of the human ASAP! - Feedback works differently: since there's no running server, the viewer's "Submit All Reviews" button will download
feedback.jsonas a file. You can then read it from there (you may have to request access first). - Packaging works —
package_skill.pyjust needs Python and a filesystem. - Description optimization (
run_loop.py/run_eval.py) should work in Cowork just fine since it usesclaude -pvia subprocess, not a browser, but please save it until you've fully finished making the skill and the user agrees it's in good shape. - Updating an existing skill: The user might be asking you to update an existing skill, not create a new one. Follow the update guidance in the claude.ai section above.
Reference files
The agents/ directory contains instructions for specialized subagents. Read them when you need to spawn the relevant subagent.
agents/grader.md— How to evaluate assertions against outputsagents/comparator.md— How to do blind A/B comparison between two outputsagents/analyzer.md— How to analyze why one version beat another
The references/ directory has additional documentation:
references/schemas.md— JSON structures for evals.json, grading.json, etc.
Repeating one more time the core loop here for emphasis:
- Figure out what the skill is about
- Draft or edit the skill
- Run claude-with-access-to-the-skill on test prompts
- With the user, evaluate the outputs:
- Create benchmark.json and run
eval-viewer/generate_review.pyto help the user review them - Run quantitative evals
- Create benchmark.json and run
- Repeat until you and the user are satisfied
- Package the final skill and return it to the user.
Please add steps to your TodoList, if you have such a thing, to make sure you don't forget. If you're in Cowork, please specifically put "Create evals JSON and run eval-viewer/generate_review.py so human can review test cases" in your TodoList to make sure it happens.
Good luck!