Claude CodeのAgent Skillsで独自ツールを作る完全ガイド【MCP不要】

2026年2月26日

「毎回同じプロンプトを書いている」「チームメンバーに同じ手順を教え続けている」——Claude Codeを使い込むほど、こういった非効率に気づきます。

SKILL.mdという1枚のMarkdownファイルを置くだけで、Claude Codeはそのファイルに書かれた手順・ドメイン知識・プロジェクト固有のルールを覚えます。これがAgent Skillsです。

MCPサーバーの構築・Node.jsのコード記述・デプロイは一切不要。ファイルを1枚書いてディレクトリに置くだけで、「/deployを実行して」という短い指示だけでClaude Codeが認証からスクリプト実行まで自動でやってくれます。この記事では、実際に動く3つのサンプルを通じて、Agent Skillsの作り方を体系的に解説します。

本記事のサンプルはすべて実際に動作確認済みです。


前提条件

このガイドを進める前に、以下の環境が必要です。

  • Claude Code: 最新バージョン(claude --versionで確認)

  • Node.js: 18.x 以上(Claude Code の実行環境)

  • 前提知識: Claude Codeの基本操作(コードを書かせたり質問したりできるレベル)

# Claude Code バージョン確認
claude --version
# 例: claude 1.x.x

なくてもOK: MCPの知識。Agent SkillsはMCPとは独立した機能です。


全体の流れ

このガイドは以下の構成で進みます。


Agent Skillsとは?

Agent Skillsは、Claude Codeに「このプロジェクト固有の手順」を覚えさせる仕組みです。

通常、Claude Codeに複雑な作業を依頼するときは毎回プロンプトで詳細な手順を説明する必要があります。Agent Skillsを使うと、その手順をSKILL.mdというファイルに書いておくだけで、次回から「/search-consoleを実行して」という短い指示だけで同じことができます。

なぜAgent Skillsが必要か

Claude Codeを業務で使い始めると、こんな場面に出くわします。

  • 「毎回同じプロンプトを書くのが面倒」

  • 「チームメンバーが同じ手順でClaude Codeを使えるようにしたい」

  • 「プロジェクト固有のAPIや設定を毎回説明するのが辛い」

Agent Skillsはこういった問題を解決するために作られた機能です。SKILL.mdにプロセス・API仕様・認証情報の参照方法などを書いておけば、Claude Codeがそれを読んで適切に動いてくれます。

git-commit / update-post / notion-tasks の各SKILL.mdがClaude Code AIインターフェースに連携する構成図


SKILL.mdの書き方・配置場所

配置場所

SKILL.md.claude/skills/ ディレクトリ以下に置きます。

プロジェクトルート/
└── .claude/
    └── skills/
        ├── search-console/
        │   └── SKILL.md
        ├── deploy/
        │   ├── SKILL.md
        │   └── deploy.sh   ← スキルが使うスクリプト
        └── git-commit/
            └── SKILL.md

スキルごとにサブディレクトリを作り、その中にSKILL.mdを置きます。関連スクリプトや設定ファイルも同じディレクトリに置いておくと管理しやすいです。

基本フォーマット

---
name: スキル名
description: いつ使うかの説明(Claudeがスキルを選択する判断基準になる)
---

# スキルのタイトル

## 概要
このスキルが何をするかの説明

## 実行方法
具体的な手順をMarkdownで記述する

## 認証情報
必要な環境変数の参照方法

## 注意事項
ハマりやすいポイント

重要なのは フロントマターのdescription です。Claude Codeはこの説明文を読んで「このスキルを使うべき状況かどうか」を判断します。「〜するとき」「〜を確認したいとき」という形式で書くと認識精度が上がります。

スキルの呼び出し方

スキルを呼び出すには、チャットで /スキル名 と入力します。

/search-console    ← Search Consoleデータを取得
/deploy            ← デプロイを実行
/git-commit        ← コミットメッセージを自動生成

または自然な日本語でも呼び出せます。「Search Consoleのデータを取得して」と言えば、Claude Codeが関連するスキルを自動で読み込んで実行します。


ハンズオン3種

ハンズオン①:Git コミットメッセージ生成スキル(初級)

まず最もシンプルな例から始めましょう。git diffの内容を読んで、日本語のConventional Commitsメッセージを自動生成するスキルです。

SKILL.mdの全文

---
name: git-commit
description: Gitの変更差分を読んでコミットメッセージを生成するとき。
             変更内容を日本語Conventional Commits形式でまとめたいとき。
---

# Gitコミットメッセージ自動生成

## 概要

`git diff`の差分を読んで、日本語のConventional Commitsメッセージを生成するスキル。

## 手順

1. `git status` と `git diff HEAD` を実行して変更内容を確認する
2. 変更の種類と内容を把握する
3. 以下の形式でコミットメッセージを生成する

## コミットメッセージのフォーマット

```
<type>: <要約(50文字以内)>

<本文(任意): 変更の理由・詳細を記述>
```

### typeの選び方

| type | 用途 |
|------|------|
| feat | 新機能追加 |
| fix | バグ修正 |
| docs | ドキュメントのみの変更 |
| refactor | 機能変更を伴わないリファクタ |
| chore | ビルド・CI・設定ファイルの変更 |

## ルール

- 要約は50文字以内
- 命令形ではなく体言止めで書く(例: 「〜を追加」「〜を修正」)
- 破壊的変更がある場合は本文に `BREAKING CHANGE:` を明記する

実際の使い方

# ファイルを変更・追加してステージングする
git add -A

# Claude Codeに依頼
# チャットで「/git-commit」または「コミットメッセージを作って」と入力

Claude Codeがgit diff --stagedを実行し、変更内容を読んで以下のようなメッセージを提案します。

feat: Search ConsoleのAPIレート制限対応を追加

- 429エラー時に自動リトライ(最大3回)
- リトライ間隔を指数バックオフで制御
- エラーログにリトライ回数を記録

git addしてClaude Codeに/git-commitと入力すると、右パネルにConventional Commitsメッセージが自動生成される様子

このスキルのポイント: わずか40行のMarkdownで、毎回「Conventional Commitsの仕様に従ってコミットメッセージを書いて、typeはfeat/fix/docs…」と説明する手間がゼロになります。


ハンズオン②:WordPress記事投稿スキル(中級)⭐ 実践例

これがAgent Skillsの真価を発揮するケースです。実際に運用しているスキルを元に解説します。

ユースケース

Markdownで書いた記事をWordPressに自動投稿するスキルです。単純なAPI呼び出しだけでなく:

  • アイキャッチ画像の設定方法

  • 下書き/公開の切り替え

といったプロジェクト固有のノウハウもSKILL.mdに含めています。

フォルダ構成

.claude/skills/update-post/
├── SKILL.md          ← 手順書
└── update_post.py    ← 実際のスクリプト

SKILL.mdの全文

---
name: update-post
description: Use when updating or publishing a WordPress post for gendosu.jp from a Markdown draft. Triggers when applying article rewrites, publishing edited content, or updating post body and title via REST API.
---

# WordPress 記事公開

## 概要

Markdown ドラフトを WordPress に公開するための完全な手順。
本文投稿・アイキャッチ生成・画像アップロードまでをすべて含む。

## 公開フロー

新規記事を公開する場合は以下の順で実行する。

### ステップ1: WordPress に下書き投稿して post_id を取得

```bash
bash -c 'set -a; source .env; set +a; curl -s -X POST \
  -u "$WP_USERNAME:$WP_APP_PASSWORD" \
  "$WP_SITE_URL/wp-json/wp/v2/posts" \
  -H "Content-Type: application/json" \
  -d "{\"title\": \"記事タイトル\", \"status\": \"draft\"}" \
  | python3 -c "import sys,json; p=json.load(sys.stdin); print(p[\"id\"])"'
```

### ステップ2: 本文を投稿

```bash
python3 .claude/skills/update-post/update_post.py <post_id> <draft_path> draft
```

### ステップ3: アイキャッチ画像を生成・設定(未設定の場合のみ)

既存記事のリライトや、すでにアイキャッチが設定済みの場合はスキップしてよい。
新規記事で未設定の場合のみ以下を実行する。

**生成:**

`.claude/skills/image-gen/SKILL.md` を参照して生成する。

```bash
python3 .claude/skills/image-gen/image_gen.py '<プロンプト>' <ファイル名>.png
```

プロンプトは記事の内容を反映した英語のビジュアル説明で書く。

**アップロード・設定:**

`.claude/skills/upload-image/SKILL.md` を参照してアップロードする。

```bash
python3 .claude/skills/upload-image/upload_media.py data/images/<ファイル名>.png <post_id>
```

### ステップ4: レビュー

下書き状態で記事を確認し、誤字・リンク・画像の表示を確認する。

### ステップ5: 公開

レビュー完了後に `publish` で再投稿する。

```bash
python3 .claude/skills/update-post/update_post.py <post_id> <draft_path> publish
```

---

## 既存記事のリライト時

既存記事を更新する場合はステップ2と5のみ実行する(アイキャッチは変更不要)。

```bash
python3 .claude/skills/update-post/update_post.py <post_id> <draft_path>
```

---

## update_post.py の引数

| 引数 | 説明 |
|------|------|
| `post_id` | WordPress の投稿 ID |
| `draft_path` | Markdown ファイルのパス |
| `status` | 投稿ステータス(省略時は `publish`)。`draft` / `publish` / `private` |

## Markdown ファイル形式

```markdown
---
keyword: "キーワード"
---

# 記事タイトル

本文を Markdown で記述する。
テーブル・コードブロックに対応。
```

- YAMLフロントマター(`---` で囲まれた部分)は自動でスキップされる
- 最初の `# ` 行がタイトルとして使用される(フロントマター後の空行も無視)
- 以降が本文(HTML に変換される)
- 投稿する Markdown は `templates/` ディレクトリのテンプレートに従って作成すること(`templates/README.md` 参照)

## 必要環境変数

`.env` に以下を設定済み:

| 変数名 | 説明 |
|--------|------|
| `WP_SITE_URL` | WordPress サイト URL |
| `WP_USERNAME` | WordPress ユーザー名 |
| `WP_APP_PASSWORD` | WordPress アプリケーションパスワード |

## 動作

- Markdown → HTML 変換(tables・fenced_code・attr_list 拡張対応)
- `## 見出し {#anchor}` → `見出し` に変換される(`{#...}` は出力されない)
- WordPress REST API `POST /wp-json/wp/v2/posts/{post_id}` を呼び出す

## 依存パッケージ

```bash
pip install markdown requests python-dotenv
```

スクリプト(update_post.py)の中身

#!/usr/bin/env python3
import os, markdown, requests, sys
from pathlib import Path
from dotenv import load_dotenv

load_dotenv(Path(__file__).parent.parent.parent.parent / ".env")

site_url = os.environ['WP_SITE_URL']
auth = (os.environ['WP_USERNAME'], os.environ['WP_APP_PASSWORD'])

post_id = sys.argv[1]
draft_path = Path(sys.argv[2])
status = sys.argv[3] if len(sys.argv) > 3 else 'publish'

md_text = draft_path.read_text()
lines = md_text.strip().split('\n')

# YAMLフロントマター(--- ... ---)をスキップ
start = 0
if lines[0].strip() == '---':
    try:
        end = lines.index('---', 1)
        start = end + 1
    except ValueError:
        pass

content_lines = lines[start:]

# 空行をスキップして最初の # タイトル行を探す
title_idx = 0
for i, line in enumerate(content_lines):
    if line.strip().startswith('#'):
        title_idx = i
        break

title = content_lines[title_idx].lstrip('# ').strip()
body_md = '\n'.join(content_lines[title_idx + 1:]).strip()

html_content = markdown.markdown(body_md, extensions=['tables', 'fenced_code', 'attr_list'])

print(f"タイトル: {title}")
print(f"ステータス: {status}")
print(f"HTML文字数: {len(html_content)}")

resp = requests.post(
    f'{site_url}/wp-json/wp/v2/posts/{post_id}',
    auth=auth,
    json={
        'title': title,
        'content': html_content,
        'status': status,
    }
)

if resp.status_code in (200, 201):
    p = resp.json()
    print(f"\n✅ 更新成功!")
    print(f"   タイトル: {p['title']['rendered']}")
    print(f"   ステータス: {p['status']}")
    print(f"   URL: {p['link']}")
    print(f"   更新日: {p['modified'][:10]}")
else:
    print(f"\n❌ エラー: {resp.status_code}")
    print(resp.text[:500])

実際の実行結果

タイトル: Docker buildxでマルチプラットフォームイメージを作る方法
ステータス: draft
HTML文字数: 18342

✅ 更新成功!
   タイトル: Docker buildxでマルチプラットフォームイメージを作る方法
   ステータス: draft
   URL: https://example.com/?p=123
   更新日: 2026-02-18

このスキルのポイント: SKILL.mdにプロジェクト固有の注意事項(.envの変数名、スクリプトのパス)が書いてあるので、Claude Codeが毎回正しい方法で実行してくれます。「WordPressに投稿して」という一言で、認証からMarkdown→HTML変換まですべて自動化されます。

SKILL.mdに手順・スクリプトを定義することで、Claude Codeが「/update-post」の一言から投稿完了まで自動実行する


ハンズオン③:マルチスキル連携(上級)

複数のスキルを組み合わせると、より高度な自動化ができます。SEOブログのデイリー実行ワークフローを例に解説します。

ワークフロー概要

① Notionからタスク取得 (/notion-tasks)
    ↓ 「自動実行可」かつ「未着手」のタスク一覧
② タスク種別で分岐
    ├── 【メタ更新】→ Search Consoleデータ取得 → 記事更新 (/update-post)
    └── 【インデックス確認】→ URL検査 (/url-inspect)
③ 結果をNotionに記録 + ステータス更新

このワークフローはcron/daily-execute.mdというファイルに定義されており、Claude Codeが毎日自動でこれを読んで実行します。

スキル間の連携パターン

スキル同士を連携させるときの書き方は2パターンあります。

パターンA:オーケストレーター型(推奨)

メインのワークフロー定義ファイル(今回のdaily-execute.mdがこれ)がスキルを呼び出す形式です。

# デイリー自動実行

## Step 1: タスク取得
.claude/skills/notion-tasks/SKILL.md を参照して、未着手タスクを取得する。

## Step 2: タスク実行
取得結果に応じて以下を呼び出す:
- 【メタ更新】→ update-post スキルを参照
- 【インデックス確認】→ url-inspect スキルを参照

## Step 3: 結果記録
Notion MCP で完了ステータスに更新する。

パターンB:スキル内参照型

スキルのSKILL.mdの中から別のスキルを参照する形式です。

# デプロイスキル

## 手順
1. テストを実行する(`.claude/skills/run-tests/SKILL.md` を参照)
2. テストが通ったら以下を実行:
   ```bash
   ./deploy.sh production
   ```
3. デプロイ後のヘルスチェックを行う

実際のNotionタスクスキル(SKILL.md抜粋)

---
name: notion-tasks
description: Notionのタスクを一覧・確認するとき。
             タスクのステータスをカテゴリや優先度でフィルタしたいとき。
---

# Notion タスク取得

## 実行方法

Notion MCP の `notion-query-database-view` を使ってクエリする:

```

view_url: view://xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

```

## 取得後の表示形式

カテゴリ順にグループ化して表示する:

| ID | タスク名 | 優先度 | ステータス |
|----|---------|--------|----------|
| N  | ...     | 🔴/🟡/🟢 | 未着手/進行中/完了 |

このスキルのポイント: Notionのビュー URLやフィルタ条件は毎回調べるのが面倒ですが、SKILL.mdに書いておけばClaude Codeが自動で正しいURLを使ってクエリします。「タスク一覧を見せて」の一言で使えます。

複数のSKILL.mdをオーケストレーターから呼び出すことで、各スキルが連携した自動化ワークフローが実現する


Agent Skills 実践Tips

Tip 1: descriptionは「いつ使うか」で書く

# ❌ 機能の説明になっている
description: Search Consoleのデータを取得するスキル

# ✅ 使うべき場面が明確
description: Search Consoleのデータを取得するとき。
             ページのCTR・順位・表示回数を確認したいとき。
             リライト前のベースライン計測が必要なとき。

descriptionはClaude Codeが「このスキルを今使うべきか」を判断するために使います。具体的なシナリオを複数書いておくと、適切なタイミングで自動的に呼び出されます。

Tip 2: ハマりポイントを必ず書く

実際の運用で発見したトラブルはSKILL.mdに記録しておきましょう。

## ⚠️ 注意事項

- `load_dotenv()` をheredoc実行時に引数なしで使うとクラッシュする
  → `load_dotenv(".env")` と明示的にパスを渡すこと
- `.env` の変数はBashのサブシェル内で展開すること
  → `bash -c 'set -a; source .env; ...'` パターンを使う

こういった細かいノウハウこそ、SKILL.mdに書く価値があります。次回同じ作業をするときに同じミスを繰り返さずに済みます。

Tip 3: スクリプトをスキルと同じディレクトリに置く

.claude/skills/search-console/
├── SKILL.md
├── search_console.py      ← スキルが使うスクリプト
└── README_for_debugging.md  ← デバッグ用メモ(任意)

スキルが依存するスクリプトをSKILL.mdと同じディレクトリに置くと、パスの管理が楽になります。スキルを別プロジェクトに移植するときも、ディレクトリごとコピーするだけで済みます。

Tip 4: プロジェクトごとに.claude/を分ける

Agent Skillsはプロジェクトルートの.claude/skills/から読み込まれます。プロジェクトAのスキルがプロジェクトBに影響することはありません。

ただし、~/.claude/skills/(ホームディレクトリ直下)に置いたスキルはすべてのプロジェクトで使えるグローバルスキルになります。「git-commit」のような汎用スキルはグローバルに、「notion-tasks」のようなプロジェクト固有スキルはローカルに置くのがおすすめです。

Tip 5: デバッグ方法

スキルが思い通りに動かないときの確認方法です。

# スキルが認識されているか確認
# Claude Codeで「利用可能なスキルを教えて」と入力

# SKILL.mdの内容をClaude Codeに直接読ませて確認
# 「.claude/skills/XXX/SKILL.mdを読んで、このスキルの使い方を教えて」

スキルが呼び出されない場合は、descriptionの書き方を見直してみてください。「〜するとき」という形式の具体的なシナリオが書かれているかどうかが重要です。


トラブルシュート

症状 原因 解決策
スキルが呼び出されない descriptionが曖昧 「〜するとき」の形式で具体的なシナリオを書く
SKILL.mdの内容が無視される ファイルが読み込まれていない .claude/skills/<スキル名>/SKILL.mdの配置を確認
スクリプトが見つからない パスが間違っている SKILL.md内のパスをプロジェクトルートからの相対パスで書く
環境変数が読み込まれない load_dotenv()の引数なし load_dotenv(".env")と明示的にパスを指定
毎回手順を忘れる SKILL.mdに書いていない ハマった手順は即SKILL.mdに追記する

まとめ

Agent Skillsは「Claude Codeを使いこなしている人の暗黙知」をチーム全体の資産に変える仕組みです。

このガイドで作成した3つのスキルを振り返ると、共通して言えることがあります。MCPのように外部サーバーを立てず、Pythonのコードを書かなくても、「何をする手順か」をMarkdownで書くだけでClaude Codeがその通りに動きます。

特に効果が大きいのは、「毎回説明しないといけないこと」を持っているチームです。.envの変数名、スクリプトのパス、APIの使い方——こういった情報は今まで誰かの頭の中か、Confluenceのどこか深いページに眠っていました。SKILL.mdに書くことで、Claude Codeが毎回正しい方法で実行します。

今日試すなら git-commit スキルが最速です。40行のMarkdownで作れて、翌日から毎回のコミット作業が変わります。


関連記事

未分類

Posted by GENDOSU