← ブログに戻る

Claude Code Skills に入れると壊れる処理3種類と、分離先の選び方

この記事を含む総合ガイド Claude Code 実戦運用ガイド

harness-ops というリポジトリで、私は Claude Code Skills を23個運用しています。ブログ運用の PDCA、Zenn 記事の公開、Kindle 表紙生成、AI 文体チェック、書籍レビュー、Telegram 通知、といったあたりです。数を絞ってきた結果が23個で、多いときは30個を超えていました。

減らしたのは「無駄なものを消した」からだけではありません。それ以上に大きかったのは、 Skill に入れるべきでない処理を Skill から追い出した ことです。今日はその「入れると壊れる」型を3種類にまとめます。

先に断っておくと、この記事は「Skills を減らせ」の話ではありません。Skills / MCP / Hook / シェルスクリプトはそれぞれ役割が違うので、正しい引き出しに入れましょう、という境界線の話です。前に書いた「Claude Code Skills を10個書いたら、4個に統合された」は「消す」の話でしたが、今回はその続編で「移す」のほうです。

前提: 私が Skill に期待している役割

3種類のアンチパターンの前に、Skill に何を期待しているかを先に書いておきます。

Skill は要するにプロンプトテンプレートです。呼ばれたときに内容がコンテキストに展開され、Claude はそれを読んでタスクを解釈します。「同じ指示を毎回タイピングする代わりに、ファイルに固定して呼び出す」ためのものです。

一方、外部サービスにアクセスするのは MCP、特定イベントに反応して自動実行するのは Hook、決定論的な処理を回すのはシェルスクリプト。役割はここで分かれます。この4つを混同すると、Skill が肥大化してコンテキストを食い、しかも判断が遅くなります。Skill / MCP / Hook / Plugin の役割の詳細は、拙著『Claude Code Mastery』第11章にまとめてあります。

以下が、この整理を私が守れなかった3つの型です。

アンチパターン1: LLM 判断が不要な決定論的処理を Skill にする

最初にやらかしたのがこれです。

harness-ops には、私が「この記事は出さない」と判断したときの取り下げフローがあります。中身は、

  1. at 予約された投稿ジョブをキャンセル
  2. Google Calendar 上の公開予定イベントを削除
  3. NG ログを rejected.jsonl に追記
  4. Telegram で結果を通知

の4手順で、これを最初は harness-reject という Skill として書いていました。

3週間くらい使ってみて気づいたんですが、この4手順のうち LLM の判断が入る場所が1つもありません 。at ジョブ ID は引数で受け取る、カレンダーからの削除は summary の完全一致、ログ追記も定型 JSON、Telegram も定型テキストです。それなのに毎回 Skill 経由で呼ぶと、SKILL.md の中身がコンテキストに展開され、その分の脳のスペースが減ります。

結果、core/harness-reject.sh というシェルスクリプトに主要部分を寄せました。Skill 側からもシェルからも呼べる形で、判断が必要な「なぜ落としたか」だけを人間が引数で渡します。

境界線として私が今使っているのはこれです。

Skill にするのは「LLM が読み解く必要のある入力」か「LLM が生成する必要のある出力」を含む手順だけ 。両端が定型なら、それはシェルスクリプトです。

決定論的な処理を Skill に入れたときの症状は3つあります。

  • 起動のたびに数百〜数千トークンをコンテキストから引く
  • テキスト解釈のばらつきが混入して、稀に「Telegram に送らない」などのケースが出る
  • 実行時間が数秒 → 十数秒に伸びる (LLM のターンを1回消費するため)

3つ目が地味に痛くて、cron から呼ばれる処理は「1回1秒」で終わるかどうかが1日の余裕を決めます。Skill にした瞬間、その予算が壊れます。

アンチパターン2: 特定操作のあとに毎回走らせたい処理を Skill にする

次によくやったのが、「特定の操作が発生したら自動で走ってほしい処理」を Skill にしてしまうケースです。

具体例: .env の中身を誤って git に含めていないかチェックする、書き込みが発生したら該当ファイルを lint する、コミット前にテストを走らせる、あたりです。

これらは Skill にすると 「呼ばれて初めて動く」 ようになります。人間が「あ、このチェック Skill 呼ばなきゃ」と思い出したときだけ走ります。忘れたら走りません。しかも、こういうチェックは「忘れたとき」にこそ効きます。

Hook に移すと逆になります。Claude Code がファイルを Edit / Write するたび、コミットの前後、といった イベントのタイミング で自動的にトリガーされます。人間の記憶に依存しないので、忘れても走ります。

使い分けはこう決めています。

「毎回走ってほしい定型チェック」は Hook 、「頼まれたときに考えてほしい判断」は Skill

私の場合、.env チェックや lint、format 系は全部 Hook に寄せました。逆に「この PR のレビュー観点」「この記事の校正」といった、対象を見て考える必要があるものは Skill のままです。

Hook はコンテキストウィンドウを消費しないという別の利点もあります。Skill でチェックを実装すると「必ずこの手順で確認せよ」というプロンプトが毎回展開されますが、Hook はコンテキスト外で完結します。長い作業ほど効いてきます。

なお Hook の詳細な発火イベントについては「Claude Code Hooks v2 — 「お願い」を「プログラム」に変える25のイベント」に書いた通り、種類は思ったより多く、事前に一覧で見ておくと「これ Hook でいけるな」の判断が早くなります。

アンチパターン3: 外部サービスへの純アクセスを Skill にする

3つ目が地味に多かったパターンです。

「Google Calendar から今日の予定を取得する」「GA4 から昨日の PV を取得する」「Notion のあるページを読む」といった、 外部サービスへの読み書きそのもの の処理を、そのまま Skill として書いていました。SKILL.md の中に認証手順、エンドポイント、レスポンス形式、エラー処理まで書いていて、200行くらいある Skill もありました。

問題は3つ出ました。

  1. 認証周りが変わったときに Skill 側を手で追従しないといけない
  2. レスポンス形式が変わったときも同じ
  3. 200行の SKILL.md が呼ばれるたびにコンテキストを食う

MCP はまさにこの用途で用意された拡張点です。Google Calendar なら Calendar 用の MCP サーバー、Notion なら Notion 用の MCP サーバー、といった具合に、 サービス側にアダプターを持たせる 設計です。Claude Code は設定一つでそれを掴みにいけます。

MCP に寄せると、Skill 側は「呼ぶ」だけになります。SKILL.md には「Calendar から今日の予定を取得して、優先順位順に並べてください」と書けば済みます。認証もスキーマも MCP サーバー側の責務です。

住み分けはこうです。

外部サービスへの入出力そのものが目的なら MCP 、外部データを踏まえた判断や生成が目的なら Skill (中で MCP を呼ぶ)

MCP に寄せてから、私の Skill の平均行数は3分の1くらいになりました。外部サービス関連のコードが SKILL.md から消えたぶんです。

3種類まとめ

言葉で書くと分かりにくいので表にします。

症状分離先理由
決定論的な一連手順を Skill 化起動オーバーヘッド + 稀な解釈揺れシェルスクリプトLLM 判断が要らない
毎回自動で走らせたい定型処理を Skill 化呼び忘れると走らないHookイベントで自動起動できる
外部サービスへのアクセスを Skill 化SKILL.md 肥大 + 追従負担MCPサービス側にアダプターを持たせられる

私が今 Skill に入れる基準

3つ全部やってから決めた基準は1つです。

「入力を LLM に読ませて解釈させ、出力も LLM に生成させる」処理だけ Skill にする 。それ以外は Skill でない何かのほうが軽く済みます。

23個生き残った Skills を見返すと、全部この条件を満たしています。ブログ記事の校正、書籍の章立て提案、レビューコメントの生成、といった「読ませて考えて書かせる」タイプです。それ以外の「呼び出したら決まった順序で決まった処理をする」ものは、いつのまにか全部シェルスクリプトか Hook か MCP に引っ越していました。

Skill は便利な引き出しですが、なんでも突っ込む引き出しにすると、そのうち中身を探すコストのほうが Skill を使うメリットを上回ります。書く前に「これ、LLM 判断入る?」と1回だけ自問すると、後で引っ越すコストがだいぶ減ります。


Skills / MCP / Hook / Plugin の役割分担と、それぞれの設計判断の詳細は、拙著『Claude Code Mastery』第11章「マルチツール連携」にまとめています。

実践Claude Code 関連書籍 実践Claude Code 毎日 Claude Code を使うエンジニアへ — CLAUDE.md・Plan Mode・チーム展開の実践ガイド 書籍ページを見る →