Claude Code の Skill は、SKILL.md というファイルを 1 つ入れたフォルダを .claude/skills/ に置くだけで作れます。 ファイルの先頭に YAML の frontmatter(--- で囲んだ設定)、その下に Claude への指示を Markdown で書きます。フォルダ名が /スキル名 というコマンドになり、description を見て Claude が自動で読み込むこともあります。

この記事は「作る」ことに絞って、そのまま置ける SKILL.md の全文を 5 種類、frontmatter 全 20 項目の日本語一覧、置換変数・置き場所の表、description の直し方、発火しない時の確認表をまとめました。雛形は claude plugin validate と、記事内の検査スクリプトを通した結果を載せています。

確認環境:Claude Code 2.1.292(Linux x64)、Python 3.11.15、PyYAML 6.0.3、git 2.43.0。仕様は 2026年10月7日に公式ドキュメント(code.claude.com/docs/en/skills)を開いて確認しました。

SKILL.md の早見表

やりたいこと 書くもの
いつ使うスキルかを伝える description(+ when_to_use)
自分が呼んだ時だけ動かす disable-model-invocation: true
Claude だけが使う背景知識にする user-invocable: false
引数を受け取る 本文に $ARGUMENTS・$0・$名前
実行時の情報を埋め込む 本文に !`コマンド`
確認なしで使わせるツールを決める allowed-tools
別のコンテキストで動かす context: fork(+ agent)
特定のファイルを触る時だけ読み込む paths
置き場所 パス 使える範囲
個人 ~/.claude/skills/<スキル名>/SKILL.md 自分の全プロジェクト
プロジェクト .claude/skills/<スキル名>/SKILL.md そのリポジトリ(コミットで共有)

すべての項目は省略できます。 推奨されているのは description だけです。

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Claude Code Skillsの作り方|SKILL.md雛形と項目一覧」

最小の SKILL.md と作成の手順

mkdir -p .claude/skills/pr-checklist

フォルダの中に SKILL.md を作ります。frontmatter は、ファイルの 1 行目が --- のときだけ読まれます。 1 行目が空行だったりすると、--- も含めて全部が本文として扱われます。

---
description: プルリクエストを出す前の確認手順。lint・テスト・差分の見直しを順に行う。
---

1. `npm run lint` を実行する
2. `npm run test` を実行する
3. `git diff main...HEAD --stat` で変更ファイルを確認する

試し方は 2 通りです。

  • 直接呼ぶ:メッセージの先頭に /pr-checklist と書く
  • Claude に任せる:description に合う頼み方をする(「PR を出す前に確認して」など)

Claude Code はスキルのフォルダを監視しているので、追加・編集・削除はセッションを再起動しなくても反映されます。セッション開始後に .claude/skills/ フォルダそのものを新しく作った場合は、/reload-skills を実行します。

そのまま置ける SKILL.md の雛形 5 種

5 つとも .claude/skills/<フォルダ名>/SKILL.md として保存します。

1. 手順書型

決まった手順をそのまま書く、いちばん基本の形です。when_to_use に「こう言われたら使う」という言い回しを足しています。

---
name: pr-checklist
description: プルリクエストを出す前の確認手順。lint・テスト・差分の見直し・説明文の下書きを順に行う。
when_to_use: 「PRを出したい」「レビュー依頼の前に確認して」「プルリク前チェック」と言われたとき。
---

# プルリクエスト前チェック

次の順に進める。どれかで止まったら、そこで報告して先に進まない。

1. `git status --short` で、コミットしていない変更がないか確認する
2. `npm run lint` を実行し、指摘があれば直す
3. `npm run test` を実行し、通らないテストがあれば原因を報告する
4. `git diff main...HEAD --stat` で変更ファイルを一覧し、意図しないファイルが混ざっていないか確認する
5. 次の形式で説明文の下書きを出す

## 説明文の形式

- 概要(1〜2 行)
- 変更点(箇条書き)
- 確認方法(実行したコマンドと結果)
- 影響範囲(触れた機能、触れていない機能)

## 守ること

- テストを通すためにテスト側を弱めない
- 秘密情報(.env、鍵、トークン)を差分に含めない

2. 引数つき($ARGUMENTS と名前付き引数)

/new-component SearchBar src/components のように呼ぶスキルです。arguments に並べた名前が、引数の位置に順番に対応します。

---
name: new-component
description: React コンポーネントのひな形(本体・テスト・index)を指定のディレクトリに作る。
argument-hint: "[コンポーネント名] [ディレクトリ]"
arguments: [component, dir]
disable-model-invocation: true
allowed-tools: Bash(mkdir -p *)
---

# コンポーネントの追加

`$dir/$component/` に次の 3 ファイルを作る。

- `$component.tsx`:関数コンポーネント。props の型は「コンポーネント名 + Props」という名前で定義する
- `$component.test.tsx`:描画できることを確かめるテストを 1 件
- `index.ts`:`export * from "./$component";`

## 入力

- 1 つ目の引数(`$0`):コンポーネント名。PascalCase にそろえる
- 2 つ目の引数(`$1`):作成先のディレクトリ
- 受け取った引数の全体:$ARGUMENTS

## 手順

1. `$dir` が存在するか確認し、なければ作ってよいか尋ねる
2. 同じ名前のディレクトリがすでにあれば、上書きせずに報告する
3. 3 ファイルを作り、`npm run lint` を実行する
  • $component は 1 つ目、$dir は 2 つ目の引数に置き換わります。$0・$1 でも同じ値を取れます。
  • 空白を含む値は /new-component "Search Bar" src のように引用符で囲むと 1 つの引数になります。
  • ファイルを作る操作なので、disable-model-invocation: true で「自分が呼んだ時だけ」にしています。
  • allowed-tools はこのスキルを呼んだターンの間だけ、挙げたツールを確認なしにします。次のメッセージを送ると解除されます。

3. 動的コンテキスト注入(!コマンド)

!`コマンド` と書いた場所は、Claude に渡る前にコマンドの出力に置き換わります。

---
name: summarize-changes
description: コミットしていない変更を要約し、気を付ける点を挙げる。変更内容を聞かれたとき、コミットメッセージを考えるとき、差分の見直しを頼まれたときに使う。
allowed-tools: Bash(git status *) Bash(git diff *) Bash(git log *)
---

## 現在のブランチと状態

!`git status --short --branch`

## 変更の量

!`git diff HEAD --stat`

## 直近のコミット

!`git log --oneline -5`

## やること

上の情報をもとに、次の順でまとめる。

1. 変更の要約を 2〜3 行で書く
2. 気を付ける点(例外処理の抜け、直書きの値、更新が必要なテスト)を箇条書きにする
3. コミットメッセージの案を 1 つ出す(1 行目は 50 字以内)

差分が空なら「コミットしていない変更はありません」とだけ答える。

このスキルが埋め込む 3 つのコマンドを、テスト用のリポジトリで実行した出力です。スキルを呼ぶと、この内容が見出しの下に入った状態で Claude に渡ります。

$ git status --short --branch
## master
 M src/api/tasks.ts
?? README.md
$ git diff HEAD --stat
 src/api/tasks.ts | 4 ++++
 1 file changed, 4 insertions(+)
$ git log --oneline -5
6c904ce API の初期ファイルと Claude Code のスキルを追加

書くときの注意点です。

  • ! は行頭か空白の直後に置きます。 KEY=!`cmd` のように別の文字に続けると、そのまま文字列として残ります。
  • 複数行のコマンドは、バッククォート 3 つに ! を付けた行で始まるコードブロックに書きます(下の例は 4 文字の字下げで示しています)。

    ## 環境
    ```!
    node --version
    git status --short
    ```
    
  • コマンドが失敗すると、スキルの呼び出し全体が中止されます(0 以外の終了コード)。失敗してもよいコマンドには || true を付けます。検索・比較系のコマンドが返す終了コード 1 は、通常の結果として扱われます。

  • 埋め込みコマンドは確認の画面を出しません。権限ルールで allow にならないコマンドは中止の理由になるので、allowed-tools に同じコマンドを書いておきます。
  • コマンドはセッションのシェルの現在のディレクトリで動きます。場所に左右されたくないパスは ${CLAUDE_SKILL_DIR} や ${CLAUDE_PROJECT_DIR} で書きます。
  • 1 つのコマンドの制限時間は Bash ツールの既定と同じ 2 分です。

4. context: fork(サブエージェントで動かす)

スキルの本文を、会話の履歴を持たない別のサブエージェントへの依頼文として渡します。調べ物のように、メインの会話を汚さずに結果だけ受け取りたい作業に向いています。

---
name: find-usages
description: 関数・クラス・設定キーがどこで使われているかを調べ、ファイルと行番号つきで報告する。影響範囲を調べたいとき、名前を変える前に使う。
argument-hint: "[調べたい名前]"
context: fork
agent: Explore
background: false
---

`$ARGUMENTS` の使用箇所を調べる。

1. Grep で `$ARGUMENTS` を検索する(定義・呼び出し・import・テスト・ドキュメント)
2. 見つかったファイルを読み、種類ごとに分ける
3. 次の形式で報告する

## 報告の形式

- 定義:`ファイルパス:行番号`
- 呼び出し:`ファイルパス:行番号`(1 行の説明つき)
- テスト:`ファイルパス:行番号`
- 文字列として現れる箇所(設定ファイル、ドキュメント)
- 変更するときに気を付ける点を 3 つまで

見つからない場合は、検索した語と対象ディレクトリを添えて「見つかりませんでした」と報告する。
  • agent には組み込みの Explore・Plan・general-purpose か、.claude/agents/ に置いた自作のサブエージェントを書きます。省略時は general-purpose です。
  • サブエージェントは会話の履歴を見られません。本文だけで作業が完結するように、やることと報告の形式を書き切ります。
  • 既定ではバックグラウンドで動き、終わると結果が会話に届きます。background: false にすると、呼び出したターンの中で結果を待ちます(v2.1.218 以降)。
  • 「この規約に従う」のような指針だけのスキルに context: fork を付けると、サブエージェントは作業の指示を受け取れません。手順のあるスキルで使います。

5. paths(対象ファイルを限定する)

paths に書いたパターンに合うファイルを扱っている時だけ、Claude が自動で読み込むスキルです。

---
name: api-conventions
description: このリポジトリの API エンドポイントの書き方(命名・エラー形式・入力検証)。src/api 以下を編集するときに従う。
paths:
  - "src/api/**/*.ts"
  - "src/api/**/*.test.ts"
user-invocable: false
---

# API の書き方

`src/api/` 以下のファイルを追加・変更するときは、次に従う。

## 命名

- パスは複数形の名詞にする(`/tasks`、`/members`)
- ハンドラー名は `動詞 + 名詞`(`listTasks`、`createTask`)

## エラー形式

エラーは必ず次の形で返す。

    { "error": { "code": "TASK_NOT_FOUND", "message": "..." } }

## 入力検証

- リクエストボディはハンドラーの最初で検証する
- 検証に通らない場合は 400 と、どの項目が合わなかったかを返す

## 参照するファイル

- 細かい規約とコード例は [reference.md](reference.md) を読む
- エラーコードの一覧は `${CLAUDE_SKILL_DIR}/scripts/list_error_codes.sh` で出せる
  • paths はカンマ区切りの文字列か、YAML のリストで書けます。
  • user-invocable: false にしたので / メニューには出ず、Claude だけが使う背景知識になります。

補助ファイルを含むディレクトリ構成

5 つの雛形を置いた .claude/skills/ の中身です。api-conventions だけ補助ファイルを持たせています。

.claude/skills/
├── api-conventions/
│   ├── SKILL.md              (必須。概要と、どのファイルを読むかの案内)
│   ├── reference.md          (細かい規約。必要な時だけ読まれる)
│   └── scripts/
│       └── list_error_codes.sh   (実行するスクリプト。読み込まれるのではなく実行される)
├── find-usages/
│   └── SKILL.md
├── new-component/
│   └── SKILL.md
├── pr-checklist/
│   └── SKILL.md
└── summarize-changes/
    └── SKILL.md

補助ファイルは、SKILL.md から「何が書いてあり、いつ読むか」を添えてリンクしておきます。同梱のスクリプトを確認なしで実行させたい場合は、本文と allowed-tools の両方で同じ変数を使います。

---
name: render-chart
description: CSV ファイルからグラフを描く
allowed-tools: Bash(${CLAUDE_SKILL_DIR}/scripts/render.sh *)
---

`${CLAUDE_SKILL_DIR}/scripts/render.sh <csvファイル>` を実行してグラフを描く。

frontmatter 全 20 項目の一覧

フィールド名は、when_to_use だけがアンダースコア、ほかはハイフン区切りです。名前が 1 文字でも違うと、エラーにならずに読み飛ばされます。

フィールド 型 既定値 使いどころ
name 文字列 フォルダ名 / メニューに出すコマンド名を変えたい時
description 文字列 本文の最初の行 何をするスキルか、いつ使うか。Claude が読み込むかどうかの判断材料
when_to_use 文字列 なし きっかけになる言い回しや依頼の例を足す
argument-hint 文字列 なし 補完時に出す引数のヒント。例:[issue-number]
arguments 文字列 / リスト なし 名前付き引数。空白区切りかリストで、位置の順に対応する
disable-model-invocation 真偽値 false true で Claude が自動では読み込まなくなる。自分で /名前 と呼ぶ作業向け
user-invocable 真偽値 true false で / メニューから隠す。Claude だけが使う背景知識向け
allowed-tools 文字列 / リスト なし スキルを呼んだターンの間、確認なしで使えるツール
disallowed-tools 文字列 / リスト なし スキルが有効な間、使えなくするツール
model 文字列 セッションのモデル このスキルの間だけ使うモデル。/model と同じ値か inherit
effort 文字列 セッションの設定 low・medium・high・xhigh・max(使える値はモデルによる)
context 文字列 なし fork でサブエージェントのコンテキストで動かす
agent 文字列 general-purpose context: fork のときに使うサブエージェントの種類
background 真偽値 true context: fork 専用。false で結果をそのターンで待つ
hooks マップ なし スキルを呼んだ時に登録し、セッションの終わりまで動かすフック
paths 文字列 / リスト なし glob パターン。合うファイルを扱う時だけ自動で読み込む
shell 文字列 bash !`コマンド` を動かすシェル。bash か powershell
metadata マップ なし 自分のツールが読むための自由なキーと値。Claude Code は中身を使わない
license 文字列 なし スキルのライセンス。受け付けるだけで動作には影響しない
compatibility 文字列(500 字まで) なし 想定する製品や前提条件。受け付けるだけで動作には影響しない

補足です。

  • 真偽値は true / false のほか、yes・no・on・off・1・0 も大文字小文字を問わず受け付けます(v2.1.218 以降)。
  • allowed-tools と disallowed-tools は、空白またはカンマ区切りの文字列か、YAML のリストで書きます。
  • allowed-tools は使えるツールを絞る項目ではありません。挙げたツールの確認を省くだけで、ほかのツールは普段の権限設定に従います。
  • model と allowed-tools の効果は、次のメッセージを送ると解除されます。スキルの本文は会話に残ります。
  • .claude/commands/ に置く従来のコマンドファイルでも同じ項目が使えます(name と paths を除く)。
  • claude.ai へのアップロードや Skills API で使えるのは、name・description・license・compatibility・metadata・allowed-tools の 6 つです。それ以外を含むと、アップロードやパッケージ化の段階でエラーになります。

置換変数 10 種

本文の中で、実行時の値に置き換わる書き方です。

変数 置き換わる内容
$ARGUMENTS 渡された引数の全体(入力したとおりの文字列)
$ARGUMENTS[N] N 番目の引数(0 始まり)。$ARGUMENTS[0] が 1 つ目
$N $ARGUMENTS[N] の短縮形。$0 が 1 つ目、$1 が 2 つ目
$名前 arguments に並べた名前付き引数
${CLAUDE_SESSION_ID} 現在のセッション ID
${CLAUDE_EFFORT} 現在の effort レベル(low〜max)
${CLAUDE_SKILL_DIR} その SKILL.md があるディレクトリ
${CLAUDE_PROJECT_DIR} プロジェクトのルート(v2.1.196 以降)
${CLAUDE_PLUGIN_ROOT} プラグインのインストール先(プラグインのスキルのみ)
${CLAUDE_PLUGIN_DATA} プラグインの永続データ用ディレクトリ(プラグインのスキルのみ)
  • 引数を渡したのに、本文に受け取る場所($ARGUMENTS・$0・名前付き引数)が 1 つもないときは、末尾に ARGUMENTS: <入力> が自動で足されます。
  • 対応する引数がない $2 などは、そのまま文字として残ります。名前付き引数は空文字になります。
  • 文章の中で $1.00 のように $ と数字を書きたいときは、\$1.00 とバックスラッシュを付けます。

置き場所 8 種と優先順位

置き場所 パス 読み込まれる範囲
組織(Enterprise) managed 設定のディレクトリ内 .claude/skills/<名前>/SKILL.md 組織が配布した端末の全利用者
個人 ~/.claude/skills/<名前>/SKILL.md 自分の全プロジェクト
プロジェクト .claude/skills/<名前>/SKILL.md そのリポジトリ
入れ子 <サブディレクトリ>/.claude/skills/<名前>/SKILL.md そのサブディレクトリ以下で始めたセッション
追加ディレクトリ --add-dir で渡したディレクトリの .claude/skills/ そのセッション
プラグイン <プラグイン>/skills/<名前>/SKILL.md プラグインが有効な場所。/プラグイン名:スキル名
claude.ai アカウント アカウントで有効にしたスキル Cowork・クラウド・そのアカウントでサインインしたセッション
コマンドファイル .claude/commands/<名前>.md 従来形式。今も動く

同じ名前が複数の場所にあるときの扱いです。

重なり方 動くほう
組織・個人・プロジェクトのうち 2 つ 組織 → 個人 → プロジェクトの順で先にあるもの
上の場所と、同梱スキルや組み込みコマンド 自分のスキル(別名は置き換わらない)
スキルと .claude/commands/ のファイル スキル
ルートのスキルと入れ子のスキル 両方読み込まれる。入れ子は /apps/web:deploy の形でも呼べる
プラグインのスキルと上の場所のスキル 両方読み込まれる(プラグイン側は名前空間つき)
  • モノレポでは、起動したディレクトリからリポジトリのルートまでの .claude/skills/ が読み込まれます。起動した場所より下にある .claude/skills/ は、Claude がそのサブディレクトリのファイルを読むか編集した時点で読み込まれます。
  • synced と anthropic-skills というフォルダ名は予約されています。
  • 設定ファイルの permissions.additionalDirectories に書いたディレクトリは、ファイルアクセスだけが広がり、そこのスキルは読み込まれません。

description の書き方:直す前と直した後を 5 組

description は、Claude が「いまこのスキルを使うか」を決める材料です。公式ドキュメントは、利用者が自然に口にする言葉を入れること、いちばん大事な用途を先頭に書くことを勧めています。使われすぎるときは、逆に範囲を具体的に絞ります。

直す前 直した後 変えた点
便利なツール CSV を読み込み、列ごとの件数・欠損・最大最小を表にまとめる。「CSV の中身を見て」「データの概要」と言われたときに使う。 何をするか、どんな言葉で頼まれるかを入れた
コードレビュー用 プルリクエストの差分をレビューし、バグの可能性・テストの不足・命名の不一致を指摘する。「レビューして」「差分を見て」に対応。 対象(差分)と出力(指摘の種類)を書いた
デプロイに関する各種の作業を行うためのスキルです。本番や検証など… 検証環境へデプロイする。テスト → ビルド → 配置 → 動作確認の順。 + disable-model-invocation: true 用途を先頭に。副作用のある作業は自分で呼ぶ形にした
API src/api 以下のエンドポイントを追加・変更するときの命名、エラー形式、入力検証の規約。 + paths 適用する場面を書き、対象ファイルを paths で絞った
文章を直す(何にでも反応する) docs/ 以下の Markdown の表記ゆれ(全角半角・用語)を直す。ソースコードのコメントには使わない。 使う範囲と使わない範囲を書いて絞った

書くときの目安です。

  • 「何をするか」+「いつ使うか」を 1〜2 文で書く。
  • 依頼の言い回しがいくつもあるときは、when_to_use に分けて書く。
  • description と when_to_use を合わせた文字数は、スキル一覧の中で 1,536 字までに切られます。大事な用途を先頭に置きます。
  • 値に「: 」(コロンと空白)を含めるときは、全体を引用符で囲みます。description: 使い方: PR 前に実行 という行は、PyYAML 6.0.3 では mapping values are not allowed here というエラーになりました。description: "使い方: PR 前に実行" と書けば、文字列として読めます。

disable-model-invocation と user-invocable の組み合わせ

書き方 自分が呼べる Claude が呼べる コンテキストに入るもの
(どちらも書かない) できる できる 説明文は常に入り、本文は呼ばれた時に入る
disable-model-invocation: true できる 自動ではしない 説明文は入らず、本文は呼ばれた時に入る
user-invocable: false できない できる 説明文は常に入り、本文は呼ばれた時に入る
向いている内容 書き方
コミット、デプロイ、通知の送信など、タイミングを自分で決めたい作業 disable-model-invocation: true
システムの背景説明や規約など、コマンドとして呼ぶ意味がない知識 user-invocable: false
調べ物や要約など、どちらから呼んでもよいもの どちらも書かない

user-invocable: false は自分が呼べなくなるだけで、Claude は引き続き使えます。Claude に使わせたくないスキルは disable-model-invocation: true にします。

SKILL.md を編集したくないスキル(共有リポジトリのものなど)は、設定ファイルの skillOverrides で見え方を変えられます。

{
  "skillOverrides": {
    "legacy-context": "name-only",
    "deploy": "off"
  }
}
値 Claude への一覧 / メニュー
"on" 名前と説明 出る
"name-only" 名前だけ 出る
"user-invocable-only" 出ない 出る
"off" 出ない 出ない

権限ルールでも制御できます。Skill(名前) は完全一致、Skill(名前 *) は引数つきの前方一致です。deny に Skill とだけ書くと、すべてのスキルが使えなくなります。

500 行以内の目安と分割の基準

公式ドキュメントは、SKILL.md を 500 行以内に保ち、詳しい資料は別ファイルに移すことを勧めています。理由は 2 つあります。

  • 読み込まれたスキルの本文は、その後のターンでも会話に残り続けます。1 行ごとに、毎ターンのトークンを使います。
  • 会話が要約(コンパクション)されると、スキルごとに先頭の 5,000 トークンだけが付け直されます(全スキル合計で 25,000 トークンまで)。後ろに書いた指示は残らないことがあります。
内容 置く場所
毎回必ず守る手順、禁止事項、出力の形式 SKILL.md の上のほう
場合によって参照する詳しい仕様、API の一覧 reference.md
入出力の例、良い例と直す前の例 examples.md
決まった処理(集計、変換、検査) scripts/ に置いて実行させる
実行時に変わる情報(差分、ブランチ、バージョン) !`コマンド` で埋め込む
毎回かならず実行したい検査 hooks(スキルの frontmatter か設定ファイル)

この記事の雛形 5 つの行数は次のとおりで、どれも 500 行を大きく下回っています。

$ wc -l .claude/skills/*/SKILL.md
  33 .claude/skills/api-conventions/SKILL.md
  24 .claude/skills/find-usages/SKILL.md
  28 .claude/skills/new-component/SKILL.md
  27 .claude/skills/pr-checklist/SKILL.md
  27 .claude/skills/summarize-changes/SKILL.md
 139 total

検査スクリプトと実行結果

claude plugin validate

Claude Code には、スキルのフォルダを点検するコマンドがあります(v2.1.233 以降)。雛形 5 つを置いたフォルダで実行した結果です。

$ claude plugin validate .claude/skills
Validating components in: /home/dev/shop-api/.claude/skills

√ Validation passed

わざと形を崩したスキルを 5 つ用意して実行すると、2 つが警告になりました。

$ claude plugin validate .claude/skills
Validating components in: /home/dev/bad/.claude/skills

Validating skill: /home/dev/bad/.claude/skills/no-desc/SKILL.md

‼ Found 1 warning:

  > description: No description in frontmatter. A description helps users and Claude understand when to use this skill.

Validating skill: /home/dev/bad/.claude/skills/blank-first/SKILL.md

‼ Found 1 warning:

  > frontmatter: No frontmatter block found. Add YAML frontmatter between --- delimiters at the top of the file to set description and other metadata.

√ Validation passed with warnings

--strict を付けると、警告もエラーとして扱われ、終了コードが 1 になります(CI 向け)。

× Validation failed (--strict treats warnings as errors)

標準ライブラリだけの検査スクリプト

上の実行では、フィールド名のつづり違いと 1,536 字を超える説明文を入れたスキルには警告が出ませんでした。そこを補う小さなスクリプトです。Python の標準ライブラリだけで動き、.claude/skills/*/SKILL.md を順に見ます。

"""SKILL.md の frontmatter を点検する(標準ライブラリのみ)

使い方: python3 check_skills.py .claude/skills
"""
import pathlib
import re
import sys

FIELDS = {
    "name", "description", "when_to_use", "argument-hint", "arguments",
    "disable-model-invocation", "user-invocable", "allowed-tools",
    "disallowed-tools", "model", "effort", "context", "agent", "background",
    "hooks", "paths", "shell", "metadata", "license", "compatibility",
}
BOOL_FIELDS = {"disable-model-invocation", "user-invocable", "background"}
BOOL_VALUES = {"true", "false", "yes", "no", "on", "off", "1", "0"}
LISTING_CAP = 1536   # description + when_to_use が一覧で切られる文字数
MAX_LINES = 500      # SKILL.md の行数の目安


def read_frontmatter(text):
    """先頭の --- から次の --- までを {キー: 文字列} にする。無ければ None。"""
    lines = text.split("\n")
    if not lines or lines[0].strip() != "---":
        return None
    fields, raw, key = {}, {}, None
    for line in lines[1:]:
        if line.strip() == "---":
            fields["__raw__"] = raw
            return fields
        m = re.match(r"^([A-Za-z_][\w-]*):\s*(.*)$", line)
        if m:                                   # トップレベルの「キー: 値」
            key = m.group(1)
            raw[key] = m.group(2).strip()
            fields[key] = raw[key].strip("\"'")
        elif key and line.strip():              # リストや折り返しの続き
            fields[key] = (fields[key] + " " + line.strip().lstrip("- ").strip("\"'")).strip()
    return None                                 # 閉じる --- が無い


def check(path):
    text = path.read_text(encoding="utf-8")
    fm = read_frontmatter(text)
    if fm is None:
        return ["frontmatter が読めない(1 行目が --- か、閉じる --- があるか)"]
    problems = []
    raw = fm.pop("__raw__")
    for key, value in raw.items():
        if value[:1] not in ("\"", "'") and re.search(r":\s|\s#", value):
            problems.append(f"{key} の値に「: 」や「 #」がある(引用符で囲む)")
    for key in fm:
        if key not in FIELDS:
            problems.append(f"知らないフィールド: {key}(読み飛ばされる)")
    if not fm.get("description"):
        problems.append("description が無い(本文の最初の行が代わりに使われる)")
    size = len(fm.get("description", "")) + len(fm.get("when_to_use", ""))
    if size > LISTING_CAP:
        problems.append(f"description + when_to_use が {size} 字({LISTING_CAP} 字で切られる)")
    for key in BOOL_FIELDS & fm.keys():
        if fm[key].lower() not in BOOL_VALUES:
            problems.append(f"{key} は真偽値で書く: {fm[key]}")
    if "context" in fm and fm["context"] != "fork":
        problems.append(f"context に書けるのは fork: {fm['context']}")
    if ("agent" in fm or "background" in fm) and fm.get("context") != "fork":
        problems.append("agent / background は context: fork と一緒に使う")
    if "shell" in fm and fm["shell"] not in ("bash", "powershell"):
        problems.append(f"shell は bash か powershell: {fm['shell']}")
    if len(fm.get("compatibility", "")) > 500:
        problems.append("compatibility は 500 字まで")
    n_lines = text.count("\n") + 1
    if n_lines > MAX_LINES:
        problems.append(f"{n_lines} 行ある({MAX_LINES} 行以内が目安。詳細は別ファイルへ)")
    return problems


root = pathlib.Path(sys.argv[1] if len(sys.argv) > 1 else ".claude/skills")
failed = 0
for skill_md in sorted(root.glob("*/SKILL.md")):
    problems = check(skill_md)
    failed += bool(problems)
    print(("NG  " if problems else "OK  ") + skill_md.parent.name)
    for p in problems:
        print("      - " + p)
print(f"{failed} 件に指摘あり" if failed else "すべて OK")
sys.exit(1 if failed else 0)

雛形 5 つに対して実行した結果です。

$ python3 check_skills.py .claude/skills
OK  api-conventions
OK  find-usages
OK  new-component
OK  pr-checklist
OK  summarize-changes
すべて OK
$ echo $?
0

形を崩した 5 つに対して実行した結果です。

$ python3 check_skills.py .claude/skills
NG  blank-first
      - frontmatter が読めない(1 行目が --- か、閉じる --- があるか)
NG  colon
      - description の値に「: 」や「 #」がある(引用符で囲む)
NG  long-desc
      - description + when_to_use が 1680 字(1536 字で切られる)
NG  no-desc
      - description が無い(本文の最初の行が代わりに使われる)
NG  typo
      - 知らないフィールド: disable_model_invocation(読み飛ばされる)
      - 知らないフィールド: allowed_tools(読み飛ばされる)
      - 知らないフィールド: when-to-use(読み飛ばされる)
5 件に指摘あり
$ echo $?
1

typo の中身は次のとおりです。ハイフンとアンダースコアが入れ替わっているだけですが、3 つとも読み飛ばされる書き方です。

---
name: typo
description: フィールド名のつづりが違う例。
disable_model_invocation: true
allowed_tools: Bash(git status *)
when-to-use: デプロイのとき
---

手順を書く。

このスクリプトは frontmatter を簡易的に読んでいるので、入れ子の深い hooks や metadata の中身までは見ていません。YAML として正しいかどうかまで確かめたいときは、PyYAML の yaml.safe_load を併用します。雛形 5 つの frontmatter は、PyYAML 6.0.3 でも読み込めることを確認しています。

発火しない時の確認表

症状 確認すること 対処
頼んでも使われない description に、依頼で使う言葉が入っているか 言い回しを description か when_to_use に足す
頼んでも使われない 「What skills are available?」と聞いて一覧に出るか 出なければ置き場所とフォルダ名を見直す
/名前 では動くが自動では使われない frontmatter が YAML として読めているか claude --debug で解析エラーを見る。claude plugin validate も使う
設定した項目が効かない フィールド名のつづり(ハイフンかアンダースコアか) 一覧表のとおりに直す。上の検査スクリプトで確認
frontmatter が丸ごと本文になる 1 行目が --- か 先頭の空行や文字を消す
/ メニューに出ない user-invocable: false や skillOverrides の "off" になっていないか 設定を戻す
自動では絶対に使われない disable-model-invocation: true になっていないか 自動でも使わせたいなら外す
サブディレクトリのスキルが出ない 起動した場所より下の .claude/skills/ か そのディレクトリのファイルを触るか、/add-dir で読み込む
新しく作ったフォルダが反映されない セッション開始後に .claude/skills/ を作ったか /reload-skills を実行する
スキルが多く、説明が切れている 一覧の文字数の枠(コンテキストの 1%)を超えていないか /doctor・/skill-doctor で確認し、使わないものを "name-only" や "off" にする
呼び出しが中止される !`コマンド` が 0 以外で終わっていないか、権限で止まっていないか 末尾に || true を付ける、allowed-tools に同じコマンドを書く
途中から従わなくなる 会話が要約されていないか もう一度スキルを呼ぶ。大事な指示を上に書く
毎回守らせたい決まりが抜ける 指示が「1 回だけ」の書き方になっていないか 「編集のたびにテストを実行する」のように書く。確実に動かしたい検査はフックにする
使われすぎる description が広すぎないか 範囲を具体的に絞る。必要なら disable-model-invocation: true

一覧に入る説明文の枠は、skillListingBudgetFraction(例:0.02 で 2%)や、1 件あたりの上限 skillListingMaxDescChars という設定キーで変えられます。

よくある質問

Q. フォルダ名と name はどちらがコマンド名になりますか? A. name を書けばそれが / メニューに出る名前になり、書かなければフォルダ名が使われます。name を書いた場合でも、フォルダ名で呼び出せます。

Q. allowed-tools に書いたツールしか使えなくなりますか? A. なりません。allowed-tools は挙げたツールの確認を省く項目で、ほかのツールは普段の権限設定のとおりに使えます。使わせたくないツールは disallowed-tools に書きます。

Q. スキルの中身は毎ターン読み直されますか? A. 読み直されません。呼ばれた時点の内容が 1 つのメッセージとして会話に入り、そのまま残ります。作業全体を通して守ってほしいことは、「1 回やること」ではなく「常に守ること」として書きます。

Q. チームで共有するにはどうしますか? A. リポジトリの .claude/skills/ に置いてコミットします。リポジトリのスキルに書かれた allowed-tools はフォルダの信頼の確認を待たずに有効になるので、取り込む前に内容を確認しておくと安心です。

まとめ

  • SKILL.md を入れたフォルダを .claude/skills/(共有)か ~/.claude/skills/(個人)に置くだけで作れる。
  • frontmatter は 20 項目あり、すべて省略できる。推奨は description。名前のつづりが違うと読み飛ばされる。
  • 引数は $ARGUMENTS・$0・名前付き、実行時の情報は !`コマンド` で受け取る。
  • 副作用のある作業は disable-model-invocation: true、背景知識は user-invocable: false。
  • context: fork は手順のあるスキル向け。本文だけで作業が完結するように書く。
  • description + when_to_use は 1,536 字まで、SKILL.md は 500 行以内が目安。大事な指示を上に書く。
  • 発火しない時は、説明文の言葉 → 一覧に出るか → frontmatter が読めているか の順に確認する。

参考・出典

確認日:2026年10月7日

  • Claude Code Docs: Skills — https://code.claude.com/docs/en/skills
  • Claude Code Docs: Settings reference(skillOverrides ほか) — https://code.claude.com/docs/en/settings-reference
  • Claude Code Docs: Configure permissions — https://code.claude.com/docs/en/permissions

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Claude Code Skillsの作り方|SKILL.md雛形と項目一覧」

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?