1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

claude-skillsの2割、仕様違反だった

1
Last updated at Posted at 2026-10-13

はじめに

Claude Codeの「Skills」機能が広まるにつれ、GitHub上にはスキルを大量に集めたOSSライブラリが増えてきました。中でも alirezarezvani/claude-skills は22.6k star(本記事執筆時点でWebFetch実測)を集める、この分野で最大級のコレクションの1つです。

ただ、こうした「大量のSKILL.mdを集めたリポジトリ」は誰かが仕様チェックをしているとは限りません。実際にcloneして、Agent Skills仕様(agentskills.io/specification)に自作のvalidatorスクリプトを当ててみたところ、356個中72個(約20%)のSKILL.mdがfrontmatterで許可されていないキーを使っていることが分かりました。ただし、この「許可されていない」は配布先によって意味が変わります。詳しくは後半の②で整理します。

本記事は、OSSのスキルライブラリを導入・公開しようとしているClaude Codeユーザー向けです。

この記事で学べること

  • Agent Skills仕様(frontmatterの許可キー・name/description制約)の具体的な中身と、Claude Code側の扱いの違い
  • 355個規模のOSSスキルライブラリを実際にcloneしてPythonで機械チェックする手順
  • 壊れたシンボリックリンク・YAML構文エラー・description文字数超過など、実際に見つかった不備の実物

対象読者

  • Claude Code / OpenAI Codex / Gemini CLIなどでAgent Skillsを使っている方
  • OSSのスキルライブラリを導入する前に品質を確認したい方
  • 自分のスキルをOSSとして公開しようとしている方

前提環境

  • Node.js: v22.22.2
  • Python: 3.11.15
  • git: 2.43.0
  • PyYAML: 6.0.1

TL;DR

  1. alirezarezvani/claude-skills(22.6k star)を実際にcloneし、SKILL.mdファイルを機械的に全数チェックしました
  2. Agent Skills仕様の許可キー(name/description/license/allowed-tools/metadata/compatibility)以外を使っているSKILL.mdが356個中 72個(約20%) ありました。Claude Codeで使う限りは無視されますが、claude.aiへのアップロードやSkills APIではエラーになります
  3. YAML構文エラーで frontmatterがパースできないファイルが2個 ありました(コロンのエスケープ漏れ)
  4. description が仕様上限の1024文字を超えているファイルが1個(1161文字)ありました
  5. リポジトリ内に 壊れたシンボリックリンクが3件 ありました。READMEの「602個のPythonスクリプトは全てstdlibのみでzero pip installs」という表記は、実際には 9ファイルが非stdlibパッケージ(PyYAML/requests/pandas/firecrawl)をimportしていた ため厳密には不正確でした

実際にcloneしてみる

まずリポジトリを浅くcloneして、規模を確認します。

git clone --depth 1 https://github.com/alirezarezvani/claude-skills.git claude-skills-test
cd claude-skills-test
find . -name "SKILL.md" | wc -l

実行結果:

777

777件と出ますが、これには罠があります。中身を見るとサブディレクトリ別の内訳は次のとおりです。

find . -name "SKILL.md" | sed 's|^\./||;s|/[^/]*$||' | awk -F/ '{print $1}' | sort | uniq -c | sort -rn | head -15
    420 .gemini
     83 engineering
     68 c-level-advisor
     52 engineering-team
     48 marketing-skill
     19 ra-qm-team
     17 product-team
      9 research
      9 project-management
      9 compliance-os
      8 commercial
      7 productivity
      7 business-operations
      5 research-ops
      5 markdown-html

.gemini/ 配下だけで420件あります。これはGemini CLI向けに 同じスキルをミラーした複製(.hermes/・.vibe/ にも同様の他ツール向けミラーが存在します)で、READMEにも「Hermes AgentとMistral VibeはBYO-syncで .hermes/skills/claude-skills/ .vibe/skills/claude-skills/ に事前生成済みツリーを同梱している」と明記されています。つまり .gemini 配下は独立したスキルではなく、正本(canonical)のコピーです。

777から .gemini の420件を引くと357件になります。これが正本のSKILL.md数で、READMEの「355 production-ready skills」という表記とほぼ一致します(差の2件はテスト用フィクスチャなどが混ざっているためと見られます)。

シンボリックリンクの状態も確認しておきます。

find . -xtype l
./.vibe/skills/claude-skills/engineering-team/status
./.gemini/skills/skills-status-2/SKILL.md
./.hermes/skills/claude-skills/engineering-team/status

-xtype l はリンク先をたどった上で「壊れているシンボリックリンク」だけを抽出するオプションです。リンク先が存在しないパスが3件見つかりました。他ツール向けミラー生成時の同期漏れと見られます。

Pythonツールは本当に「stdlibのみ」か検証する

READMEには「602 CLI scripts (all stdlib-only, zero pip installs)」という具体的な数値付きの主張があります。検証しやすい主張なので、実際にASTで全 .py ファイルのimportを解析しました。

import ast
import sys
from pathlib import Path

STDLIB = sys.stdlib_module_names
root = Path(".")
py_files = list(root.rglob("*.py"))

external = {}
total = 0
for f in py_files:
    total += 1
    try:
        tree = ast.parse(f.read_text(encoding="utf-8", errors="ignore"), filename=str(f))
    except SyntaxError:
        continue
    for node in ast.walk(tree):
        if isinstance(node, ast.Import):
            for alias in node.names:
                mod = alias.name.split(".")[0]
                if mod not in STDLIB:
                    external.setdefault(mod, set()).add(str(f))
        elif isinstance(node, ast.ImportFrom):
            if node.module:
                mod = node.module.split(".")[0]
                if mod not in STDLIB:
                    external.setdefault(mod, set()).add(str(f))

print(f"total py files scanned: {total}")
print(f"distinct external (non-stdlib) top-level modules: {len(external)}")

実行結果:

total py files scanned: 617
distinct external (non-stdlib) top-level modules: 26

617ファイル中「stdlibではないモジュール」は26種類ヒットしました。ただし内訳を見ると config_loader(32ファイルで使用)や security_scorer のような名前も混ざっています。これはpipパッケージではなく、同じスキルディレクトリ内の兄弟スクリプトを相対的にimportしているケース です(AST単体では「外部importかローカル自作モジュールか」を区別できないため、同じ扱いで検出されます)。

そこで、実際にpipでインストールする必要がある実在パッケージ(yaml=PyYAML, requests, pandas, firecrawl)だけに絞り込みました。

REAL_PKGS = {"yaml", "requests", "pandas", "firecrawl"}
# (上のASTループで mods & REAL_PKGS が非空のファイルだけ抽出)

実行結果:

files with real pip-installable external deps: 9
  engineering-team/skills/senior-backend/scripts/api_scaffolder.py: ['yaml']
  engineering-team/skills/senior-computer-vision/scripts/vision_model_trainer.py: ['yaml']
  engineering-team/skills/senior-data-engineer/scripts/pipeline_orchestrator.py: ['yaml']
  engineering/skills/mcp-server-builder/scripts/openapi_to_mcp.py: ['yaml']
  engineering/skills/skill-tester/scripts/quality_scorer.py: ['yaml']
  engineering/skills/skill-tester/scripts/skill_validator.py: ['yaml']
  engineering/skills/tech-debt-tracker/assets/sample_codebase/src/payment_processor.py: ['requests']
  engineering/universal-scraping-architect/skills/universal-scraping-architect/scripts/firecrawl_example.py: ['firecrawl']
  engineering/universal-scraping-architect/skills/universal-scraping-architect/scripts/local_bs4_example.py: ['pandas', 'requests']

617ファイル中9ファイル(約1.5%)が、READMEの「zero pip installs」という表記に反して非stdlibパッケージをimportしています。件数としては小さいものの、「全てstdlibのみ」という 断定的な表記としては不正確 という結果になりました。PyYAML(6ファイル)が最多で、設定ファイルの読み込みに使われているケースが多く見られました。

ツールを1本実際に動かしてみる

せっかくなので中身も1本動かしてみました。engineering/terraform-patterns/skills/terraform-patterns/scripts/tf_module_analyzer.py はTerraformディレクトリの構成品質を採点するツールで、引数なしで実行すると内蔵デモファイルに対して解析が走ります。

cd engineering/terraform-patterns/skills/terraform-patterns/scripts
python3 tf_module_analyzer.py --output json

実行結果(一部省略):

No directory provided. Running demo analysis...

{
  "score": 38,
  "files": ["main.tf", "outputs.tf", "variables.tf"],
  "resource_count": 3,
  "data_source_count": 1,
  "variable_count": 4,
  "output_count": 2,
  "module_count": 1,
  "providers": ["aws"],
  "findings": [
    {"severity": "high", "message": "Missing 'versions.tf' — Provider and Terraform version requirements"},
    {"severity": "high", "message": "Variable 'instance_type' missing type constraint — accepts any value"},
    {"severity": "high", "message": "No remote backend configured — state is stored locally"}
  ],
  "finding_counts": {"critical": 0, "high": 3, "medium": 3, "low": 1}
}

内蔵のデモTerraformコード(EC2インスタンス・S3バケット・セキュリティグループを含む3リソース構成)に対して、バージョン制約なし・リモートバックエンド未設定などを検出し、100点満点中38点というスコアを返しました。標準ライブラリの argparse/json/re だけで書かれており、外部依存ゼロで動きます。

Agent Skills仕様との適合率を検証する

ここからが本題です。Agent Skillsの仕様(agentskills.io/specification)では、SKILL.mdのfrontmatterで使えるキーは以下の6つに限定されています。

キー 必須/任意 制約
name 必須 64文字以内・kebab-case(小文字英数字とハイフン)・親ディレクトリ名と一致
description 必須 1024文字以内
license 任意 -
allowed-tools 任意 -
metadata 任意 -
compatibility 任意 500文字以内

この6キー以外(author・version・tags・context・compatible_tools 等)は、この仕様の上では許可外です。なお context はClaude Codeが独自に定義しているキーで、context: fork と書くとスキルをサブエージェントのコンテキストで実行できます(Claude Code公式ドキュメントで確認)。つまり「agentskills.ioの仕様外」と「Claude Codeで無効」は別の話です。この違いは②で扱います。

検証の流れは次のとおりです。

この流れを実装したvalidatorがこちらです。

import re
import yaml
from pathlib import Path

ALLOWED = {"name", "description", "license", "allowed-tools", "metadata", "compatibility"}
NAME_RE = re.compile(r"^[a-z0-9]+(-[a-z0-9]+)*$")

root = Path(".")
skill_files = [p for p in root.rglob("SKILL.md")
               if ".gemini" not in p.parts and "assets/sample-skill" not in str(p)]

disallowed_key_files = []
long_desc = []
no_frontmatter = []

for f in skill_files:
    text = f.read_text(encoding="utf-8", errors="ignore")
    if not text.startswith("---"):
        no_frontmatter.append(str(f))
        continue
    end = text.find("\n---", 3)
    if end == -1:
        no_frontmatter.append(str(f))
        continue
    try:
        fm = yaml.safe_load(text[3:end])
    except Exception as e:
        no_frontmatter.append(f"{f} (yaml error: {e})")
        continue
    if not isinstance(fm, dict):
        no_frontmatter.append(str(f))
        continue
    extra = set(fm.keys()) - ALLOWED
    if extra:
        disallowed_key_files.append((str(f), sorted(extra)))
    desc = str(fm.get("description", ""))
    if len(desc) > 1024:
        long_desc.append((str(f), len(desc)))

print(f"total canonical SKILL.md scanned: {len(skill_files)}")
print(f"no/broken frontmatter: {len(no_frontmatter)}")
print(f"disallowed extra keys: {len(disallowed_key_files)}")
print(f"description exceeds 1024 chars: {len(long_desc)}")

.gemini 配下(他ツール向けミラー)と、テスト用フィクスチャ1件(assets/sample-skill)を除外し、正本356件を対象にしました。

実行結果:

total canonical SKILL.md scanned: 356
no/broken frontmatter: 2
  markdown-html/skills/design-system/SKILL.md (yaml error: mapping values are not allowed here ...)
  markdown-html/skills/md-slides/SKILL.md (yaml error: mapping values are not allowed here ...)
disallowed extra keys: 72
  markdown-html/skills/md-review/SKILL.md: ['author', 'compatible_tools', 'tags', 'version']
  markdown-html/skills/markdown-html-orchestrator/SKILL.md: ['author', 'compatible_tools', 'context', 'tags', 'version']
  business-operations/skills/knowledge-ops/SKILL.md: ['author', 'compatible_tools', 'context', 'tags', 'version']
  ...(69件省略)
missing name/description: 0
name violates 64char/kebab-case: 0
description exceeds 1024 chars: 1
  research/litreview/skills/litreview/SKILL.md: 1161 chars

3種類の不備が見つかりました。

① YAML構文エラーで2件がfrontmatterとしてパースできない

design-system/SKILL.md と md-slides/SKILL.md はいずれも description フィールドの本文中に、エスケープされていない : (コロン)が含まれており、YAMLパーサが「マッピングの区切り文字」と誤認してパースに失敗します。バッククォート内のコード片や設定パスの説明にコロンを使う際、frontmatterの1行に収めようとすると起きやすい典型的な事故です。なお公式ドキュメントによると、Claude CodeはYAMLが不正でもスキル自体は読み込みますが、フィールドは何も設定されない状態になります。

② 72件(20.2%)が仕様外キーを使っている

最多パターンは author・version・tags・compatible_tools の組み合わせで、context が加わるケースも多く見られました。おそらく別の(もしくは独自の)フォーマット規約を元に付けたメタデータで、仕様の策定前から存在していたテンプレートを流用し続けている可能性があります。

この72件の扱いは、スキルをどこで使うかで変わります。読者の指摘を受けて、公式ドキュメント(Claude Code Skills)で確認し直しました。

  • Claude Code内で使う場合:公式ドキュメントに「Claude Code ignores a field it doesn't recognize without reporting an error」とあり、未知のキーは無視されます。エラーにはなりません
  • claude.aiへのアップロード、Skills API、package_skill.py の場合:許可キー(name/description/license/compatibility/metadata/allowed-tools)以外があるとハードエラーになると記載されています。したがって、これらの配布先を想定するなら「実害は小さい」とは言えません
  • context は、Claude Codeが定義済みのフロントマターです。72件に含まれる context をまとめて「仕様外」とするのは不正確で、少なくともClaude Code内では意味を持つキーです。ただし、ここで見つかった context の値が fork かどうかまでは検証していません
  • author と version は、metadata(自由形式のYAMLマップ)の下に移せば許可キーの範囲に収まります。tags や compatible_tools も同様に移せるはずですが、移した場合の挙動までは確認していません

つまり、72件は「Claude Codeでは動くが、配布先によってはエラーになる」状態です。Claude Code専用の個人利用であれば問題になりませんが、複数の環境へ配るライブラリとしては、許可キーに寄せる価値があります。

③ description上限超過が1件

research/litreview/skills/litreview/SKILL.md の description は1161文字あり、Agent Skills仕様の上限である1024文字を137文字超過しています。

descriptionの長さに関する上限は、確認できた範囲で2種類あります。

  • 仕様(agentskills.io)の description 上限:1024文字。本記事のvalidatorが見ているのはこちらです
  • Claude Codeのスキル一覧での上限:description と when_to_use を合わせて1,536文字で切り詰められます(公式ドキュメントの記載)

1161文字はClaude Code側の1,536文字には収まっていますが、when_to_use の有無は確認していません。仕様の1024文字は超えているため、仕様準拠という観点では違反です。超過した場合に各配布先がエラーにするかどうかは、公式ドキュメントでは確認できていません。

ハマりポイント

検証スクリプトを書く過程で2つハマりました。

1つ目は前述の壊れたシンボリックリンク(find . -xtype l で3件検出)です。素朴に Path.read_text() をすると FileNotFoundError になります。rglob("SKILL.md") はリンクもファイルとして列挙するため、事前に is_file() でのフィルタか、例外処理が必要です。

2つ目はASTベースのimport検出です。自分自身の検証スクリプトを解析対象ディレクトリに置いたまま実行すると、スクリプト自身が使っている yaml importまでカウントに混入してしまいます。検証用スクリプトはリポジトリの外に置く(あるいは明示的にパスを除外する)べきでした。

著者視点の発見ポイント

  • READMEの「zero pip installs」という表記は、602という具体的な数字とセットで書かれているだけに信頼したくなりますが、実際にASTで数えると9ファイルが非stdlibパッケージをimportしていました。具体的な数字が書いてあるclaimほど、検証コストが低いので実際に検証する価値があります
  • frontmatterの仕様違反は、Claude Code内では「動かない」わけではありません(YAMLパースエラーの2件を除く)。だからこそ誰もチェックせず放置されやすいと考えられます。一方で、claude.aiへのアップロードやSkills APIではエラーになるため、配布先を広げた時点で表面化します。動作に影響しないルール違反は、機械チェックを組み込まない限り蓄積します
  • 当初は「仕様外キー=実害は小さい」とまとめていましたが、読者の指摘で公式ドキュメントを読み直し、context がClaude Code定義済みのキーであること、配布先によってはエラーになることを確認して改めました。仕様は「どの環境の仕様か」を切り分けて読む必要があります
  • 355個規模のスキルライブラリは便利ですが、「大きい・starが多い=品質が担保されている」わけではないことが定量的に確認できました。導入前に自分でlintを書いて通す、というひと手間の価値は十分にあります

まとめ

  • alirezarezvani/claude-skills(22.6k star)をcloneし、Agent Skills仕様に対する適合率を機械的に検証しました
  • 正本356件のSKILL.mdのうち、72件(20.2%)がAgent Skills仕様の許可キー以外を使用し、2件がYAML構文エラーでパース不能、1件が description の仕様上限1024文字を超過していました
  • 許可キー外の72件は、Claude Code内では無視されて動きますが、claude.aiへのアップロードやSkills APIではエラーになります。context はClaude Codeの定義済みキーです
  • リポジトリ内に壊れたシンボリックリンクが3件ありました
  • READMEの「602 CLIスクリプトは全てstdlibのみ」という表記は、実際には9ファイルが非stdlibパッケージ(PyYAML/requests/pandas/firecrawl)に依存しており、厳密には不正確でした
  • OSSのスキルライブラリを使う前に、仕様ベースの機械チェックを自分で1本書いて通しておくと、こうした潜在的な不備を導入前に把握できます

参考リンク

1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?