はじめに
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 の仕様は name と description を required とし、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 | 許可 |
effort や user-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 固有フィールド(
effort22 件・user-invocable13 件ほか)です - 「Claude Code で動くこと」と「Agent Skills 仕様に準拠していること」は別物です。CI に置くバリデータは、そのスキルを配布するかどうかで選ぶのが妥当だと感じました
関連記事
- OpenCodeのplanモード、read-onlyは権限ルールだけで作られていた
- Claude Codeのauto mode既定化、denyとhookは4モードとも効いた
- last30daysスキルを実測、起動経路の違いで取得件数が3.3倍差
参考リンク
-
Claude Code changelog — v2.1.233 の
claude plugin validate改善、v2.1.234 の変更点 - Claude Code: Extend Claude with skills — frontmatter フィールド一覧(All fields are optional の記述)
-
Agent Skills Specification —
name/descriptionの必須と制約、許可フィールド一覧 - skills-ref (npm) — 仕様の参照実装バリデータ