Claude Codeで設定できるプロンプトがどんどん複雑化してるので、自分の理解を整理しとく。ユーザー単位でもプロジェクト単位でも設定できるが、プロジェクト単位をあちこちでやるのは大変なので、ユーザー単位での設定をある程度進めたいなと思ってる。
CLAUD.md、rules、slash commands、skills、subagents、全部一緒じゃないですかー!という人も、それぞれの用途とコンテキストの扱いを理解すれば、使い分けの意義が見えてくると思う。
設定できるプロンプトと用途
プロンプトの肥大化と複雑化はコンテキストウィンドウの枯渇や重要情報の埋没などの様々な問題を生む。この問題を回避するためにプロンプトを用途に応じて様々に設定できるようになっている。
- CLAUDE.md (
~/.claude/CLAUDE.md)- 全プロジェクトに共通する設定
- rules (
~/.claude/rules/)- CLAUDE.mdの分割先。ディレクトリ構造を使って構造化できるのと、ファイルパスに応じたルールの適用を制御できる(e.g.,
paths: src/api/**/*.ts)
- CLAUDE.mdの分割先。ディレクトリ構造を使って構造化できるのと、ファイルパスに応じたルールの適用を制御できる(e.g.,
- slash commands (
~/.claude/commands/)- markdownファイルで定義する定型プロンプト。
/commandのようにユーザーが明示的に実行する簡潔な指示テンプレート
- markdownファイルで定義する定型プロンプト。
- skills (
~/.claude/skills/)SKILL.mdファイルとサポートファイルで構成される再利用可能な専門知識パッケージ。会話内容に基づきClaudeが自動判断して発動する
- subagents (
~/.claude/agents/)- 専門領域に特化したシステムプロンプト・ツール設定を持つ独立したAI。特定タスクに自動委譲または明示的に呼び出し可能
使い分け
Claude Code起動時に読むべき設定はCLAUDE.mdとrules
Claude Codeは起動時にCLAUDE.mdとrulesを全文読みむので、プロジェクトに依存せず使う情報はここに置く。
rulesに分割するメリットとしては、パス限定ルールを記述できる点と、ディレクトリ構造を利用してマークダウンよりも明示的に情報を階層化できる点かと思う。
~/.claude/rules/
├── frontend/
│ ├── react.md
│ └── styles.md
├── backend/
│ ├── api.md
│ └── database.md
└── general.mdCLAUDE.mdやrulesは全文を読む特性上、コンテキストを圧迫しやすい。コンテキスト消費をうまくおさえるには、プロンプトの詳細を必要になるまで伏せられるskills, slash commands, subagentsの活用を検討したほうがいい。
なお、パス限定ルールは、条件に一致するパスを操作するまでコンテキストを消費しないらしいが(Oikonさんによる検証)、「ユーザー設定」レベルで効果的に扱うのは難易度が高めだと思う。たとえば、tsファイル限定でフロントエンド用のルールをユーザーレベルで読み込ませると、CLIを作っているプロジェクトにフロントエンドのコンテキストが混入する。まずはskillsで様子見してもよさそうだ。もしファイルパスの一致で確実に読み込ませたい内容であればパス限定ルールが活躍するだろう。
ユーザーが判断したタイミングで読み込ませたい内容はslash commands
実験した限り、slash commandsを削除しても/contextに表示されるコンテキストの消費量は変わらなかった。つまり、slash commandsは呼び出すまでコンテキストを消費しない。
コンテキスト消費の特徴と、ユーザーが明示的に実行する簡潔な指示テンプレートという目的をふまえると、ユーザーが判断したタイミングで読み込ませたい内容はslash commandsに書くべき言える。
たとえばgit commitする手順やルールは /git:commit のようにslashコマンドを呼ぶまで概要すら知らなくていいはずだ。
- 変更をすべてコミットせずに、意味のある範囲でできるだけ小さくコミットしてね
- commit logにはwhyを残してね
といった情報は実際にコミットを始めるまで知らなくていい。
逆に「ユーザーの利用言語を問わず日本語で返事すること」みたいな全体に影響するルールはCLAUDE.mdに書いておくべきだ。
Claude Codeが自動判断して読み込む内容はskillsかsubagents
slash commandsはコンテキスト消費を限界まで遅延できる一方で、Claude Codeが自動呼び出ししない欠点がある。
それを補うのがskillsやsubagentsだ。 Claude Codeはskillsやsubagentsの全体ではなくdescription(概要)だけをあらかじめ読む。概要から必要性を判断して全体を読む流れをとることで、コンテキスト消費をぎりぎりまで最小にしつつ、複雑な機能を発揮できる。
じゃあskillsとsubagentsはどう使いわけるのとなるが、ここでまたコンテキストの使い方に注目したい。
コンテキストを独立させたいならsubagents
Claude Codeがサブエージェントの専門分野に一致するタスクに遭遇すると、そのタスクを特化したサブエージェントに委譲でき、サブエージェントは独立して動作し、結果を返します。 https://code.claude.com/docs/ja/sub-agents
とあるように、サブエージェントはclaude codeの中でclaude codeを呼ぶようなものだ。サブエージェントは独立したコンテキストを持つので、タスクが巨大な場合や、親側が結果を概要レベルで知っていればよい場合に向いている。
試行錯誤を伴うエラーの原因調査は最たるものだろう。人間でも試行錯誤をしすぎると、あれってなんだっけ……?となるがサブエージェントに独立させれば、結果だけを受け取って情報整理できる。
見方を変えれば、特定条件で反映したいCLAUDE.mdとも言えそうだ。
コンテキストを共有したいならskills
たとえばClaude Codeにテスト駆動開発させるとしよう。
Claude Codeに必ずテスト駆動開発させるわけではないので、高度な知識をCLAUDE.mdやrulesに書いておくのはコンテキストの無駄遣いだ。
かといって、サブエージェントに独立させると、親側のコンテキストを十分に渡せなかったり、RED-GREEN-REFACTORのサイクルごとにコンテキストが分断され、開発の経緯を共有しきずに状況を見失うおそれがある。
Skillsなら、「計画を元にTDDして」みたいな具合に、コンテキストを完全に引き継いで複雑なタスクを実行させられるわけだ。
skillsとsubagentsの明示的呼び出しについて
「Claude Codeが自動判断して読み込む内容はskillsかsubagents」と書いたが、subagentsについては
コマンドでサブエージェントに言及して、特定のサブエージェントをリクエストします
とあるように、ユーザーが明示的に呼び出すこともできる。「test-runnerサブエージェントを起動して」みたいに指示すればいいらしい。
更に明示的にしたければ、 @test-runnerといった記法もある。
Skillsも基本的には「commitスキルを使って」みたいな指示で呼び出せると思うが、@を使うような記法はない。
それもそのはず、明示的に呼び出したいならそれは技能ではなく指示なので、slash commandsを使うべきだからだ。
自動でも手動でも使いたい場合は、slash commandsに具体的な指示を書き、slash commandを呼び出すskillを書けばいい。
---
name: git-commit
description: Stage meaningful diffs and create Conventional Commits with WHY-focused messages. Use when agent needs to commit code changes.
---
Execute `/git:commit` slash command`設定の肥大化と戦う
使い分け方法を見ていくと、肥大化した各種設定をどうリファクタすべきかも見えてくる。
重複の排除
同じ内容が複数の場所に書かれていたら、一箇所にまとめて参照する形にする。
- slash commandとskillで重複 → skillからslash commandを呼び出す形に統一
- 複数のsubagentsで共通のルール → 常に必要ならCLAUDE.mdへ、特定条件で必要ならskillsとして切り出す
読み込みタイミングの最適化
CLAUDE.mdやrulesに書いてあるが、常に必要ではない内容は移動を検討する。
- 特定タスクでしか使わない詳細な手順 → slash commandsへ
- 自動判断で発動させたい専門知識 → skillsへ
- 独立したコンテキストで処理させたいタスク → subagentsへ
ENJOY!
CLAUD.md、rules、skills、slash commands、subagents、全部一緒じゃないですかー!と思っていた頃もあったが、なんとなく脳内に描いていた使い分けを言語化できた。
うまく使うと、コンテキスト管理の上手なClaude Codeができあがりそうなので、リファクタ用slash commandでも作ってみようと思う。
Atusy's blog