Claude Codeのスキル自作|SKILL.mdが呼ばれない7つの原因
この記事でわかること
- 自作した
SKILL.mdが Claudeに自動で呼ばれない ときに、どこを疑えばいいか- スキルの置き場所・frontmatterの各フィールドが、呼ばれるかどうかにどう効くか
- 「呼ばれるスキル」にするための
descriptionの書き方対象読者: Claude Codeでスキル(Agent Skills)を自作していて、
/名前では動くのに自動では発動しない人。
要点(TL;DR)
- スキルが自動で呼ばれるかは、ほぼ
description(+when_to_use)だけ で決まる。Claudeは本文を読まずに、この一覧を見て「使うかどうか」を判断する。 - だから
descriptionに ユーザーが実際に言う言葉(トリガー語)を書かないと、永遠に呼ばれない。 - 置き場所は
~/.claude/skills/<スキル名>/SKILL.mdのディレクトリ形式が必須。skills/foo.mdのように直置きしても読まれない。 -
disable-model-invocation: trueは「/で手動専用」にするフラグ。これが付くと description ごと文脈から消え、自動発動しなくなる。 -
syncedは予約ディレクトリ名。自分のスキルにこの名前を付けると読み込み対象から外れる。
動作環境 / 前提
本記事の確認環境は以下。
| 項目 | 値 |
|---|---|
| 機種 | Mac mini(Apple M6 / メモリ32GB) |
| OS | macOS 27.0.1(ビルド 26A434) |
| Claude Code | 2.1.312 |
| スキル配置 |
~/.claude/skills/(personal)および <repo>/.claude/skills/(project) |
フィールド名・上限値の仕様は公式ドキュメント(Agent Skills)に準拠する。
Claude Codeは更新が速いので、フィールドの対応状況はお使いのバージョンで確認してほしい。
スキルが呼ばれるまでの流れ
まず「どこで落ちるのか」を把握すると切り分けが速い。発動までは大きく4段階ある。
重要なのは E の段階でモデルに渡るのは本文ではなく description だけ という点。
本文にどれだけ丁寧な手順を書いても、発動判定には使われない。
実際、この記事を書いているセッションでも、スキルは
「名前+descriptionの1行要約」の一覧としてモデル側に提示されていた。
つまり description は内部メモではなく、発動用の検索インデックスだと考えるのが正しい。
原因1: ディレクトリ形式になっていない
一番多い。スキルは「ファイル1枚」ではなく「ディレクトリ+その中の SKILL.md」で置く。
# 正しい(読まれる)
~/.claude/skills/pv-check/SKILL.md
# 誤り(読まれない)
~/.claude/skills/pv-check.md
~/.claude/skills/SKILL.md
探索される場所は次の通り。
| 種別 | パス |
|---|---|
| 個人(全プロジェクト共通) | ~/.claude/skills/<name>/SKILL.md |
| プロジェクト | <repo>/.claude/skills/<name>/SKILL.md |
| サブディレクトリ |
<subdir>/.claude/skills/<name>/SKILL.md(必要時に読み込み) |
| 追加ディレクトリ |
--add-dir で渡した場所の .claude/skills/<name>/SKILL.md
|
| プラグイン |
<plugin>/skills/<name>/SKILL.md(/plugin名:skill名 で呼ぶ) |
プロジェクトスキルは、起動ディレクトリからリポジトリルートまでの各階層が探索される。
.claude/skills をリポジトリルート以外の深い場所に置いて「出てこない」と悩むケースがあるので、
まず ls で位置を確認するのが早い。
# 個人スキルと、いまのリポジトリのプロジェクトスキルを列挙する
# (カレントを . にすると home 全体を走査して固まるので、対象を絞るのがコツ)
find ~/.claude/skills .claude/skills -maxdepth 3 -name SKILL.md 2>/dev/null
原因2: frontmatterが1行目から始まっていない
frontmatterは --- で囲むが、開始の --- がファイルの1行目でなければならない。
先頭に空行やコメント、BOM、見出しが入ると frontmatter として解釈されず、description が拾われない。
---
name: pv-check
description: ...
---
空行が1行入っているだけで落ちるため、確認は機械的にやるとよい。
# 1行目が --- になっているスキルだけを合格として表示する
for f in ~/.claude/skills/*/SKILL.md; do
head -1 "$f" | grep -q '^---$' && echo "OK $f" || echo "NG $f"
done
description を省略した場合は本文の最初の非空行が代わりに使われる仕様なので、
「なぜか見出しがdescription扱いになっている」ときはfrontmatterの解釈に失敗している疑いが濃い。
原因3: descriptionに「言われ方」が書いていない
ここが本質。description は「このスキルは何をするか」だけでなく
**「どう言われたときに使うか」**を含める必要がある。
悪い例と良い例を比べる。
# 悪い: 何をするかしか書いていない → ユーザーの発話と結びつかない
description: PVを集計する。
# 良い: 機能 + トリガー語 + 対象外の明示
description: >
Qiita記事のPV・LGTM数を取得して一覧表示する。
「PVを見て」「アクセス数どうなってる」「記事の数字を集計して」
などと言われたときに使う。記事の執筆・投稿そのものは別スキル。
筆者が実際に使っているスキルも、description に
「『定期実行』『毎朝〜して』『◯分ごとに』『cron』『ジョブのログ』『止めて』などのときに使う」
という想定発話を列挙し、さらに「クラウドで動かすものではなく、このMacで動かすもの」と
似て非なるスキルとの境界まで書いている。これが効く。
書くときのチェックリスト:
- ユーザーが使う口語の言い回しを2〜5個入れた
- 業務固有の名詞(製品名・スクリプト名)を入れた
- 紛らわしい別スキルとの使い分けを1文で書いた
- 「〜のときに使う」という発動条件の形で締めた
長すぎるdescriptionは切られる
description と when_to_use は、一覧に載る際に 合計1,536文字で切り詰められる。
延々と書くと、末尾に置いたトリガー語が落ちて発動しなくなる。
重要な言い回しは必ず前半に置くこと。
原因4: 自動呼び出しを自分で切っている
frontmatterには、呼ばれ方を制御するフィールドが2つある。混同しやすい。
| フィールド | 既定 |
true/false にすると |
|---|---|---|
disable-model-invocation |
false |
true で Claudeの自動発動を止める。descriptionが文脈から消え、/名前 の手動専用になる |
user-invocable |
true |
false で /メニューから隠す。descriptionは残るのでClaudeからは呼べる |
つまり「自動で呼ばれない」なら disable-model-invocation を、
「/に出てこない」なら user-invocable を疑う。効果が逆方向なので取り違えると延々ハマる。
---
name: dangerous-deploy
description: 本番デプロイを実行する。
disable-model-invocation: true # 事故防止。人間が /dangerous-deploy と打つまで動かない
---
破壊的操作のスキルは、むしろ意図的に true にしておくのが安全側。
原因5: ディレクトリ名が予約語になっている
次の名前は読み込まれない。知らないと原因不明の「無反応」になる。
-
synced(大文字小文字を問わず)… claude.ai アカウントから同期されたスキルの置き場所として予約済み。
実機でも~/.claude/skills/synced/が存在していた。ここに自作スキルを置いても読まれない。 -
anthropic-skillsおよびanthropic-skills:で始まる名前 … プラグイン外では読み込まれない。
また、ディレクトリ名と frontmatter の name には使えない文字がある。
| 禁止 | 具体例 |
|---|---|
| ゼロ幅・制御文字 |
U+200B など |
| 私用領域・未割り当て文字 | 外字 |
| 書字方向を変える文字 |
U+202E など |
| 通常でない空白 | ノーブレークスペース、連続スペース、前後のスペース |
| 山括弧 |
< >
|
地味に踏むのは「前後のスペース」。name: pv-check のように末尾に空白が入っていると弾かれる。
エディタの自動整形で入ることがあるので、疑ったら可視化する。
# name 行の末尾に不要な空白がないか確認する
# macOS(BSD)の cat に -A は無いので、grep の POSIX 文字クラスで見る
grep -nE 'name:.*[[:blank:]]$' ~/.claude/skills/*/SKILL.md || echo "(末尾空白なし)"
原因6: pathsで自動発動を絞っている
paths にglobを書くと、一致するファイルを扱っているセッションでしか自動ロードされない。
---
name: migration-helper
description: DBマイグレーションの書き方を案内する。
paths:
- "db/migrate/**"
---
便利な反面、「普段は出てこない」状態を自分で作ってしまう。
常時効かせたいスキルに paths を付けていないか確認する。
原因7: スキルが多すぎて埋もれている
スキルの説明文は起動時にまとめて文脈へ載る。数が増えるほど、
似た description 同士でどれを選ぶべきか曖昧になる。
公式ドキュメントでは、SKILL.md は 500行未満に収めることが推奨されている(厳格な上限ではない)。
また自動コンパクション時には、呼ばれたスキルごとに先頭 5,000トークン、
全スキル合計 25,000トークンまでが再添付される、という budget が示されている。
対策は単純で、
- 1スキル=1目的に割る(「書く」と「投稿する」を混ぜない)
- 長い手順は別ファイルに逃がし、
SKILL.mdからは参照だけにする - 似たスキルには description に相互の使い分けを明記する
つまずきポイント
/名前 では動くのに自動では呼ばれない
典型は 原因3(descriptionにトリガー語がない) か 原因4(disable-model-invocation: true)。
手動呼び出しは description を見ないので動いてしまい、切り分けを誤らせる。
まず frontmatter を疑い、次に description を「言われ方」に書き換える。
一覧にそもそも出てこない
/ を打って候補に出ないなら、発動判定より前(探索・パース)で落ちている。
原因1・2・5 のどれか。find と head -1 の2コマンドで大半が判明する。
外部にアップロードすると弾かれる
Claude Code は知らない frontmatter フィールドを黙って無視するが、
claude.ai へのアップロードや Skills API では、
name / description / license / compatibility / metadata / allowed-tools 以外のキーが
ハードエラーになる。Claude Code 用に effort や hooks を書いたスキルは、そのままでは通らない。
配布を考えるなら、ローカル専用フィールドは分けておくと安全。
未検証事項(正直に)
- 本記事の フィールド名・上限値(1,536文字 / 500行 / 5,000・25,000トークン)は公式ドキュメントの記載であり、
筆者が計測して確かめたものではない。 - 「descriptionにトリガー語を入れると発動率が上がる」は、筆者の運用実感と仕様の読み合わせによる推論。
自動発動する/しないのA/B比較は未実施。今回、検証用スキルを/tmpに置いて
claude -pで自動発動を試そうとしたが、非対話シェルで認証が通らず計測できなかった(Not logged in)。
ここは対話セッションで改めて確認したい。 -
pathsの glob の詳細な一致規則(相対/絶対、**の扱い)は未検証。
まとめ
- 自動発動の判定材料は
description(+when_to_use)だけ。本文は判定に使われない。 -
descriptionには「機能」ではなく 「どう言われたら使うか」 を書く。想定発話を並べるのが効く。 - 呼ばれないときの切り分け順序は ①配置 → ②frontmatterの1行目 → ③予約語・禁止文字 → ④
disable-model-invocation→ ⑤descriptionの言い回し。 -
disable-model-invocation(自動を止める)とuser-invocable(/から隠す)は逆方向。取り違えに注意。 - 上限値は公式ドキュメント由来、発動率の改善効果は筆者の推論(未検証)。
次に読む / 続編
- 同じ
~/.claude配下の自動化として、以前 Claude Codeのhooks(PreToolUse)で危険なコマンドを止める話を書いた。スキルが「何をするか」を足す仕組みなら、hooksは「何をさせないか」を足す仕組みで、併用すると安定する。 - 次は、スキルを cron から
claude -pで定期実行して日次バッチにする構成を、認証まわりの詰まりどころ込みで書く予定。 - 自作スキルが呼ばれない事例があれば、
descriptionの実物つきでコメントしてもらえると助かる。追記していく。