SKILL.mdとは?Claude Code Skillsの核心ファイル
Claude Codeの~/.claude/skills/ディレクトリに配置するSKILL.mdは、AIエージェントの振る舞いを定義するMarkdownファイルです。このファイルの設計次第で、Claude Codeの使い勝手とコスト効率が大きく変わります。
この記事で解決する課題:
- SKILL.mdが肥大化してcontext tokenを消費する
- Claude Code Skillsの作り方がわからない
- ベストプラクティスに沿った設計方法を知りたい
「Claude Codeにスキル作らせたら、SKILL.mdが300行超えた...」
AIに任せると便利だけど、気づけばSKILL.mdが肥大化して、context tokenを食い尽くす。そんな経験、ありませんか?
Claude Code公式ドキュメントでは「SKILL.mdは500行以下に保つ」「スクリプトはcontext消費なしで実行できる」というベストプラクティスが示されています。本記事では、この原則をブログ自動公開システムという具体的なユースケースに適用し、87%のSKILL.md削減を達成した実践例を共有します。
この記事で学べること
- Claude Code Skillsの肥大化が起きる理由
- 「決定論的」vs「非決定論的」処理の見分け方
- SKILL.mdを最小化するスクリプト分離パターン
- 完全動作するスクリプト実装例
- 実際に遭遇した落とし穴と対処法
前提条件
- Claude Codeを使ったことがある
~/.claude/skills/の基本的な構造を理解している- シェルスクリプトの基礎知識
💡 公式リファレンス
Agent Skills - Claude Code Docs
- Skillsの作り方と設計原則
Claude Code Best Practices
- Anthropic公式のベストプラクティス
なぜSKILL.mdは肥大化するのか
AIは「親切」すぎる
Claude CodeにSkillを作らせると、こんなことが起きます:
# SKILL.md(肥大化例)
## Usage
...(30行)
## Workflow
1. まず〇〇を確認します
2. 次に△△を判定します
3. もし□□の場合は...
4. そうでなければ...
...(100行続く)
## Examples
...(50行)
## Troubleshooting
...(30行)
親切心からすべての分岐とエッジケースを自然言語で記述しようとする。結果、読み込むだけでcontextの10%が消費される...なんてことも(コーヒー1杯分のコストが毎回飛んでいく)。
本当の問題は「再解釈コスト」
SKILL.mdに書かれた自然言語の手順は、毎回AIが解釈し直す必要があります。
「次の公開日を計算する」
↓ AIが解釈
「今日の日付を取得して、曜日を判定して、
火曜か木曜なら次のその曜日を...」
↓ 再解釈のたびにトークン消費
これが決定論的な処理(入力が同じなら出力も同じ)であれば、スクリプトで一発解決です。
決定論的 vs 非決定論的処理
決定論的処理(スクリプト向き)
| 処理 | 特徴 | 例 |
|---|---|---|
| 日付計算 | 入力→出力が固定 | 次回公開日の算出 |
| ファイル存在チェック | Yes/No判定 | seedディレクトリの確認 |
| JSON生成 | テンプレート出力 | manifest.json作成 |
| 文字列変換 | ルールベース | slug生成、パス変換 |
これらはスクリプト化すべき。
非決定論的処理(AI向き)
| 処理 | 特徴 | 例 |
|---|---|---|
| 文章生成 | 創造性が必要 | ブログ記事本文 |
| 判断・選択 | 文脈依存 | カテゴリ推定、タグ提案 |
| 対話・確認 | ユーザー意図の理解 | 切り口の選択 |
これらはAIに任せる。
完全動作するスクリプト実装
ディレクトリ構成
.claude/skills/blog-publish/
├── SKILL.md # 最小限の呼び出し定義(42行)
└── scripts/
├── orchestrate.sh # メインエントリーポイント
├── detect_mode.sh # モード判定
└── get_next_date.sh # 日付計算
get_next_date.sh - 次回公開日の計算
「次の火曜または木曜」を計算する完全なスクリプト:
#!/bin/bash
# get_next_date.sh - 次の火曜or木曜を計算
# Usage: ./get_next_date.sh [base_date]
# Output: YYYY-MM-DD
set -euo pipefail
BASE_DATE="${1:-$(date +%Y-%m-%d)}"
# 曜日を取得(0=日, 1=月, ..., 6=土)
day_of_week=$(date -j -f "%Y-%m-%d" "$BASE_DATE" "+%w" 2>/dev/null || \
date -d "$BASE_DATE" "+%w")
# 次の火曜(2)または木曜(4)までの日数を計算
case $day_of_week in
0) days_to_tue=2; days_to_thu=4 ;; # 日曜
1) days_to_tue=1; days_to_thu=3 ;; # 月曜
2) days_to_tue=7; days_to_thu=2 ;; # 火曜 → 次は木曜
3) days_to_tue=6; days_to_thu=1 ;; # 水曜
4) days_to_tue=5; days_to_thu=7 ;; # 木曜 → 次は火曜
5) days_to_tue=4; days_to_thu=6 ;; # 金曜
6) days_to_tue=3; days_to_thu=5 ;; # 土曜
esac
# 早いほうを選択
if [[ $days_to_tue -le $days_to_thu ]]; then
days_to_add=$days_to_tue
else
days_to_add=$days_to_thu
fi
# 日付を計算(macOS/Linux両対応)
if date -v +1d > /dev/null 2>&1; then
# macOS
date -j -v +${days_to_add}d -f "%Y-%m-%d" "$BASE_DATE" "+%Y-%m-%d"
else
# Linux
date -d "$BASE_DATE + $days_to_add days" "+%Y-%m-%d"
fi
detect_mode.sh - ソース種別の判定
#!/bin/bash
# detect_mode.sh - 入力ソースの種別を判定
# Usage: ./detect_mode.sh <source>
# Output: repo | export | blog | unknown
set -euo pipefail
SOURCE="$1"
if [[ "$SOURCE" =~ ^https://github\.com/ ]]; then
echo "repo"
elif [[ "$SOURCE" =~ \.mdx$ ]]; then
echo "blog"
elif [[ "$SOURCE" =~ \.md$ ]]; then
echo "export"
else
echo "unknown"
fi
orchestrate.sh - メインエントリーポイント
#!/bin/bash
# orchestrate.sh - Skill初期化のオーケストレーター
# Usage: ./orchestrate.sh <source> [--date YYYY-MM-DD]
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
SOURCE="$1"
DATE_ARG=""
# 引数パース
shift
while [[ $# -gt 0 ]]; do
case "$1" in
--date) DATE_ARG="$2"; shift 2 ;;
*) shift ;;
esac
done
# 各処理を実行
MODE=$(bash "$SCRIPT_DIR/detect_mode.sh" "$SOURCE")
if [[ -n "$DATE_ARG" ]]; then
PUBLISH_DATE="$DATE_ARG"
else
PUBLISH_DATE=$(bash "$SCRIPT_DIR/get_next_date.sh")
fi
# seedディレクトリの確認
SEED_EXISTS=false
if [[ "$MODE" == "repo" ]]; then
# GitHubURLからowner/repoを抽出
REPO_PATH=$(echo "$SOURCE" | sed 's|https://github.com/||' | sed 's|\.git$||')
SEED_DIR="seed/${REPO_PATH//\//-}"
[[ -d "$SEED_DIR" ]] && SEED_EXISTS=true
fi
# JSON出力
jq -n \
--arg mode "$MODE" \
--arg source "$SOURCE" \
--arg publish_date "$PUBLISH_DATE" \
--argjson seed_exists "$SEED_EXISTS" \
'{
mode: $mode,
source: $source,
publish_date: $publish_date,
seed_exists: $seed_exists
}'
SKILL.md - 最小限の定義
# blog-publish
## Usage
`/blog-publish <source> [--date next|YYYY-MM-DD]`
## Init
`bash scripts/orchestrate.sh <source> [--date DATE]`
Returns: `{mode, source, publish_date, seed_exists}`
## Phase Execution
| Phase | Condition | Skill |
| --------- | ------------- | -------------------- |
| Seed | mode=repo | AskUser: reuse? |
| Blog | !--skip-blog | `seed-to-blog` |
| Thumbnail | !--skip-thumb | `generate-thumbnail` |
| SNS | !--skip-sns | `sns-announce` |
42行。 AIが知るべきは「何を呼び出すか」だけ。
スクリプト言語の選択
Bash vs Python vs Node.js
| 言語 | メリット | デメリット | 向いている処理 |
|---|---|---|---|
| Bash | 依存なし、軽量 | 複雑なロジックが辛い | ファイル操作、コマンド連携 |
| Python | 可読性高い、ライブラリ豊富 | 環境依存 | データ処理、API連携 |
| Node.js | JSON処理が得意 | node_modules問題 | Web API、非同期処理 |
私たちはBash + jqの組み合わせを採用しました。理由:
- 依存が少ない - jqさえあれば動く
- Claude Codeとの相性 - シェル実行が最もシンプル
- デバッグしやすい - 各スクリプトを単独テスト可能
実際に遭遇した落とし穴
落とし穴1: macOS/Linux互換性
最初のバージョンではdateコマンドの互換性を考慮していませんでした。
# ❌ macOSでしか動かない
date -v +1d
# ❌ Linuxでしか動かない
date -d "+1 day"
# ✅ 両対応
if date -v +1d > /dev/null 2>&1; then
date -v +${days}d -f "%Y-%m-%d" "$BASE" "+%Y-%m-%d"
else
date -d "$BASE + $days days" "+%Y-%m-%d"
fi
落とし穴2: JSON出力のエスケープ
タイトルに引用符が含まれているとJSONが壊れました。
# ❌ 引用符でJSONが壊れる
echo "{\"title\": \"$TITLE\"}"
# ✅ jqを使えば安全
jq -n --arg title "$TITLE" '{title: $title}'
落とし穴3: エラーハンドリング
set -eだけでは不十分でした。
# ❌ パイプの途中で失敗しても気づかない
cat file.txt | grep pattern | wc -l
# ✅ pipefailで全段階をチェック
set -euo pipefail
効果測定
Token消費量の比較
| 項目 | Before | After | 削減率 |
|---|---|---|---|
| SKILL.md サイズ | 312行 | 42行 | 87%削減 |
| 1回の実行コスト | ~8,000 tokens | ~1,200 tokens | 85%削減 |
| エラー発生率 | 月5回程度 | 月1回未満 | 80%減少 |
なぜエラーが減るのか
自然言語の曖昧さがなくなるから。
# Before(自然言語)
「次の火曜または木曜のうち、早いほうを選ぶ」
→ AIが「早いほう」を誤解釈する可能性
# After(スクリプト)
if [[$days_to_tue -le $days_to_thu]]; then
days_to_add=$days_to_tue
fi
→ 常に同じ結果
応用:他のSkillへの適用
同じパターンを他のSkillにも適用しています:
| Skill | スクリプト化した処理 | 効果 |
|---|---|---|
generate-thumbnail | 画像パス生成、存在チェック | 50%削減 |
sns-announce | ハッシュタグ生成、文字数計算 | 40%削減 |
cross-post-publish | 記事一覧取得、カテゴリフィルタ | 60%削減 |
まとめ
Claude Code Skillsを設計する際の原則:
- 決定論的処理はスクリプト化 - 日付計算、ファイル操作、JSON生成
- SKILL.mdは呼び出し定義のみ - 「何を」呼ぶかだけ記述
- AIには創造性が必要な部分を任せる - 文章生成、判断、対話
- OS互換性とエラーハンドリングを忘れずに -
set -euo pipefailと両OS対応
AIに「次の火曜を教えて」と毎回聞くのは、電卓を持ってるのにソロバンの達人を雇うようなもの。適材適所で行きましょう。



