Claude Code の Skills(SKILL.md)入門:スラッシュコマンドとの違いと実用スキル3例【動作確認済み】

- 確認したバージョン
- Claude Code 2.1.303
- 確認日
- 2026/10/19
- 確認した環境
- Debian GNU/Linux 13(GUI なしのサーバー環境)
この記事でわかること
- SKILL.md の置き場所と最小の書き方
- Claude が自動で使う場合と /名前 で呼ぶ場合の違い(実際に確認)
- disable-model-invocation と user-invocable: false の効き方
- claude -p でスキルの自動呼び出しが拒否されたときの対処
- 実用スキル 3 例(差分の要約・リリースノート・表記ルール)
- 旧カスタムスラッシュコマンド(.claude/commands)からの移行手順
目次(10項目)
Claude Code の Skills(スキル) は、SKILL.md というファイルに手順や知識を書いておくと、Claude が必要なときに読み込んで使ってくれる仕組みです。/スキル名 で自分から呼ぶこともできます。
以前からある カスタムスラッシュコマンド(.claude/commands/*.md)とよく似ていて、公式ドキュメントにも「カスタムコマンドはスキルにマージされた」と書かれています。では何が違って、どう移行すればいいのか。実際にスキルを 3 つ作り、旧形式のコマンドからの移行まで試しました。
この記事の画面について
端末の画像は、tmux の capture-pane で取り込んだ文字と色をそのまま画像にしたものです。内容は編集していません。/skills の一覧には筆者の claude.ai アカウントから同期されたスキルも並ぶため、その部分は画像から切り出して省いています。一部の端末画像では、日本語が行末で折り返された位置に表示上の空白が入っています(入力したコマンドには空白はありません)。
検証環境
| 項目 | 内容 |
|---|---|
| 確認日 | 2026-10-19 |
| Claude Code | 2.1.303(ネイティブ版、Claude Pro でログイン) |
| OS | Debian GNU/Linux 13(trixie) |
| モデル | --model haiku(claude -p で 1 回ずつ実行) |
| 検証用リポジトリ | Python のファイル 1 つとコミット 2 つだけの小さな Git リポジトリ |
スキルとスラッシュコマンドの違い
公式ドキュメントの内容と、今回確認したことをまとめます。
| 項目 | スキル(.claude/skills/<名前>/SKILL.md) |
旧コマンド(.claude/commands/<名前>.md) |
|---|---|---|
/名前 で呼ぶ |
できる(確認) | できる(確認) |
| Claude が自動で使う | できる(description を見て判断)(確認) |
未確認(ドキュメントでは name・paths 以外の frontmatter は共通) |
| 補助ファイル(スクリプト・資料) | フォルダにまとめて置ける | 置き場所がない |
name / paths の指定 |
できる | できない(ドキュメントより) |
| 同じ名前があるとき | スキルが優先(確認) | — |
| 今後 | 新しく作るならこちら | 引き続き動く(確認) |
ポイント
スキルの本文は使われるときだけ読み込まれます。普段コンテキストに入るのは description(説明文)だけです。毎回は要らない長い手順書は、CLAUDE.md に書くよりスキルにしたほうがコンテキストを節約できます。
スキルの置き場所
| 場所 | パス | 使える範囲 |
|---|---|---|
| 個人 | ~/.claude/skills/<名前>/SKILL.md |
このマシンのすべてのプロジェクト |
| プロジェクト | .claude/skills/<名前>/SKILL.md |
そのリポジトリ(コミットすればチームで共有) |
| プラグイン | <プラグイン>/skills/<名前>/SKILL.md |
/プラグイン名:スキル名 として |
同じ名前のスキルが個人とプロジェクトの両方にあると、個人のほうが優先されます(ドキュメントより。今回は未確認)。この記事では、試したスキルがほかのプロジェクトに影響しないよう、すべてプロジェクトの .claude/skills/ に作りました。
手順 1:実用スキル 3 例を作る
役割の違う 3 つを用意しました。どれも、使われたことが出力でわかるように、最後に目印の一文を書かせています。
| スキル | 役割 | 呼び出し設定 |
|---|---|---|
summarize-changes-ja |
未コミットの変更を日本語で要約し、危険な点を指摘 | 既定(自分でも Claude でも呼べる) |
release-note |
指定バージョンのリリースノート下書き | disable-model-invocation: true(自分で呼ぶときだけ) |
jp-style |
日本語の表記ルール(背景知識) | user-invocable: false(Claude だけが使う) |
例 1:差分を日本語で要約する(summarize-changes-ja)
公式ドキュメントの最初の例(summarize-changes)を日本語向けにしたものです。!`git diff HEAD` の行は、スキルが Claude に渡される前にコマンドが実行され、その出力に置き換わります(動的コンテキスト注入)。
.claude/skills/summarize-changes-ja/SKILL.md:
---
description: 未コミットの変更を日本語で要約し、危険な点を指摘する。ユーザーが「何を変更した?」「差分を見て」「コミットメッセージを考えて」と聞いたときに使う。
allowed-tools: Bash(git diff *)
---
## 現在の変更
!`git diff HEAD`
## 指示
上の差分を日本語の箇条書き 2〜3 点で要約し、続けて気づいたリスク(ハードコードされた値、エラー処理の欠落、更新が必要なテストなど)を挙げてください。差分が空なら「未コミットの変更はありません」とだけ答えてください。
最後の行に「(summarize-changes-ja スキルで回答)」と書いてください。
例 2:リリースノートの下書き(release-note)
勝手に動いてほしくない作業向けに、disable-model-invocation: true を付けました。$ARGUMENTS には /release-note v0.2.0 の v0.2.0 の部分が入ります。argument-hint は入力中に表示されるヒントです。
.claude/skills/release-note/SKILL.md:
---
description: 指定したバージョンのリリースノート下書きを git log から作る
disable-model-invocation: true
argument-hint: "[version]"
allowed-tools: Bash(git log *)
---
## 直近のコミット
!`git log --oneline -n 10`
## 指示
上のコミット履歴から、バージョン $ARGUMENTS のリリースノート下書きを日本語で作ってください。
見出しは「## $ARGUMENTS」、本文は「追加」「修正」の 2 区分の箇条書きにします。
最後の行に「(release-note スキルで作成)」と書いてください。
例 3:日本語の表記ルール(jp-style)
コマンドとして実行するものではなく、Claude が文章を書くときに参照してほしい知識です。user-invocable: false にすると、/ のメニューに出なくなります。
.claude/skills/jp-style/SKILL.md:
---
description: このプロジェクトで日本語の文章(README、コメント、紹介文、ドキュメント)を書くときの表記ルール。
user-invocable: false
---
このプロジェクトの日本語表記ルール:
- 文体は「です・ます」で統一する
- 「出来る」「下さい」ではなく「できる」「ください」とひらがなで書く
- 1 文は 60 文字以内を目安にする
- 文章の最後に「(jp-style 準拠)」と付ける
比較用に、旧形式のコマンド .claude/commands/todo-scan.md(TODO コメントを表にする)も置いておきました(中身は手順 4 の画面に写っています)。
手順 2:認識されたか確認する
対話モードで /skills を開くと、読み込まれたスキルの一覧が出ます。
release-noteには 「locked by author · user-only」 と表示されました。disable-model-invocation: trueが効いている印です。- 旧形式のコマンド
todo-scanも、同じ一覧に「project」として出ています。 - 右側の
~20 tokなどは、普段コンテキストに入る説明文のおおよそのトークン数です。
/ を入力したときの候補も確認しました。
注意:組み込みコマンドと名前が近い
release-note と組み込みの /release-notes(Claude Code の更新履歴を表示)は 1 文字違いです。Tab 補完で違うほうを選びやすいので、自作スキルには組み込みと紛らわしくない名前を付けたほうが安全です。
手順 3:自動呼び出しと明示呼び出しを試す
ここからは claude -p(非対話モード)で試しました。どのツールが使われたかを見るために --output-format stream-json --verbose で出力し、次の trace.jq で「使われたツール」と「最終回答」だけを取り出しています。
# stream-json から「使われたツール」と「最終回答」だけを取り出す
if .type == "assistant" then
(.message.content[]? | select(.type == "tool_use") | "[tool] \(.name) \(.input | tojson)")
elif .type == "result" then
"[result]\n\(.result)"
else empty end
検証用のリポジトリでは、app.py に「挨拶に『さん』を付ける」変更と、わざとダミーの API キーを直書きした行(API_KEY = "sk-test-1234")を入れてあります。
自動呼び出し:最初は拒否された
summarize-changes-ja の説明文に合う質問「何を変更した?」を投げました。
Claude は自分でスキルを選んで呼ぼうとしましたが、回答の最後に「スキルの呼び出しは失敗した」と書かれています。保存しておいた JSON を見ると、結果の permission_denials に Skill が入っていました。つまり、権限の確認で拒否されていたのです。
{"permission_denials":[{"tool_name":"Skill","tool_use_id":"toolu_…","tool_input":{"skill":"summarize-changes-ja"}}]}
(tool_use_id は省略しています。)
このときの permissionMode は default でした。claude -p では承認を求める画面を出せないため、承認が必要な操作はその場で拒否されます。スキルの呼び出し(Skill ツール)もその対象になっていたようです。
対処:Skill を許可する
--allowedTools で Skill を許可します。特定のスキルだけなら Skill(名前)、すべてなら Skill です(権限ルールの書き方は公式ドキュメントの「Claude のスキルへのアクセスを制限する」にあります)。対話モードで自動呼び出しに承認が求められるかは、この記事では確認していません。
許可すると、Bash を使わずに(差分はスキルに埋め込まれているので)回答しました。ダミーの API キーの直書きもリスクとして指摘されています。
明示呼び出し:/release-note v0.2.0
disable-model-invocation: true のスキルは、自分で /名前 を書いて呼びます。claude -p でも、プロンプトの先頭に書けば動きました。
$ARGUMENTS が v0.2.0 に置き換わっています。今回は --allowedTools を付けなくても動きました(自分で呼ぶ場合は Skill ツールを経由しないため、と考えられますが未確認です)。
disable-model-invocation のスキルは自動では使われない
同じ内容を、スラッシュなしの普通の文で頼みました。権限が理由で使われないのと区別するため、--allowedTools Skill ですべてのスキルを許可しています。
Skill ツールは一度も呼ばれず、Claude は自分で git の履歴を調べて書いていました。目印の「(release-note スキルで作成)」もありません。デプロイやメッセージ送信のように、タイミングを自分で決めたい作業にはこの設定が向いています。
user-invocable: false のスキル
jp-style を /jp-style で呼ぶとどうなるかも試しました。
claude -p '/jp-style'は何も出力せず、終了コード 0 で終わりました。stream-json の結果もnum_turns: 0、コスト 0 で、モデルは呼ばれていません。- 存在しない名前(
/no-such-skill)のときは「インストールされていない」という案内が返ってきたので、反応が異なります。スクリプトで使う場合、エラーにならない点に注意が必要です。
次に、表記ルールが関係しそうな依頼をしました。
Claude が自分で jp-style を読み込み、です・ます調で書いたうえで、最後に「(jp-style 準拠)」を付けました。/ メニューからは隠れていても、Claude からは使えることが確認できました。
手順 4:旧スラッシュコマンドから移行する
まず、旧形式のコマンドがそのまま動くことを確認しました。
移行は、フォルダを作って SKILL.md という名前で置くだけです。frontmatter(description や allowed-tools)はそのまま使えます。今回は、移行したほうが使われたとわかるよう、目印の文だけ書き換えました。
mkdir -p .claude/skills/todo-scan
sed 's#commands/todo-scan.md で実行#skills/todo-scan/SKILL.md で実行#' \
.claude/commands/todo-scan.md > .claude/skills/todo-scan/SKILL.md
旧コマンドを残したまま、同じ名前で /todo-scan を実行しました。
ドキュメントのとおり、スキルのほうが優先されました。動作を確かめたら、旧コマンドを削除して完了です。
移行のチェックリスト
.claude/commands/<名前>.mdを.claude/skills/<名前>/SKILL.mdにコピーする(ファイル名は必ずSKILL.md)- サブフォルダにあったコマンド(例:
commands/frontend/component.md→/frontend:component)は、スキルにすると名前の付き方が変わります。呼び出し名を保ちたいなら frontmatter のnameで調整します(ドキュメントの命名ルールより。今回は未確認) - 両方ある状態で
/名前を実行し、スキル側が動くことを確認する - 旧コマンドを削除する
- 自動で動いてほしくないものには
disable-model-invocation: trueを足す
実際に試した結果
- Claude は
descriptionに合う質問でスキルを自分で選んだ。ただしclaude -pの既定の権限では Skill の呼び出しが拒否され、--allowedTools 'Skill(名前)'で動いた /名前での明示呼び出しは、claude -pでも許可なしで動いたdisable-model-invocation: trueのスキルは、Skill を許可していても自動では使われなかったuser-invocable: falseのスキルは/メニューに出ず、claude -p '/名前'は何も出力せず終了コード 0。Claude からは自動で使われた- 旧形式のコマンドは今も動き、同じ名前のスキルがあるとスキルが優先された
つまずきポイントのチェックリスト
- スキルが自動で使われない
→
claude -pならpermission_denialsを確認し、--allowedToolsで Skill を許可する。説明文に、ユーザーが実際に言いそうな言葉を入れる。 /名前で何も起きない →user-invocable: falseになっていないか確認。/skillsに出ているかも見る。- frontmatter が効いていない気がする
→
---はファイルの 1 行目に置く。項目名を間違えてもエラーにならず無視される(ドキュメントより)。claude plugin validate .claude/skillsで検査できます(v2.1.233 以降、未確認)。 - 動的コンテキスト注入(
!`コマンド`)が失敗する → コマンドが 0 以外で終わるとスキル全体が中止されます(ドキュメントより)。grepのように「見つからないと 1」を返すものは|| trueを付けておくと安心です(今回の todo-scan でも付けています)。
まとめ
まとめ
- スキルは
.claude/skills/<名前>/SKILL.md。旧.claude/commands/も動くが、新しく作るならスキル - Claude は
descriptionを見て自動で使う。claude -pでは--allowedTools 'Skill(名前)'が必要だった - 勝手に動かしたくないなら
disable-model-invocation: true、背景知識ならuser-invocable: false !`コマンド`で最新の情報を埋め込める- 移行はコピーして確認して旧ファイルを消すだけ。同名ならスキルが優先される
スキルはコンテキストの節約にもなります。どれだけ読み込まれているかは /context で確認できます(エラー・利用制限の記事に実際の画面があります)。外部のサービスやデータにつなぎたい場合は MCP、「必ず実行したい処理」なら hooks が向いています。
参考
この記事は、AI を使って下書きを作り、手順とコマンドの出力・画面は筆者の検証環境で実際に実行して確認しています。アイキャッチ画像は生成画像(イラスト)で、実際の画面ではありません。