手元に、自分で書いたか導入したかした skill の定義が64本ありました。35日分のセッション記録を全件数えたら、そのうち61本は一度も起動されていませんでした。
この記事は、その61本を数えた記録です。
結論:SKILL.md を書くだけでは起動しない
Skills は「書いたら Claude が拾ってくれる」仕組みではありません。当メディアの環境では、定義済み64本のうち35日間で1回でも起動されたのは3本でした。起動された自作 skill は、常時読み込まれる CLAUDE.md 側から名前を名指しされている2本だけです。
だから、SKILL.md を書く前に通す分岐は「良い description を書けるか」ではなく「呼ばれる導線を上の層に置けるか」になります。
先に要点を3つ書きます。
- 定義しただけでは起動しない。 64本中61本(95%)が35日間0回。Skill ツールの呼び出しはツール呼び出し全体30,263件のうち29件で、0.096%でした。
- 効いたのは description の厚さではなかった。 自作8本のうち起動されたのは、常時ロード層から名指しされている2本(13回)。名指しの無い6本は0回で、そのなかには description を449字まで書いたものが含まれます。
- 厚く書くと不利に働く場合がある。 公式ドキュメントは、skill 一覧が文字予算を超えると呼び出し回数の少ない skill から説明を削ると説明しています。手元の一覧は26,102字で、既定の1%予算(公式は「1%」とだけ書いており、1Mコンテキストなら10,000字という換算は当メディアの試算)の261%でした。
前提:この記事の数字は何を測ったものか
数字の話に入る前に、何を数えたのかを開示します。集計対象は Claude Code がセッションごとに残す JSONL の記録で、~/.claude/projects 配下の全ファイルです。会話の本文や顧客名は集計にも記事にも出していません。数えているのは件数だけです。
集計に使ったスクリプトは記事内に全文を載せています。同じものを自分の環境で回せば、自分の起動率が出ます。この記事で読者に持ち帰ってほしいのは、当メディアの61という数字ではなく、自分の環境の数字です。
assistant 54,283ターンに対してツール呼び出し30,263件 という比は、1ターンあたり0.56回です。ツールを呼ばない応答(説明・確認・判断だけの応答)が半分近くあるということで、これは体感と合っています。
Claude Code の Skills とは何か
Skills は、SKILL.md に手順を書いてフォルダごと置くと、Claude がツールキットとして扱えるようになる拡張の仕組みです。公式ドキュメントは、同じプレイブックやチェックリストを何度も貼り付けているとき、あるいは CLAUDE.md の節が事実ではなく手順に育ってきたときに作る、と位置づけています。
CLAUDE.md との決定的な違いは読み込みのタイミングです。CLAUDE.md は毎回読まれます。skill の本体は使われるときにだけ読まれるため、長い参照資料を抱えていても、呼ばれるまでのコストはほぼゼロです。
2026年9月時点の公式ドキュメントによると、カスタムコマンドは skill に統合されています。.claude/commands/deploy.md と .claude/skills/deploy/SKILL.md はどちらも /deploy を作り、同じように動きます。既存の commands はそのまま機能し続けます。skill 側が追加で持っているのは、サポートファイル用のディレクトリ、呼び出せる相手を制御する frontmatter、そして Claude が関連すると判断したときに自動で読み込む機能の3つです。
この3つ目、「関連すると判断したときに自動で読み込む」が、この記事で検証する対象です。
35日間の実測:64本中61本が一度も起動しなかった
集計結果を先に出します。ローカルの skills ディレクトリに SKILL.md の実体があるものを、名前の重複を畳んで数えて64本。35日間で1回でも起動されたのは3本、残る61本(95%)は0回でした。
内訳です。
- Skill ツールの呼び出し 29件。同じ期間のツール呼び出し総数は30,263件なので、0.096%
- skill を1回でも起動したセッションは 496件中22件(4.4%)
- 起動された種類は9種。うちローカルに定義の実体があるのは3本で、残る6種は組み込みまたはコマンド由来
比較として、同じ35日のツール呼び出し上位は Bash 19,021件、Read 3,273件、Edit 2,180件、Write 1,726件です。Skill の29件は、この並びのはるか下にいます。
正直に書いておくと、この61本のうち相当数はプラグインを入れたときに付いてきたもので、自分で書いたわけではありません。それでも「入れたが使っていない」ことに変わりはなく、後述するとおり一覧のコンテキストは毎回消費されています。
スラッシュで手動起動した回数は0だった
29件すべてについて、直前のユーザー発話を確認しました。/skill-name の形で手動指定されていたものは0件です。つまり29件はすべて、Claude 側の判断で読み込まれています。
これは良い知らせに見えますが、裏返すと「手で呼ぶ運用が定着していない」ということでもあります。作った本人が呼んでいないものを、モデルが拾ってくれることを期待するのは筋が悪い、というのがこの数字の読み方です。
起動された2本と、されなかった6本の違い
ここが本題です。自作 skill 8本を、起動されたかどうかで二分して、何が違うかを探しました。
差がついたのは description の書き方ではありませんでした。常時読み込まれる設定ファイル(CLAUDE.md と rules/*.md)に skill 名が書かれているかどうかで、きれいに分かれました。
| skill | 常時ロード層に記載 | description | 35日の起動 |
|---|---|---|---|
| chatwork-send | あり | 201字 | 9回 |
| google-data | あり | 239字 | 4回 |
| gcp-account-setup | なし | 180字 | 0回 |
| setup-pengin | なし | 119字 | 0回 |
| takumi-design-direction 他3本 | なし | 390〜449字 | 0回 |
gcp-account-setup は description に「TRIGGER when:〜」という呼び出し条件の記法まで書いてあります。それでも0回でした。逆に、起動された2本の description は201字と239字で、長い側ではありません。
n=8 なので、これだけで断定はしません。 ただし補強材料があります。プラグイン同梱の56本は、すべて description が書かれた状態で一覧に載っており、常時ロード層からは名指しされていません。この56本のうち55本が0回でした。合計64本で見て、常時ロード層から名指しされている2本だけが自作側の起動13回を占めている、という対応になります。
当メディアの CLAUDE.md には、依頼のパターンと起動するものを対応させた節があり、そこに次の2行が入っています。
### タスクトリガー
- Chatwork へ送る / 報告する / 共有する
→ `chatwork-send` SKILL を起動
- GA4 / Search Console / スプレッドシートを扱う
→ `google-data` SKILL を起動
起動された2本は、この2行を持っている2本です。書いてある内容は「skill を起動しろ」だけで、手順は何も書いていません。それでも、この1行の有無が起動13回と0回を分けました。
公式ドキュメントが説明している「説明が削られる」仕組み
前節の結果は、感覚的には description の敗北に見えます。しかし公式ドキュメントを読むと、むしろ description を厚く書くほど不利になりうる仕様が説明されています。
要点はこうです。Claude Code は skill 名と説明の一覧を毎回コンテキストへ読み込みます。一覧には常にすべての skill 名が含まれますが、skill が多い場合は文字予算に合わせて説明のほうが短縮されます。予算はモデルのコンテキストウィンドウの1%でスケールし、あふれたときは呼び出し回数が少ない skill から説明が削られます。
つまり、使われていない skill ほど先に説明を落とされる、という向きの力が働きます。
手元の一覧が予算に対してどれくらいかを数えました。
| 項目 | 実測値 |
|---|---|
| 定義済み skill | 64本 |
| skill 名の合計 | 913字 |
| description + when_to_use の合計 | 25,189字 |
| 一覧の合計 | 26,102字 |
| 既定予算(200Kコンテキストの1%) | 2,000字 → 1,305% |
| 既定予算(1Mコンテキストの1%) | 10,000字 → 261% |
1エントリあたりの上限(1,536字)を超えているものは0本でした。問題は個々の長さではなく、64本ぶんの合計です。
ここは正確に書きます。「削られた瞬間」を直接観測したわけではありません。 観測したのは、入力側の一覧が26,102字あり、公式が既定とする予算の261%であることと、その状態で61本が0回だったことの2つです。仕様の説明と実測が同じ方向を向いている、というところまでが言えることです。
この整理をしてから見ると、description を449字まで書いた4本が0回だったのは、努力不足ではなく構造として説明がつきます。厚く書けば予算を圧迫し、呼ばれていないものから削られ、削られるからさらに呼ばれない。長さで殴る方向には出口がありません。
置き場所で実行率が変わる:Skills / commands / hooks / CLAUDE.md の使い分け
同じ内容を書いても、置き場所によって実際に守られる率が変わります。当メディアは6層で整理していて、上から強制力が強い順です。
hook と skill の差は構造的なものです。当メディアの settings.json は PreToolUse の matcher を Bash にしているため、35日間の Bash 呼び出し19,021回すべての手前を必ず通ります。skill は29回です。守らせたいことを skill に書くと、600分の1の頻度でしか届きません。
{
"hooks": {
"PreToolUse": [
{ "matcher": "Bash",
"hooks": [{ "type": "command", "command": "python ~/.claude/hooks/pre_bash.py" }] }
],
"PostToolUse": [
{ "matcher": "Bash|Agent|Skill",
"hooks": [{ "type": "command", "command": "python ~/.claude/hooks/post_tool.py" }] }
]
}
}
matcher はツール名の完全一致です。Bash のように公式のツール名そのままで書きます(大文字小文字を変えた場合の挙動は、公式ドキュメントに明記がありません)。
| 置き場所 | 向いているもの | 向いていないもの |
|---|---|---|
| hooks | 破ると事故になる操作の禁止・強制 | 判断の質を上げること |
| commands(= skill のスラッシュ起動) | 手で呼ぶ決まった1手順 | 呼ぶのを忘れる作業 |
| Skills | 3ステップ以上の作法一式・参照資料の遅延読み込み | 毎回必ず守らせたい規範 |
| CLAUDE.md(常時ロード) | 判断基準と、下の層への導線 | 長い手順書 |
| subagent | コンテキストを分けたい調査・独立した監査 | コスト削減 |
skill に規範を書かないでください。 事故を止めたいなら hooks です。当メディアが FTP の誤アップロードを止めているのも、回路ブレーカーを鳴らしているのも hooks 側で、この設計と実装はClaude Code hooks の実運用記事に書いています。
逆に、skill が向いているのは「手順が長く、毎回は必要ない」ものです。chatwork-send は送信アカウントの使い分け、ルームIDの解決、To通知の付け方、トーン、承認ゲートまでを一本道にした作法一式で、これを CLAUDE.md に常駐させると毎セッション読まれて薄まります。使うときだけ読み込ませたいから skill にしています。
権限と安全:skill に実行系を持たせるときの線引き
skill は frontmatter の allowed-tools で、そのスキルが動いている間だけツールを事前承認できます。公式ドキュメントは、これは利用可能なツールを制限するものではなく権限を付与するものだと明記していて、プロジェクトの .claude/skills/ に入っている skill については、リポジトリを信頼する前に中身を確認するよう促しています。
当メディアが skill に実行系を持たせるときの線は3つです。
- 読む・調べる・下書きする:承認を取らずに実行してよい。ルームIDの解決や過去ログの確認はここ
- ローカルへ書く:実行して、差分という証拠を残す。下書きの保存はここ
- 外部へ送る・本番へ出す:1件ずつ承認を取る。Chatwork 送信と FTP アップロードはここ
承認をまとめて取らせないでください。 これは実際に事故った側の話で、まとめて取った承認は必ず別の操作へ流用されます。chatwork-send は「提示はまとめて、同意は1件ずつ」を skill の本文に書いています。起動されても、送信の直前で必ず止まります。
allowed-tools を書くときも同じ線でいきます。読み取り系は事前承認しても実害がありません。送信・アップロード・削除を含むコマンドを事前承認すると、skill が自動起動した瞬間に承認ゲートが消えます。
---
name: review-diff
description: 変更差分をレビューする
# 読み取り系だけを事前承認する
allowed-tools: Bash(git status *) Bash(git diff *) Read Grep
# 送信・削除・デプロイは書かない。書くと自動起動の瞬間にゲートが消える
# allowed-tools: Bash(git push *) Bash(rm *)
---
特定のツールを skill から取り上げたい場合は disallowed-tools を使います。ブロックしたいだけなら、skill 側ではなく権限設定の deny ルールへ書くほうが確実です。
disallowed-tools: AskUserQuestion # 止まらずに走り切らせたい自律 skill 向け
skill 本文にも、承認の線を文章で残しておきます。frontmatter は権限を扱いますが、「1件ずつ取る」という運用の作法までは表現できません。
### 承認が必要な操作
- 送信・アップロード・削除は、対象1件ごとに承認を取る
- 提示はまとめてよいが、同意は1件ずつ取る
- 過去の承認を別の操作へ流用しない
基本操作:置き場所・書き方・呼び出し方
置き場所によって、誰がその skill を使えるかが決まります。個人用は全プロジェクトで、プロジェクト用はそのリポジトリだけで、プラグイン用はプラグインが有効な場所で効きます。
~/.claude/skills/<name>/SKILL.md 個人用(すべてのプロジェクト)
<repo>/.claude/skills/<name>/SKILL.md プロジェクト用(このリポジトリのみ)
<plugin>/skills/<name>/SKILL.md プラグイン同梱
同じ名前が複数のレベルにある場合、personal がプロジェクトを上書きします。プラグインの skill は plugin-name:skill-name の名前空間を持つので衝突しません。
フォルダの中身は、必須が SKILL.md だけで、あとは必要になってから足します。
~/.claude/skills/chatwork-send/
├── SKILL.md 必須
├── references/ 長い資料。呼ばれたときだけ読まれる(この名前は当メディアの構成。公式の例は reference.md と scripts/)
├── templates/ 雛形(同上・名前は任意)
└── scripts/ 実行するスクリプト
SKILL.md の最小形はこれだけです。
---
name: chatwork-send
description: Chatwork へメッセージを送る時の作法一式。送信アカウントの使い分け・ルームID解決・To通知・トーン・承認ゲートまで。TRIGGER when:「送って」「報告して」「共有して」。SKIP for:読み取りのみ、メール送信。
---
### 手順
1. 送信アカウントを確定する
2. ルームIDを解決する
3. 本文を作り、送信前に本人へ提示する
4. 同意を1件ずつ取ってから送る
frontmatter はすべて任意で、推奨されているのは description だけです。省略すると本文の最初の空でない行が使われます。呼び出しは /chatwork-send で手動、あるいは Claude の判断で自動です。
自動で拾われたくない、手で呼ぶときだけ動かしたい、という skill にはこれを足します。
---
name: deploy
description: 本番へ反映する
disable-model-invocation: true # 自動起動しない。/deploy でのみ動く
user-invocable: true # false にすると / メニューから隠れる
---
引数を渡したいときは $ARGUMENTS を置きます。/fix-issue 123 と打つと、そこへ 123 が入ります。
---
name: fix-issue
description: GitHub の issue を番号で直す
argument-hint: [issue-number]
disable-model-invocation: true
---
issue $ARGUMENTS を、社内のコーディング規約に従って修正する。
期待どおりに読み込まれないときは、次の2つで切り分けます。frontmatter の YAML が壊れていると、スラッシュ指定では動くのに自動では一致しなくなります。
claude --debug # frontmatter のパースエラーと、一覧の予算超過警告が出る
/doctor # skill 一覧のコンテキストコストと、その主な内訳を見る
/context # 予算適用後の skill 行のサイズ(モデルが実際に受け取る量)
description の書き方で1つだけ効くと分かっているのは、ユーザーが実際に打つ言葉を前に置くことです。公式ドキュメントも、一覧が短縮される前提で主要なユースケースを前置きするよう案内しています。「Chatwork へメッセージを送る」より前に「送って」「報告して」が来ているほうが一致します。
メリットとデメリットを実測で書く
35日回した実感を、良い側と悪い側の両方で書きます。
| 内容 | 根拠 | |
|---|---|---|
| 利点 | 長い参照資料を、使うときだけ読み込める | CLAUDE.md に置くと毎回読まれて他が薄まる |
| 利点 | 作法の抜けが減る。承認ゲートを手順に埋め込める | chatwork-send は9回とも承認ゲートを通った |
| 利点 | 1フォルダで完結するので配布しやすい | scripts・templates を同梱できる |
| 欠点 | 定義しても起動されない | 64本中61本が35日0回 |
| 欠点 | 一覧が毎セッション コンテキストを食う | 26,102字。1%予算の261% |
| 欠点 | 使わない skill が、使う skill の説明枠を奪う | 予算超過時は呼び出しの少ない側から削られる仕様 |
一番効いたのは3つ目の欠点です。プラグインを入れるほど、自分で書いた skill の説明が削られやすくなります。 使っていないプラグインを外すのは、掃除ではなく起動率の改善策でした。
死んでいる skill を起動される skill に直す4手順
当メディアが chatwork-send と google-data で実際に通した順番です。順番に意味があります。
01 起動回数を数える。 推測でどれが使われていないかを決めないでください。次のスクリプトで自分の環境の実数が出ます。
import json, os, pathlib
from collections import Counter
projects = pathlib.Path(os.path.expanduser("~")) / ".claude" / "projects"
calls, tools = Counter(), 0
for jf in projects.rglob("*.jsonl"):
for line in jf.read_text(encoding="utf-8", errors="replace").splitlines():
if not line.strip():
continue
try:
rec = json.loads(line)
except ValueError:
continue
if rec.get("type") != "assistant":
continue
for b in (rec.get("message") or {}).get("content") or []:
if isinstance(b, dict) and b.get("type") == "tool_use":
tools += 1
if b.get("name") == "Skill":
calls[(b.get("input") or {}).get("skill", "?")] += 1
print("tool calls:", tools, "/ skill calls:", sum(calls.values()))
for name, n in calls.most_common():
print(" ", name, n)
02 常時ロード層に1行足す。 CLAUDE.md に「この依頼が来たらこの skill を起動する」と名指しで書きます。手順は書きません。書くのは対応だけです。当メディアの実測で、起動13回と0回を分けたのはこの1行でした。
03 description を条件文に直す。 「何をするか」ではなく「いつ使うか」を、ユーザーが打つ言葉で前に置きます。長さは足しません。むしろ削ります。
04 1週間後にもう一度数える。 増えていなければ、それは skill に向いていない作業です。守らせたいことなら hooks へ、手で呼ぶ1手順なら commands へ移します。直らないものを直そうとし続けないでください。 当メディアは、この判断をせずに4本を放置して35日を使いました。
この記事で使っている skill の骨格と、導線設計のチェックリストを配布しています。SKILL.md の最小テンプレート、description を条件文に直す前後の実例、常時ロード層に足す1行の書き方、起動回数を数えるスクリプト、そして skill / commands / hooks / CLAUDE.md の振り分け表をまとめたものです。顧客名・実案件・認証情報・社内パスは含みません。ライセンスは自由で、帰属表示も不要です。
この検証の限界
数字の弱いところを書いておきます。
- 自作 skill は8本しかありません。 常時ロード層への記載と起動回数の対応はきれいに出ましたが、n=8です。プラグイン56本の0回が補強材料になっているものの、これは因果の証明ではなく相関の観測です
- 「説明が削られた瞬間」は観測していません。 観測したのは入力側の一覧が26,102字あることと、公式の仕様説明です
- 35日という期間は、skill の性質に対して短い可能性があります。 月1回しか発生しない作業の skill は、この集計では0回に見えます
- 1人の環境の記録です。 チームで運用した場合に同じ傾向が出るかは確認していません
そのうえで、再現の手順は上に全部載せました。自分の環境で数えれば、この記事の主張が自分にも当てはまるかは1分で判定できます。
よくある質問
SKILL.md を書いたのに Claude が使ってくれません。何から見ればよいですか
まず frontmatter の YAML が壊れていないかを確認してください。公式ドキュメントによると、YAML が不正な場合は本体が空のメタデータで読み込まれ、スラッシュ指定では動くのに自動では一致しなくなります。claude --debug でパースエラーを確認できます。
それが問題なければ、description を直す前に、常時読み込まれる設定ファイル側に「この依頼が来たらこの skill を起動する」という1行を足してください。当メディアの環境では、この1行がある2本だけが35日間で起動され、無い6本は0回でした。
description は詳しく書いたほうが起動されやすいですか
当メディアの実測では、そうなりませんでした。description を390字から449字まで書いた4本は35日間0回、201字と239字の2本が13回です。
公式ドキュメントは、skill 名と説明の一覧を毎回コンテキストへ読み込み、一覧が文字予算を超えると呼び出し回数の少ない skill から説明を削ると説明しています。手元の一覧は26,102字で、既定の1%予算(公式は「1%」とだけ書いており、1Mコンテキストなら10,000字という換算は当メディアの試算)の261%でした。厚く書くほど予算を圧迫し、使われていない skill ほど先に説明を落とされます。長さではなく、ユーザーが実際に打つ言葉を前に置くほうが効きます。
Skills と hooks と commands はどう使い分ければよいですか
破ると事故になることは hooks、決まった1手順の呼び出しは commands、複数ステップの作法一式が Skills です。強制力が違います。
当メディアの PreToolUse hook は対象を Bash にしているため、35日間の Bash 呼び出し19,021回すべての手前を必ず通りました。同じ期間の Skill 起動は29回です。守らせたいのか、思い出させたいのかで層を選んでください。
Claude Code の周辺は、料金の考え方、Windows で運用するときの罠、Codex との併用、subagent を使ったレビュー体制にも実測記録を置いています。skill を直す前に、そもそも何を自動化すべきかで迷っているなら、そちらから読んでも構いません。
訂正履歴
- 2026-10-05: 公式ドキュメント(skills 日英・hooks 日本語)を再取得して照合(26日ぶり)。保存場所・frontmatter のキー・1%予算・1,536字・hook のイベント名と matcher の仕様は変更なし。表現を4か所直した。(1)description を省略したときに使われるのは「最初の段落」ではなく「最初の空でない行」だった (2)matcher の大文字小文字の区別と「黙って何も起きない」は公式に記載が無いため、公式の「完全一致」の範囲に書き直した (3)構成例の references/ と templates/ は当メディアの命名で、公式の例は reference.md と scripts/ である旨を添えた (4)1%予算の「2,000字/10,000字」は当メディアの換算である旨を明記した。公式には新しい設定(skillListingBudgetFraction・skillListingMaxDescChars・skillOverrides)と
claude plugin evalが増えているが、本記事の実測期間には無かった機能なので本文には足していない
よくある質問