AIに書かせた壮大なSKILL.mdを実装したら、ただのテンプレ生成器だった話
はじめに
Claude Code のスキル機能を使って、あるエンジニアの過去の PR を解析して「コーディングスタイル」「パターン」「ベストプラクティス」を自動抽出するスキルを見つけました。
レビュー対象は、自分のローカル .claude/skills/ にあった個人作のスキルです(作成時に AI にドラフトを書かせた履歴が残っていました)。
SKILL.md を読んだ時は胸が熱くなりました。
GitHub 貢献を分析して、コーディングスタイル・パターン・ベストプラクティスを構造化プロファイルに落とす。新人オンボーディング / コードレビュー訓練 / 知識継承 / AI エージェントへの作風移植に使える。
ところが、付属のシェルスクリプトを実際に走らせて、動作を追ったら 「実装は静的テンプレ生成器」 だったことが判明しました。
この記事は、AI に書かせたスキル定義を運用する際の 現実チェック と、ズレが見つかったときの対応を共有するものです。
発見: SKILL.md と実装のギャップ
スキルのファイル構成:
.claude/skills/engineer-expertise-extractor/
├── SKILL.md (15.5 KB, 638 行)
└── scripts/
└── extract_engineer.sh (613 行)
SKILL.md は壮大でした。命名規則の抽出、パターン認識、アーキテクチャ判断の分析、レビューフィードバックのスタイル解析。全部できそうに書いてあります。
スクリプトを grep してみると:
gh search prs "author:$USER" --limit $N --json ... > raw_data/prs.json
gh pr view $PR_NUMBER --repo $REPO --json ... > raw_data/pr_${PR_NUMBER}.json
...
cat > "$OUTPUT_DIR/coding_style/naming_conventions.md" << 'EOF'
# Coding Style: [Engineer Name]
## Naming Conventions
...(ハードコードされた汎用テンプレ)
EOF
実体は 「GitHub から生データを取ってくる」+「固定テンプレ文書を書き出す」 の 2 段構えでした。スクリプトは対象エンジニアの PR 内容を一切読み込まず、出力するテンプレは誰を対象にしても同じ。
「パターン認識」「スタイル抽出」という claim に対して、実装はゼロ 。raw data は取ってくるので、その後に別途 LLM で分析する前提の設計でした。
なぜこのズレが起きるか
AI 生成のスキル定義で似たパターンを何度か見たので、仮説を立ててみます。
仮説 1: SKILL.md は LLM の「ベストケース表現」
AI に「このスキルを説明して」と頼むと、機能の 理想像 を書きがちです。「できること」を並べる一方、「実装の制約」や「LLM なしで動く範囲」は抑えめに書かれる。
仮説 2: スクリプトは bash の表現力の範囲で書かれる
一方、実装を bash で書けば、LLM 呼び出しなしでは分析的な処理(パターン認識や文体判定など)はできません。結果として、「データ取得 + 静的テンプレ」という 2 段構成に落ち着きます。
仮説 3: 設計者も SKILL.md と実装が一致しているか確認していない
AI が生成した SKILL.md を読み、AI が生成したスクリプトを採用して、誰も両者の整合を取っていない。
ズレを検知する方法
運用に組み込めるセルフチェックとして、以下の 3 つを使っています。
- SKILL.md の 動詞 をスクリプト実装でトレースする
- 異なる入力で 2 回 実行して生成物を diff する
- スクリプト内に LLM 呼び出しが存在するか を grep で確認する
動詞を実装でトレースする
SKILL.md に含まれる動詞(「抽出する」「分析する」「判定する」「生成する」)を拾って、対応する実装を確認します。
- 「抽出する」 → スクリプトで対象データを解析しているか?
- 「分析する」 → LLM 呼び出し or 解析ロジックがあるか?
- 「判定する」 → 条件分岐やスコアリングがあるか?
- 「生成する」 → 単なるテンプレ出力か、動的生成か?
全部「cat > file << EOF」だけだったら、実装が claim に追いついていない可能性が高い。
実行して生成物を確認する
理想 SKILL.md を信じるより、1 回走らせて生成物を見るほうが確実です。
./scripts/extract_engineer.sh some_user
ls engineer_profiles/some_user/
# → raw_data/*.json は実データ。他の .md はテンプレ?
異なるユーザーで 2 回走らせて、生成物を diff してみる。内容がほぼ同じなら、それは対象非依存のテンプレ生成 です。
LLM 呼び出しの有無をチェック
スクリプト内で curl や anthropic / openai の SDK 呼び出しが 無い場合、分析系の claim は自動で疑う。
# LLM 呼び出しの痕跡を幅広く探す(Claude CLI / Anthropic SDK / OpenAI SDK / Gemini)
# スキルのルート直下すべてを走査する(SKILL.md 内の埋め込みスクリプトも拾う)
grep -rEi --exclude-dir=.git --exclude-dir=node_modules \
"claude +(-p|--print)|curl.*(anthropic|openai|generativelanguage)|anthropic-ai/sdk|import +Anthropic|from +anthropic|import +openai|from +openai|google-generativeai" \
.
ズレが見つかったときの 3 つの対応策
A. 実装を強化する
スクリプトに LLM 呼び出しを追加して、本当に分析するように書き換える。
- メリット: SKILL.md の claim が正しくなる
- デメリット: 開発コスト、API キー管理、コスト管理
B. SKILL.md をダウングレードする
実装の実力に合わせて SKILL.md を書き直す。「静的テンプレ生成 + 生データ取得」と正確に書く。
- メリット: 低コスト、誤解を防ぐ
- デメリット: AI に SKILL.md を「立派に書かせる」という動機と衝突
C. ハイブリッド運用として再定義する(スクリプト + LLM の役割分担)
「スクリプトは材料を用意する」「分析は別途 LLM でやる」というハイブリッド運用を前提にして、SKILL.md にもそう書く。
- メリット: 実装と claim が一致する、運用として現実的
- デメリット: 毎回手動で LLM を呼ぶ必要がある
採用したのは C でした。SKILL.md を書き換えて「raw data 取得はスクリプト、分析は LLM 側で行う」と明示。運用時は raw_data/*.json を Claude に読み込ませて、観点別に抽出プロンプトを投げる流れに。
AI 生成ドキュメントとの付き合い方
この経験から、AI 生成の技術ドキュメントに対するスタンスが変わりました。
- 「書いてある」≠「できる」: 動詞を実装でトレースする
- 実行して確認するコストは安い: 1 回走らせる時間 vs 誤った claim を信じて後で困る時間
- Hybrid 運用が現実的: 完全自動化より、LLM を適切な場所で呼ぶ設計
- SKILL.md の「見栄え」に引っ張られない: 長くて立派だから優れているわけではない
特に、エージェントが自分で作ったスキルを別のエージェントが使う という連鎖で、ズレが増幅しやすいです。1 次情報(実装)に戻って確認する癖が大事。
まとめ
- AI 生成の SKILL.md は claim を過大に書きがち 、実装とのギャップに注意
- ズレ検知は 動詞のトレース + 実行確認 + LLM 呼び出しの有無チェック の 3 つで
- 対応策は 強化 / ダウングレード / ハイブリッド運用 の 3 つから選ぶ
- 長くて立派な SKILL.md ほど、実装との整合を疑う
AI 協働時代のドキュメントは、「書かれたこと」を自動で信じないで、1 次情報に戻って確認する癖 が必要になっています。スキルを採用する前に 1 回走らせる、を運用ルールにしておくと、この手のズレに早く気づけます。
関連記事
-
engineering-process-improvementスキルの運用: 開発セッション直後の振り返りを改善フローにつなげる方法 - AI が読みやすいリポジトリ設計: AI が迷わないリポジトリ設計:長いプロンプトより先に整える4つの置き場所
- SKILL.md と同様に「入口+検証」で運用する考え方: DESIGN.md 導入ガイド: AI実装のための入口・契約・検証をどう整えるか
Discussion