0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

plugin validateを通ったSKILL.md 30個が公式仕様の検証で全滅した

0
Posted at

はじめに

Claude Code v2.1.233 で claude plugin validate が「素の .claude/skills ディレクトリも検査し、frontmatter のパースに失敗する SKILL.md を報告する」よう改善されました(公式 changelog)。手元のスキル資産を CI で守れそうだと思い、v2.1.234 で実際に走らせてみたところ、30 個のスキルが全部パスする一方、Agent Skills 仕様の参照実装 skills-ref では 30 個すべてが失格 という結果になりました。対象読者は、.claude/skills を複数人・複数リポジトリで運用していて、スキル定義の検証を CI に組み込みたい方です。

同じ SKILL.md を 2 つのバリデータに与えると何が起きるのか、11 ケースの実測で切り分けます。

2 つのバリデータの判定(11 ケース実測)

claude plugin validate --strict(Claude Code 2.1.234)と skills-ref validate(0.1.5)に、同一の SKILL.md を与えた結果です。すべて 2026-08-18 に実行しています。

# SKILL.md の状態 claude plugin validate --strict skills-ref validate
1 YAML が壊れている(引用符が閉じていない) ❌ error / exit 1 ❌ error / exit 1
2 frontmatter ブロックがない ⚠️ warning → exit 1 ❌ error / exit 1
3 description がない ⚠️ warning → exit 1 ❌ error / exit 1
4 description: ""(空文字列) ✅ pass / exit 0 ❌ error / exit 1
5 description が 1,300 文字 ✅ pass / exit 0 ❌ error(1024 字上限)
6 name がない ✅ pass / exit 0 ❌ error(必須フィールド)
7 name: Bad_Name Upper(大文字・記号・空白) ✅ pass / exit 0 ❌ error(小文字と数字とハイフンのみ)
8 name が 120 文字 ✅ pass / exit 0 ❌ error(64 字上限)
9 name とディレクトリ名が不一致 ✅ pass / exit 0 ❌ error(一致必須)
10 未知フィールド totally_unknown_field ✅ pass / exit 0 ❌ error(許可 6 フィールド外)
11 allowed-tools: NotARealTool, Bash(存在しないツール名) ✅ pass / exit 0 ✅ pass / exit 0

--strict を前提に数えると、判定が一致したのは 11 件中 4 件(#1・#2・#3・#11)だけでした。claude plugin validate が止めるのは実質「YAML が壊れている」「frontmatter や description が丸ごとない」の 3 パターン で、値の中身(長さ・文字種・ディレクトリ名との一致)は見ていません。

検証環境と再現手順

  • Claude Code 2.1.234(claude --version
  • skills-ref 0.1.5(npm i -g skills-ref@0.1.5
  • Node.js v22.22.2 / Linux x86_64
  • 実行日: 2026-08-18(JST)

ケースごとに独立したディレクトリを作り、片方ずつ壊した SKILL.md を置いて両方のバリデータに通しました。たとえば #7(name の文字種違反)はこれだけのファイルです。

mkdir -p badname/.claude/skills/badname
cat > badname/.claude/skills/badname/SKILL.md <<'EOF'
---
name: Bad_Name Upper
description: Skill with an invalid name format for testing.
---
body
EOF

claude plugin validate --strict badname/.claude/skills   # → √ Validation passed (exit 0)
skills-ref validate badname/.claude/skills/badname       # → Validation failed (exit 1)

skills-ref の出力はこうなります。

Validation failed for .../badname:
  - Skill name 'Bad_Name Upper' must be lowercase

同じファイルに対する claude plugin validate --strict の出力は √ Validation passed の 1 行だけです。--strict はヘルプに「unrecognized fields, missing metadata で落とす」と書かれていますが、スキルの未知フィールド(#10)では発火しませんでした--strict が効いたのは warning が出るケース(#2・#3)を error に格上げする場面だけです。

判定が割れた 7 ケースで何が起きているか

割れた 7 件(#4〜#10)はすべて「Claude Code は素通し、Agent Skills 仕様は失格」の向きでした。逆向き(Claude Code だけが落とす)は 1 件もありません。

理由は、両者が別のドキュメントを実装しているからです。Claude Code の skills ドキュメントは frontmatter について 「All fields are optional. Only description is recommended」 と明記しており、name は省略時にディレクトリ名へフォールバックする設計です(Claude Code の skills ドキュメント)。一方 Agent Skills の仕様namedescriptionrequired とし、name は 1〜64 文字・小文字英数字とハイフンのみ・連続ハイフン禁止・親ディレクトリ名と一致、description は 1〜1024 文字と定めています。

つまり #6〜#9 は「Claude Code のバグ」ではなく 実装している仕様が違う だけです。ただし運用上は、CI に claude plugin validate だけを置くと「仕様違反のスキルが緑で通る」状態になります。

実リポジトリの 30 スキルでは 100% 乖離した

本ブログの自動運用リポジトリには .claude/skills 配下に 30 個のスキルがあります。両方を掛けた結果です。

バリデータ パス 失格
claude plugin validate --strict .claude 30 / 30 0
skills-ref validate(1 スキルずつ) 0 / 30 30

失格理由は 30 件すべてが Unexpected fields in frontmatter でした。仕様が許可するのは name / description / license / compatibility / metadata / allowed-tools の 6 つだけで、Claude Code 固有のフィールドがそこに入っていないためです。30 スキルでの出現数はこうなりました。

フィールド 使用スキル数 Agent Skills 仕様
effort 22 未定義
user-invocable 13 未定義
argument-hint 6 未定義
model 4 未定義
disallowed-tools 3 未定義
when_to_use 1 未定義
compatibility 2 許可
allowed-tools 1 許可

effortuser-invocable は Claude Code のドキュメントに載っている正規のフィールドです。つまり Claude Code のドキュメントどおりに書くほど、Agent Skills 仕様の検証は通らなくなります

2 つの基準の関係

Agent Skills は Claude 以外のエージェントでも読める共通フォーマットとして公開されており、仕様側は「配布可能性」を守るために厳しく、Claude Code 側は「自分が読めれば動く」ため緩い、という住み分けに見えます。

どちらを CI に置くか

実測を踏まえた使い分けです。

  • 自リポジトリ専用のスキル: claude plugin validate --strict で十分です。YAML 破損と description 欠落という、実害が大きく気づきにくい 2 つを止められます。ただし description: ""(#4)はすり抜けるので、空文字列を書かない運用は別途必要です。
  • 配布・共有するスキル: skills-ref validate を追加します。name とディレクトリ名の不一致(#9)は、仕様準拠のローダーではスキルが読み込まれない条件なので、配布前に落としておく価値があります。
  • 両方を通したい場合: Claude Code 固有フィールドが未知フィールド扱いになるため、skills-ref は素通りできません。今回の 30 スキルのように effort / user-invocable を使うなら、skills-ref は「配布用に切り出したスキルだけ」に適用範囲を絞るのが現実的です。

補足として、Claude Code の skills ドキュメントには「Claude Code はすべてのフィールドを受け付けるが、Claude Code の外では Agent Skills 仕様のフィールドしか使えない」旨と、仕様外フィールドを含めるとパッケージングやアップロードがハードエラーで失敗する例(Unexpected key(s) in SKILL.md frontmatter: argument-hint. Allowed properties are: allowed-tools, compatibility, description, license, metadata, name)が記載されています。配布経路に乗せた瞬間に落ちる という点では、skills-ref の判定は「将来の失敗の先取り」でもあります。

なお #11 のとおり、allowed-tools に存在しないツール名を書いても どちらも検出しません。ツール名のタイプミスは実行時まで気づけないため、ここはレビューで見るしかありません。

まとめ

  • claude plugin validate(2.1.234)が落とすのは、YAML パース不能・frontmatter 欠落・description 欠落の 3 パターンでした。--strict は警告を error に格上げするだけで、未知フィールドでは発火しませんでした
  • Agent Skills 仕様の参照実装 skills-ref は、name の必須・64 字上限・小文字英数字とハイフンのみ・ディレクトリ名一致、description の 1024 字上限と空文字列禁止、未知フィールド禁止まで見ます
  • 実リポジトリの 30 スキルは前者を 30/30 でパスし、後者は 0/30 でした。原因はすべて Claude Code 固有フィールド(effort 22 件・user-invocable 13 件ほか)です
  • 「Claude Code で動くこと」と「Agent Skills 仕様に準拠していること」は別物です。CI に置くバリデータは、そのスキルを配布するかどうかで選ぶのが妥当だと感じました

関連記事

参考リンク

0
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?