はじめに
こんにちは、CTO室の伊藤です。
Claude Code の各機能に関する情報は様々な方々が発信してくださり、私も大いにお世話になっています。Claude Codeのアップデートの早さに感謝しながら、CLAUDE.mdやskills, agentsと自分なりのカスタマイズを日々試しています。(最近、~/.claudeのdotfilesだけでだいぶ草稼いでるのは内緒...)
ただ正直なところ場当たり的なカスタマイズになりつつあり、それぞれの機能や設定が「何のための設定なのか」「この設定は何を解決するのか」をあまり意識できていませんでした。複数の機能を組み合わせる上では、各機能の役割と設計上の判断基準を整理する必要があると思い、本記事ではその結果を共有できればと思います。
なお、私の場合ありがたいことに会社のお金でMAX プラン($200/月)を使っていて、トークン数の節約をあまり考えなくて良いが故のやり方も含みますのでご留意ください。
各種機能の全体像
Claude Code のカスタマイズ手段を、私は以下の 3 つの観点で整理しました。
- 何を知っているか— Claude に渡す知識と文脈
- どこまでやっていいか— Claude の行動の境界線
- どうやって進めるか— Claude の手順・手段・作業の委譲
| 機能 | 何を知っているか | どこまでやっていいか | どうやって進めるか |
|---|---|---|---|
| CLAUDE.md / rules | ◎ プロジェクトの記憶 | △ 「〜しないで」は指示できるが強制力なし | △ 「〜で進めて」は指示できるが強制力なし |
| settings.json / hooks | △ SessionStart でコンテキスト注入可 | ◎ deny/ask/allow で静的制御 + PreToolUse で動的ブロック | ○ PostToolUse で編集後に自動フォーマット等 |
| skills | ◎ 専門知識を必要時に注入 | △ allowed-tools でスキル実行中の使用ツールを指定 | ◎ 手順を定義 |
| agents | ○ 独自プロンプトでの専門文脈 | ◎ tools 制限で行動を限定 | ◎ 作業の委譲・並列実行 |
| MCP | ○ 外部サービスからデータ取得 | — | ○ 外部サービスへの操作 |
(◎ = 主目的 / ○ = その役割も担う / △ = 間接的に関わる / — = 基本的に無関係)
それぞれの観点についての設計を詳しく記載していきます。
何を知っているか
Claude Codeの登場当初は、CLAUDE.mdにコード規約やテストの方針等々すべてを書いていました。しかし、CLAUDE.md はセッション開始時に必ずフルロードされるため、書いた分だけ常にコンテキストを消費します。公式の Best Practices でもこう述べられています。
CLAUDE.md is loaded every session, so only include things that apply broadly. For domain knowledge or workflows that are only relevant sometimes, use skills instead.
つまり、CLAUDE.mdにはすべてのタスクに共通する最小限の情報のみを書き(不明点は憶測で実装せず質問してから進める等)、それ以外は必要な時にだけロードされる形に分離するべきです。 この「最初は概要だけを渡し、詳細は必要になった時点で初めて開示する」という段階的な情報設計は、公式ブログ「Equipping agents for the real world with Agent Skills」で Progressive Disclosure と呼ばれています。skills 内部の 3 段階モデル(skills の description → SKILL.md 本体 → reference.md 等の参照ファイル)として紹介されていますが、この考え方は CLAUDE.md や rules にもそのまま当てはまります。
Progressive Disclosure の考え方を踏まえ、各内容がコンテキストに入るタイミングは以下のように整理できます。
| いつコンテキストに入るか | |
|---|---|
| CLAUDE.md | 常時 |
| rules/*.md | 常時(paths で適用タイミングを制御) |
| skills の name + description | 常時(disable-model-invocation: true のスキルは 呼び出されるまで description もコンテキストに入らない) |
| SKILL.md 本体 | 必要時 — コマンドで明示的に呼び出し時 or 自動発動 |
| skills の参照ファイル | 必要時 — SKILL.md 内で参照された時 |
rules/*.md
TypeScript を書いているときに Python のルールは不要ですし、その逆も然りです。rules/ では言語ごと・関心ごとにルールファイルを分け、paths フロントマターで対象パスを指定することで、Claude が実際に考慮するルールを必要なものだけに絞れます。
# rules/typescript.md --- paths: - "**/*.ts" - "**/*.tsx" ---
ただし paths が制御するのはあくまで「Claude がいつ考慮するか」であり、コンテキストへのロード自体は防げないと考えられます。公式ドキュメントでは rules/*.md は "automatically loaded as project memory" と説明されつつ、"These conditional rules only apply when Claude is working with files matching the specified patterns" とも記載されています。「ロードはされるが適用されない」のか「マッチするまでロードされない」のかは明示されていませんが、私の環境で /context の出力を確認した限りでは、パス条件に関わらずコンテキストに含まれていました。コンテキストの消費量を減らすことが主目的なら、次に紹介する skills への分離が有効です。
SKILL.md
skillsに切り出すことによって、セッション開始時にロードされるのはskillsの name と descriptionだけになります。Claudeはどんなスキルがあるのかだけを把握し、必要だと判断した時もしくはユーザーが /skill-name で呼び出した時に、初めてSKILL.md の全文を読み込みます。数十個のスキルを CLAUDE.md に全部書いたら常時数千行がコンテキストに入ってしまいますが、スキルとして分離すれば 詳細は必要なときだけ コンテキストに入ります。
さらに、この同じ原則は SKILL.md の中にも適用できます。公式ドキュメントでは SKILL.md を 500 行以下に保つことが推奨されています。
Keep
SKILL.mdunder 500 lines. Move detailed reference material to separate files.
SKILL.md にも書ききれない詳細情報(Mermaid のダイアグラムパターン集や、スキルの frontmatter 仕様等)はskillsディレクトリ内の参照ファイルに分離します。SKILL.md の末尾に「詳細は references/best-practices.md を参照」と書くだけで、Claude Codeは必要なときだけ参照ファイルを開いてくれます。
skills/skill-creator/
├── SKILL.md # スキル作成の手順
└── references/
├── best-practices.md # ベストプラクティス集
└── frontmatter-spec.md # frontmatter の仕様書
つまり、CLAUDE.md → SKILL.md → 参照ファイル と段階的にロードしていく構造となっていて、どの段階でも「要約だけ渡して、詳細は必要になってから」という同じパターンが繰り返されています。
MCP
ここまで紹介した CLAUDE.mdやrules、skills は、いずれも事前に用意した「静的な知識」です。しかし、ライブラリのドキュメントや API の仕様は日々更新されるため、静的なファイルに書いた情報はすぐに古くなります。
MCP(Model Context Protocol)サーバーは、この問題を補完します。たとえば Context7 は、ライブラリ名を指定するだけで最新のドキュメントとコード例を取得してくれます。skills の参照ファイルに特定バージョンの API 仕様を書き込む代わりに、MCP 経由で常に最新の情報を引けるわけです。
何を解決したか
かつてCLAUDE.mdにすべてを書いていた頃、私は
- 指示が効かない: いわゆる Lost in the middle問題で、長大なコンテキストの中間部分が軽視される。
- コンテキストがすぐ埋まる: セッション開始時点で 40〜50% ほど消費されていて、タスクの途中で毎回
compacting conversationが走ってしまう。
Progressive Disclosure による分離で、これらの問題はかなり改善されました。実際に私の環境でコンテキスト使用量を確認できる /context コマンドを実行すると、設定関連の占有率はかつての半分程度(System tools10% + そのほか5%程度)に収まっています。
どこまでやっていいか
Claude Code にはいくつかの Permission Mode があり、代表的なものは以下の通りです。(他にも dontAsk 等のモードがあります)
| モード | 挙動 |
|---|---|
| default | ファイル編集もコマンド実行も、初回は都度確認を求める |
| acceptEdits | ファイルの読み書きは自動許可。Bash コマンドは確認を求める |
| plan | 分析と計画だけ行い、ファイル変更やコマンド実行はしない |
| bypassPermissions | すべての確認をスキップする(--dangerously-skip-permissions) |
defaultの場合、Claude Codeは何をするにも確認を求めてくるので、操作ミスのリスクは低いです。しかしそのぶん、作業のたびに Y/N を押す手間がかかります。実際の開発ではacceptEdits にして編集を自動許可することも多く、確認の手間を減らすためには権限制御の設計が重要になります。
権限制御には、性質の異なる2つの仕組みがあります。1つはツール呼び出し時の検査で、もう一つはskills や Subagents の tools 制限です。
呼び出し時検査のパイプライン
Claude Code が操作を実行するときは、以下の順で評価が走ります。
- hooks(PreToolUse): スクリプトでコマンドの中身を動的に検証
- Permission rules(deny → ask → allow): 静的パターンで判定。deny が最優先で絶対禁止、ask はユーザーに確認、allow は自動許可
Permission Mode: どのルールにもマッチしなかった操作に対して、現在のモード(defaultやacceptEdits)が適用される
Rules are evaluated in order: deny -> ask -> allow. The first matching rule wins, so deny rules always take precedence.
hooks
hooks はパイプラインの最初に位置し、ツール実行の直前にスクリプトを走らせ、コマンドの中身を見て判断する動的な仕組みです。settings.json の hooks キーで定義します。deny だとすり抜けやすいコマンドの変形パターン、例えば Bash(rm -rf /*) を deny したときの cd / && rm -rf * や変数展開、パイプ経由の削除等も hooks は対応しやすいです。さらに、hooks は deny にはできない外部の状態を参照した条件付き判断も可能です。たとえば「main ブランチにいるときだけファイル編集をブロックする」という判断は、コマンドのパターンだけでは表現できず、hooks でしか実現できません。
#!/usr/bin/env bash # branch-guard.sh — main ブランチでのファイル編集をブロック # Exit codes: 0=許可(JSON出力で詳細制御も可), 2=ブロック current_branch=$(git branch --show-current 2>/dev/null) if [[ "$current_branch" == "main" ]]; then echo "[Guard] main ブランチでの直接編集は禁止されています" >&2 exit 2 fi
なお、hooks は async: true を設定して非同期実行にすることもできます。今回のようなブロック判定が必要な PreToolUse は同期で実行する必要がありますが、PostToolUse で lint を走らせる場合や通知を行う場合は、結果を待つ必要はないので私の場合非同期にしています。
deny
hooks を通過したコマンドは、次にpermissions の静的ルールで評価されます。settings.json のdeny → ask → allow の順で評価され、最初にマッチしたルールが適用されます。
denyにマッチした操作は、ツールの呼び出し自体がシステムレベルでブロックされます。ここにはどんな状況でも実行してはいけない操作を入れます。ただし静的なパターンマッチなので、引数の順序違いや変数展開ですり抜ける可能性がある点は公式ドキュメントでも警告されています。こうした抜け道を hooks で補完する必要があります。
"deny": [ "Bash(rm -rf /*)", // 危険な削除 "Bash(git push --force *)", // 破壊的 Git 操作 "Read(.env)", // 秘密情報の読み取り ]
また、settings.json のルールはスコープごとに設定でき、優先順位は大きく Managed(組織) > Project > User の順です(厳密にはCLI引数やLocal Projectを含む5段階)。Managedによる組織のセキュリティポリシー で deny された操作は、Project や User レベルでallow しても通らないようになっています。
ask/allow
denyにマッチしなかった操作は、次にaskルールで評価されます。askにマッチした操作は、acceptEdits モードであっても実行前にユーザーに確認が求められます。askにもマッチしなかった操作は、最後にallowルールで評価され、マッチした場合はdefaultモードであっても常に自動許可となります。askには、コミットの実行やパッケージのインストールのような、普段から実行するが確認なしでは実行しないで欲しい操作を入れています。
"allow": [ "Read", // 読み取り系は自由に "Bash(git status)", // Git も読み取りは自由 ], "ask": [ "Bash(git commit *)", // コミットは都度確認 "Bash(pnpm add *)", // パッケージの追加も都度確認 ]
tools制御
ツールの検査とは別で、そもそも特定のツールを選択肢から外しておくというアプローチもあります。それが skills の allowed-tools と、Subagents の tools です。
# skills/workflow-research.md(読み取り専用スキルの例) --- name: workflow-research allowed-tools: Read, Glob, Grep, WebFetch, WebSearch, Task, mcp__context7__*, AskUserQuestion ---
これは私の調査用スキルですが、Edit / Writeのような書き込み系のツールを設定していません。意図としては、このスキル実行中にこれらのツールが選択肢から消えることで、調査中にうっかりファイルを変更する事故を抑制するものです。ただし、2026年2月時点ではskills の allowed-tools には許可の伝搬が正しく動作しないバグが報告されています。そのため、基本的にはこれだけに頼りすぎず hooks や deny/ask と併用するべきかと思います。
# agents/planner.md(読み取り専用エージェントの例) --- tools: - Read - Glob - Grep - mcp__sequential-thinking__* ---
こちらは Subagents の tools で制御していて、スキルの allowed-tools よりも安定してツール制限が効きます。読み取り系のツールだけを渡すことで、調査と実装の関心をツール権限レベルで分離しています。
何を解決したか
かつての私は Claude Code の操作を常に目視で監視していました。何をするか分からないという不安からacceptEditsにすることもためらい、毎回の確認ダイアログを一つずつ承認するを繰り返していました。
実際、勝手に意図せぬ操作が行われたことも何度かあります。
- プロジェクト外の別ファイルへのアクセス
- PRを勝手にマージ
- コンテナ内で実行して欲しいコマンドをローカルで実行
これらは、hooks や deny で仕組みとしてブロックできます。本当に危険な操作は仕組みとして止めてくれるという安心感があるからこそ、複数の Claude Code の並列操作のようなacceptEditsでの作業をかなり進めやすくなりました。
どうやって進めるか
最後に、Claude Code の「どうやって進めるか」を主に制御するskills と agentsについて、それぞれどう設計し組み合わせるかの考え方を紹介します。
スキルとエージェントの役割分担
前提として、skills と agents はどちらも Claude の振る舞いをカスタマイズする機能ですが、担う役割が異なります。
- skills = 「何を知り、何をするか」: 知識と手順の定義
- agents = 「どこで、どんな制約で実行するか」: 実行環境の分離と制約の定義
Skills add knowledge to the current conversation. Subagents run in a separate context with their own tools. Use Skills for guidance and standards; use subagents when you need isolation or different tool access.
スキルのコンテンツは Reference content(コーディング規約やドメイン知識などの背景知識)と Task content(PRの作成やコードレビューなどの実行手順)の2種類に分類されています。一方 agents は、ツール制限によって「何ができるか」の境界を、専門プロンプトによって「何をしないか」の制約を定義します。
この分離は、スキルの agent: フロントマターで表現できます。
# skills/security-review/SKILL.md --- name: security-review context: fork agent: security-reviewer allowed-tools: Read, Grep, Glob, Bash(rg:*), Bash(fd:*) --- # ここにレビュー手順(何を検査するか)を記述
例として挙げたsecurity-review スキルは「何を検査するか」(対象ファイルの特定、レポートフォーマット)を定義し、security-reviewer エージェントが「どんな能力と制約で検査するか」(読み取り専用、特定ツールのみ使用可)を担当します。同じエージェントを別のスキルから呼び出すこともできるため、能力・制約のセットを再利用できます。
逆方向の組み合わせも可能です。エージェント側の skills: フロントマターで、スキルをプリロードできます。
# agents/implementer.md --- name: implementer description: | Implementation specialist for executing planned changes. Use after planning phase is complete. Use for: code implementation, test creation, refactoring execution. memory: user tools: - Read - Write - Edit - Bash(npm run:*) - Bash(pnpm:*) skills: - commit-message - test-generation ---
implementer エージェントは commit-messageスキル と test-generationスキル をプリロードしているため、コミットメッセージの規約やテスト生成のパターンを「知っている」状態で作業できます。
つまり、agent: は能力と制約を持った専門家への作業の委譲、skills: はエージェントへの知識の注入です。どちらも「知識・手順」と「能力・制約」を分離して定義し、必要なときに組み合わせるという同じ思想に基づいています。
context: fork
スキルの context: fork は、メインの会話コンテキストから独立した Subagents でスキルを実行する設定です。会話履歴は引き継がれず、SKILL.mdの内容がそのままサブエージェントへのプロンプトになります。
fork するかどうかの判断基準は、「入力データだけで完結する分析タスクか、会話で決めた方針を引き継ぐ対話的タスクか」で考えています。セキュリティレビューを例に挙げると、この場合必要なのは対象コードだけで、「さっきユーザーと何を話していたか」は関係ありません。脆弱性レポートだけが親コンテキストに返ればいいので、 context: fork が適切です。私のエージェント定義でも、security-reviewerやgit-analyst, log-analyst などの分析系エージェントはすべて読み取り専用で、独立したコンテキストで実行を前提にしています。
一方で、リファクタリングの実行は「さっき決めた設計方針でここを直して」のように、会話の中で合意した判断を引き継ぐ必要があります。文脈を共有しながらファイルを変更するため、fork しないのが適切です。
加えて、前節で触れた Reference content と Task content の区別もこの判断に関わります。公式ドキュメントでは以下の警告があります。
context: forkonly makes sense for skills with explicit instructions. If your skill contains guidelines without a task, the subagent receives the guidelines but no actionable prompt, and returns without meaningful output.
コーディング規約やドメイン知識のような Reference content は、それ自体に実行すべきタスクを含まないため fork しても意味のある出力が返りません。fork が有効なのは、実行手順が明確に定義された Task content を持つスキルです。
スキルの呼び出し制御とコンポジション
スキルには disable-model-invocation と user-invocable という制御パラメータがあります。これらの組み合わせで、スキルの性質を分類できます。
| 型 | 設定 | 例 | 判断基準 |
|---|---|---|---|
| 自動発動型 | デフォルト | code-review, mermaid-generator | Claude Code が文脈から判断して呼び出してよい |
| 手動起動型 | disable-model-invocation: true |
smart-commit, gh-pr-create | 副作用がある。ユーザーが /skill-name で明示的に呼び出す |
| 背景知識型 | user-invocable: false |
commit-message, mcp-guidance | /メニューには表示されず、主に Claude Code が自動で読み込む |
disable-model-invocation: true に設定すると、Claude Code がそのスキルを自動的に発見・呼び出すことを防ぎ、さらに description もコンテキストに含まれなくなります。基本的に、コミットやプッシュなど副作用を伴う操作は、ユーザーが起動タイミングを制御すべきなのでこれを設定しています。
user-invocable: false は、公式ドキュメントでは「ユーザーがコマンドとして直接起動する意味のない背景知識」向けとされており、Claude Code が文脈から必要と判断したときに自動で読み込む使い方が想定されています。
何を解決したか
以前はすべてを1つのセッションで完結させようとした結果、途中で方針がブレたりコンテキストが溢れて前半の指示が失われたりすることが頻繁にありました。また、コミットメッセージの粒度やPRのフォーマットといったタスクの品質も毎回まちまちで、都度プロンプトで指示し直す手間がかかっていました。
skills と agents の設計で、これらの問題はかなり改善されました。コミットメッセージの規約やPRテンプレートをスキルとして定義したことで、スキルを呼び出すだけで毎回同じ品質のアウトプットが得られます。また、読み取り専用のエージェントに調査を委譲し context: fork でコンテキストを分離することで、メインセッションの方針がブレにくくなりました。頻繁に行うタスクを再利用可能なスキルとして切り出したことが、品質の安定と作業効率の両方に効いています。
まとめ
Claude Code のカスタマイズ手段は豊富で、本記事では挙げきれなかった機能も他に多くあります。(直近だとAgentTeamsとか...!)今回自分なりの観点で整理してみたことで、個々の機能への理解が深まっただけでなく、それらを設定の寄せ集めではなく組み合わさったシステムとして設計する意識が持てるようになりました。改めて公式ドキュメントを読み直す中で、普段情報を分かりやすく発信してくださる方々にも助けられていることを実感しています。
本記事が少しでも 私と同じく試行錯誤されているClaude Code ユーザーの方々の参考になれば幸いです。