
그 SKILL.md, 다른 스킬과 발화가 겹치지 않나요? 충돌과 깨진 참조를 CI에서 잡아내는 Linter를 만들었다
요약
Claude Agent Skills(SKILL.md)의 참조 정합성 오류와 스킬 간 발화 중복 충돌을 CI 단계에서 자동으로 검출하는 Linter인 'skills-lint'를 소개합니다. 의존성 없이 가볍게 실행되며, Jaccard 유사도를 활용해 스킬 간 트리거 문구 충돌을 효과적으로 잡아냅니다.
핵심 포인트
- SKILL.md 내 파일 경로 참조 오류 및 깨진 링크 자동 검출
- Jaccard 유사도를 이용한 스킬 간 발화(description) 중복 판정
- 의존성 없는 가벼운 도구로 npx 및 GitHub Action 지원
- PR 시점에 인라인 주석으로 오류를 알려 개발 워크플로우 통합
스킬이 늘어나면, 조용히 사고가 터진다
Claude의 Agent Skills (SKILL.md)를 쓰기 시작했을 때, 나는 쾌적했다. 곤란해진 것은 스킬이 5개, 10개로 늘어난 뒤부터다. 두 가지 불안이 생겨났다.
하나는 참조의 부패다. SKILL.md에 "전처리는 scripts/extract.py를 사용한다"라고 적었는데, 나중에 그 스크립트의 이름을 변경했다. SKILL.md는 여전히 옛날 경로를 가리키고 있다. 아무도 눈치채지 못한다. 에이전트(Agent)는 그것을 믿고 움직인다.
또 하나는 더 까다로운 문제인데, 스킬끼리의 "발화 중복"이다. 스킬은 description의 트리거(Trigger) 문구로 호출된다. 비슷한 설명의 스킬을 두 개 두면, 동일한 입력에서 어느 쪽이 기동할지 알 수 없게 된다. 게다가 조용히, 잘못된 쪽이 작동한다.
이 두 가지를 PR(Pull Request) 시점에 기계적으로 잡아내는 도구, skills-lint를 만들었다.
먼저 기존 도구를 찾아보았다. 그리고, 겹치는 부분이 있었다
솔직히 말하겠다. 만들기 전에 "어차피 누군가 만들었겠지"라고 생각하며 찾아보았다. 예상대로 트리거 충돌 검출은 pulser와 같은 선행 도구가 이미 하고 있었다. 유료인 SkillCheck에도 유사한 기능이 있다. 여기서 나는 한 번 실망했다.
하지만 자세히 보니 빈틈이 있었다. 충돌을 보는 도구는 참조 정합성(Reference Integrity)을 보지 않는다. 참조 정합성을 보는 도구는 npm 의존성이 있거나 유료다. "참조 정합성 + 충돌 검출 + 의존성 제로 + 무료로 매 PR 실행"을 하나로 묶은 것은 없었다.
그래서 묶었다. 그것이 skills-lint다.
무엇을 잡아내는가
검출하는 것은 세 가지다.
- 참조 정합성:
SKILL.md본문의scripts/run.py나[doc](references/guide.md)가 실제로 존재하는가. 언어는 묻지 않는다. - frontmatter:
name이 소문자 하이픈 형식인가,description(발화 트리거)이 있는가. - 충돌: 두 스킬의
name이 중복되지 않는가(설치 충돌),description이 너무 가깝지 않은가.
세 번째인 "너무 가까움"의 판정에는 문자 바이그램(Bigram) 유사도(Jaccard)를 사용했다. 형태소 분석(Morphological Analysis)과 같은 무거운 의존성을 가져오지 않아도 되고, 일본어 트리거 문구에서도 효과적이다. 임계값(Threshold)은 0.7로 높게 설정하여 오검출을 방지했다.
일부러 비슷하게 만든 두 스킬을 넣으면 다음과 같이 나온다.
✗ examples/bad/summarizer-a/SKILL.md — 1건
:4 참조 `scripts/missing.py`가 존재하지 않습니다
examples/bad/summarizer-b/SKILL.md:1 description이 summarizer-a와 고유사 (0.94) — 동일한 입력에서 혼동될 위험이 있음
...
부패한 참조와 유사도 0.94의 충돌을 동시에 잡아내어 CI를 떨어뜨린다. 이것뿐이다.
사용법
로컬이라면 한 줄.
npx @hyuga/skills-lint # .claude/skills / skills를 자동 탐색
CI에 배치한다면 GitHub Action으로.
- uses: hyuga611/skills-lint@v1
with:
paths: .claude/skills
지적 사항은 PR에 인라인 주석(Inline Annotation)으로 나타나며, 작업(Job)이 실패한다. 사람이 의식하지 않아도 매 PR마다 실행된다. 이것이 정착의 핵심이라고 나는 생각한다.
자매 도구 reflint도 같은 날 업데이트했다
skills-lint는 이전에 만든 reflint (AGENTS.md / llms.txt의 참조 정합성 Linter)와 같은 방식으로 만들었다. 의존성 제로, 순수 함수인 scan과 CLI 분리, GitHub Action, PR 주석.
그 reflint도 같은 날 v0.2.0을 출시했다. llms.txt 안의 마크다운(Markdown) 링크 대상이 리포지토리 내에 실제로 존재하는지 검증하는 기능이다. 기존의 llms.txt 도구들은 포맷 검사나 외부 링크의 생존 여부(Liveness) 정도까지만 다룬다. 리포지토리 내의 참조 정합성을 CI에서 확인하는 것은 찾아볼 수 없었다. 이 부분은 경쟁자가 없다.
- reflint: https://github.com/hyuga611/reflint
요약
스킬이 늘어나는 시대, 가장 조용한 사고는 "발화의 중복"과 "부패한 참조"다. 육안으로는 알아챌 수 없다. 그래서 CI로 잡아낸다.
- 리포지토리 (Repository): https://github.com/hyuga611/skills-lint
npx @hyuga/skills-lint
로 지금 바로 테스트해 볼 수 있습니다.
같은 고통을 겪고 있는 분이 있다면, 꼭 사용해 보세요.
Discussion

AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기