스킬의 프론트매터에 오타가 있습니다. 아무도 알려주지 않을 것입니다.
요약
Claude Code 명령어의 프론트매터(frontmatter)에 대한 의미론적 린터인 `frontmatter-guard`가 소개되었습니다. 이 도구는 알려지지 않은 키나 잘못된 훅 이벤트 이름을 감지하여, 개발자가 놓치기 쉬운 '조용한 무효화(no-op)' 오류를 방지합니다. 이를 통해 스킬/플러그인의 안정적인 배포와 정확한 작동을 보장할 수 있습니다.
핵심 포인트
- `frontmatter-guard`는 Claude Code 프론트매터의 의미적 린터입니다.
- 알려지지 않은 키(`unknown-key`)나 잘못된 훅 이벤트 이름(`unknown-hook-event`)을 감지합니다.
- 이 도구는 개발자가 놓치기 쉬운 '조용한 무효화' 오류를 방지하는 데 중점을 둡니다.
- CI 환경에 대비하여 명확한 종료 코드(0, 1, 2)를 반환하도록 설계되었습니다.
스킬의 프론트매터에 오타가 있습니다. 아무도 알려주지 않을 것입니다.
며칠 전 저는 다음과 같은 프론트매터를 가진 Claude Code 명령어를 출시했습니다:
---
name: deploy-helper
description: "배포를 돕습니다"
...
effort: high는 모델이 과도하게 작동하는 것을 막기 위한 것이었습니다. 저는 배포하기 전에 claude plugin validate를 실행했습니다. 통과했습니다. 초록색입니다. 출시하세요.
하지만 effort는 Claude Code 프론트매터 키가 아니었습니다. 그것은 Codex의 개념이었습니다. 제 설정은 조용히 세션 기본값으로 폴백(fallback)했고, 공식 검증기—검증하는 것이 전적인 임무인 그 도구—는 이에 대해 아무 말도 할 수 없었습니다.
저를 가장 괴롭히는 실패 모드는 다음과 같습니다: 큰 충돌이 아니라 조용한 무효화(no-op)입니다. 오타가 난 PreToolUs 훅은 절대 발동되지 않습니다. licence 키는 아무것도 라이선싱하지 않습니다. 자신의 설정을 읽어보면 괜찮아 보이고, 하지만 아무 일도 일어나지 않습니다. 영원히.
그래서 저는 frontmatter-guard를 만들었습니다: 스킬/플러그인 프론트매터에 대한 의미론적 린터(semantic linter)로, 실제 키 어휘와 실제 훅 이벤트 목록을 알고 있으며, 이탈할 경우 크게 실패합니다.
pip install frontmatter-guard
frontmatter-guard check .claude/ --strict
commands/deploy.md:4: error [unknown-key] 알 수 없는 키 'effort'.
수정: 이 키를 제거하세요 -- 알려지지 않은 키는 조용히 무시되므로, 현재 아무것도 하지 않습니다.
commands/deploy.md:7: error [unknown-hook-event] 알려지지 않은 훅 이벤트 'PreToolUs'. 'PreToolUse'를 의도하셨습니까?
...
무엇을 검사하는지
- unknown-key (error) — 알려진 스킬/플러그인 어휘에 포함되지 않은 최상위 키입니다. difflib의 "혹시 이것을 의미하셨나요" 제안이 함께 제공됩니다. 이는
effort/licence/descripton을 포착하는 역할을 합니다. - unknown-hook-event (error) — 이벤트 이름은 Claude Code의 실제 이벤트 목록(
PreToolUse,PostToolUse,SessionStart,SessionEnd,UserPromptSubmit,Stop,SubagentStop,Notification,PreCompact)과 비교하여 검증됩니다. 잘못된 이벤트 이름은 훅이 절대 실행되지 않음을 의미하며, 이는 CI(지속적 통합)가 경고를 발생시키기를 바라는 정확한 경우입니다. - missing-required (error) —
name또는description이 누락되었거나 비어 있습니다. - bad-version (warning) — semver와 유사하지 않은(
semver-ish)version값입니다. - bad-type (warning) — 예를 들어,
hooks:가 문자열로 지정되거나,name:이 숫자로 지정되는 등 잘못된 타입의 경우입니다. - parse-warning (warning) — 지원되는 하위 집합을 벗어난 frontmatter YAML입니다. 경고만 발생하고 충돌하지는 않습니다.
모든 발견 사항은 file:line, 규칙 이름, 그리고 구체적인 수정 제안을 포함합니다. 종료 코드는 CI에 대비되어 있습니다: 모든 오류(또는 --strict 플래그 사용 시의 모든 경고)에는 1, 깨끗할 때는 0, 사용 오류에는 2가 반환됩니다. 기계 처리를 위해서는 --format json을 사용하십시오.
공식 검증기만 사용하지 않는 이유?
왜냐하면 그것들은 서로 다른 질문에 답하기 때문입니다. claude plugin validate는 "이 플러그인이 로드될 수 있는가?"—즉, 호환성과 구조를 묻습니다. 반면, frontmatter-guard는 "당신이 작성한 모든 것이 실제로 작동하는가?"—즉, 의미론적 엄격함을 묻습니다. 알 수 없는 키들은 공식 검사에서는 아무도 모르게 통과하지만, 여기서는 실패합니다. 그것들은 경쟁하는 것이 아니라 상호 보완적입니다.
또한 damson/skill-lint라는 CI 액션이 스킬에 대한 구조적 검사를 수행합니다. frontmatter-guard는 로컬 표준 라이브러리 전용으로 의미론적 검사를 수행하는 CLI이며, 동일한 명령어를 즉각적인 피드백을 위한 pre-commit과 강제 적용을 위한 CI 모두에서 사용할 수 있습니다.
엔지니어링 관점의 이야기
의존성(dependencies)이 없고 Python 3.9 이상에서 작동합니다. YAML 파싱은 표준 라이브러리에 포함된 수동으로 제작한 서브셋 파서입니다—블록 맵과 시퀀스, 인라인 플로우 컬렉션, 리터럴 블록, 따옴표가 있는 스칼라를 처리합니다. 듣기에는 위험해 보일 수 있지만, 이는 의도적인 설계 결정입니다: 프론트매터(frontmatter)는 YAML의 작고 지루한 영역이며, 의존성 없는 파서는 도구가 1초 만에 설치되고 잠긴 CI 러너(CI runners)를 포함하여 어디든 실행될 수 있게 합니다. 서브셋을 벗어나는 모든 내용은 parse-warning을 생성하고 린트(lint)는 계속 진행됩니다—이상한 입력에서 충돌하는 린터보다 쓸모없는 것이 더 나쁩니다.
이 도구는 두 가지 형태를 모두 검사합니다: --- 울타리 뒤에 있는 *.md 프론트매터(skills, commands)와 plugin.json 파일입니다. 이 둘 모두에 동일한 규칙 세트가 적용됩니다.
사용해 보기
pip install frontmatter-guard
frontmatter-guard check . --strict
GitHub: https://github.com/hahahahahahahahah6/frontmatter-guard
PyPI: https://pypi.org/project/frontmatter-guard/
만약 이 도구가 조용히 배포되었을 오타를 잡아낸다면, 그것이 바로 이 도구의 목적입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기