🐈

脱・ファット・CLAUDE.md

に公開

夏なのでCLAUDE.mdのダイエット方法についてまとめました。

CLAUDE.mdとは何か

CLAUDE.mdとは、Claude Codeのメモリ機能です。大きく分けてユーザーメモリプロジェクトメモリがあります。

  • ユーザーメモリは、個人用のCLAUDE.mdで、~/.claude/CLAUDE.mdに設置します。
  • プロジェクトメモリは、プロジェクト共有で使用するCLAUDE.mdで、プロジェクトのルート./CLAUDE.mdに設置します。

繰り返し使用したいプロンプトをこれらにまとめておくことで、Claude Codeの振る舞いをいい感じにできます。反面、やみくもに追加していくとついつい肥大化しがちなファイルでもあります。

なぜCLAUDE.mdを薄くしたいのか

LLMの出力品質はコンテキストに大きく依存します。コンテキストが不十分・不適切だと、ハルシネーションが発生しやすくなると言われています。目的のタスクに対し、不要なプロンプトが含まれていると成功率が下がります。このことについて、「LLMのプロンプトエンジニアリング」[1]では、「物語に関係しない要素は、そもそも登場させるべきではない」というチェーホフの銃に例えて説明されています。

意味のある文章のスニペット(断片)を取得できれば、それは素晴らしいコンテキストとなりますが、無関係な情報を取得してしまうと、他のより有用なコンテキストが埋もれてしまう可能性があります。さらに悪いことに、そのような情報によってモデルが誤った方向に導かれる可能性があります。最悪の場合、モデルは与えられた情報を必ず活用しようとする傾向があるため、完全に無関係なコンテキストまでも深読みしてしまうかもしれません。私たちはこれを「チェーホフの銃の誤謬」と呼んでいます。
「LLMのプロンプトエンジニアリング」p.103

一方で、CLAUDE.mdは起動時にそのすべてが読み込まれるという特性があります。[2]
そのため、再利用したいあらゆるプロンプトをすべてCLAUDE.mdに記述してしまうと都度関係のないプロンプトまで読み込まれることになります。
 LLM利用にあたり目的のタスクを遂行するためには、必要な情報を、過不足なくモデルに読み込ませることが重要です。これらの技術は、近頃ではコンテキスト・エンジニアリング[3]として注目を集めています。なんでも突っ込んでいくうちにファットになってしまったCLAUDE.mdを薄くしたいという動機がここにあります。
 Claude Codeには、状況に応じて適切にプロンプトを読み込ませる機能が複数提供されています。

  • ユーザーメモリ / プロジェクトメモリ
  • カスタムスラッシュコマンド
  • サブエージェント

すべてをCLAUDE.mdに寄せるのではなく、内容に応じてプロンプトを分散していくことでCLAUDE.mdの肥大化を避けることができます。
反面、多機能過ぎてどこに何を書いたらいいか混乱しがちです。以降は、これら機能をどのように使い分けるべきかについて考えていきます。

CLAUDE.mdの読み込みルール

そもそもClaude CodeはどのようなルールでCLAUDE.mdを読み込んでいるのかを見ていきましょう。

ユーザーメモリ

ユーザーメモリに記述したプロンプトは常にコンテキストに読み込まれ、すべてのセッションで利用されます。個人で管理するため気軽に追加しやすいのがユーザーメモリの特徴ですが、すべてのプロンプトをここに集約してしまうとタスクと関係ないものまで読み込まれる可能性が高くなります。
そのため、ユーザーメモリは最低限の記述にとどめ、プロジェクト固有のプロンプトはプロジェクトメモリに移植していくのが基本戦略になります。

~/.claude/CLAUDE.md
<!-- ユーザーメモリにはすべてのセッションに適用したいプロンプトを記述する -->
## Communication style
ずんだもん口調で

<!-- 以下はプロジェクトメモリに移行を検討 -->
## Frontend rules
<!-- backendに関するルール -->

## Backend rules
<!-- backendに関するルール -->

プロジェクトメモリ

プロジェクトメモリは、現在の作業ディレクトリにあるCLAUDE.mdをセッション起動時に読み込みます。
それに加え、次のルールに従って、関連する階層上のCLAUDE.mdを取得して読み込みます。[4]

  • 現在の作業ディレクトリからルートディレクトリ(自身は除く)に至るまでの間にあるCLAUDE.mdを再帰的に取得し、セッション起動時に読み込みます。
  • 現在の作業ディレクトリ内のサブツリーにあるCLAUDE.mdを、サブツリー内のファイルアクセス時に動的に取得し読み込みます。
/
├── CLAUDE.md # 起動時に読み込まれない
├── parent_dir
│   ├── CLAUDE.md # 起動時に読み込まれる
│   └── current_work_dir
│       ├── CLAUDE.md # 起動時に読み込まれる
│       ├── domain
│       │   ├── CLAUDE.md # domain配下のファイルアクセスに動的に読み込まれる
│       │   └── hoge.go
│       └── db
│           ├── CLAUDE.md # db配下のファイルアクセスに動的に読み込まれる
│           └── hoge.sql
└── parent_sibling_dir
    └── CLAUDE.md  # 読み込まれない

共通ルールは上位ディレクトリのCLAUDE.mdにまとめ、配下のディレクトリ毎にCLAUDE.mdを分散させることによって、タスク実行時に読み込むコンテキストを最小限におさえることができます。

./CLAUDE.md
<!-- プロジェクトメモリには、すべてのディレクトリに適用したいプロンプトを記述する -->
## Backend rules
### Project Structure
<!-- ディレクトリ構成 -->

<!-- 以下は各ディレクトリに移行を検討 -->
### Domain rules
<!-- ドメインに関するルール -->

### Database rules
<!-- データベースに関するルール -->

メモリ機能まとめ

ユーザーメモリ / プロジェクトメモリの読み込みルールをまとめると以下のようになります。

種類 配置場所 読み込みタイミング
ユーザーメモリ ~/.claude/CLAUDE.md 全てのセッション起動時
プロジェクトメモリ ./CLAUDE.md プロジェクト起動時
プロジェクトメモリ(祖先) プロジェクトからルートディレクトリまでの CLAUDE.md(/ 自身は除く) プロジェクト起動時
プロジェクトメモリ(サブツリー) ./**/CLAUDE.md サブツリー内ファイルアクセス時

これらルールを理解し、プロンプトを適切な箇所に分散することで、タスク実行時に読み込むコンテキストを実行タスクに必要なものだけに絞り込むことができます。
 CLAUDE.mdには、そのプロジェクト内で行われるどのようなタスクを実行する際にも参照される可能性がある基本的な情報を記述するのが最適です。一方で、Claude Code に与えたいコンテキストには、ワークフローと呼ばれるプロンプト群があります。ワークフロープロンプトは特定のタスクに強く結びついているため、CLAUDE.mdに記述すると、関係のないタスクにおいては無駄なコンテキストとなってしまいます。
このような特定タスクのためのプロンプトを定義するのに最適なのがカスタムスラッシュコマンドおよびサブエージェントです。

カスタムスラッシュコマンド

カスタムスラッシュコマンドは、頻繁に使用するプロンプトを、Markdownファイルとして定義し再利用するための機能です。CLAUDE.mdと同様にユーザースコープとプロジェクトスコープそれぞれで定義できます。個人的によく使うプロンプトを再利用したり、チーム全体の作業を標準化したりできます。[5]
定義したカスタムスラッシュコマンドは、Markdownファイル名をコマンド名として以下の形式で呼び出すことができます。

/<command-name> [arguments]

繰り返し使うワークフローはカスタムスラッシュコマンドにしておくことで、CLAUDE.mdをさらに薄くできます。

backend/CLAUDE.md
## Backend rules
### Project Structure

<!-- 以下は各ディレクトリに移行を検討 -->
### Add WEB API workflow
<!-- WEB APIの追加手順 -->

### Add DB table workflow
<!-- データベーステーブルの追加手順 -->

サブエージェント

サブエージェントは、Claude Code自身がセッションの途中でタスクを委任できる事前設定されたAIエージェントです。[6]
サブエージェント作成コマンド/agents に従って設定する他、./claude/agents/に直接Markdownファイルを作成することでも設定できます。

カスタムスラッシュコマンドとサブエージェントの使い分け

カスタムスラッシュコマンドとサブエージェントは、一連のタスクの再利用という似た機能を提供します。使い分けに関する明確な決まりは特にはありませんが、特性として以下のような違いがあります。

カスタムスラッシュコマンド サブエージェント
呼び出し方法 /から選択 @-から選択 or 自動委任
メインセッションのコンテキスト 消費する 消費しない
toolの個別許可
並列実行 不可

カスタムスラッシュコマンドは、実態はプロンプトの埋め込みであるため、メインセッションのコンテキストを消費します。一方サブエージェントはメインとは独立したコンテキストウィンドウを使用するため、コンテキストを消費しません。また、並列実行が可能です。どちらも明示的な呼び出しが可能で、カスタムスラッシュコマンドは/プレフィックス、サブエージェントは@-プレフィックスで呼び出すことができます。
 一見サブエージェントが上位互換のように思えますが、特定のタスクに特化を想定している・セッション途中でClaude Code自身から動的に呼び出されるなどの性質があるため、関心毎が横断的なタスクにはカスタムスラッシュコマンドの方がより適切といえそうです。
「コンポーネントを設計・実装する」「WEB APIを実装する」などの複雑な手順を含むワークフローはカスタムスラッシュコマンドで作成し、ワークフローの各ステップから呼び出されるような特定タスク(デバッグ、テスト、PR作成など)をサブエージェントとして定義するのがよいでしょう。

まとめ

すべてをCLAUDE.mdに記述するのではなく、適切に機能分散することで、コンテキストウィンドウの効率的な利用、タスクの成功率向上、チーム間での知識共有の標準化が期待できます。一方で過度な分散はプロンプトの管理コストを増加させる可能性があります。公式のベストプラクティスにもある通り[7]、トライアンドエラーを繰り返しながら少しずつチューニングしていくのがよいでしょう。


脚注
  1. https://amzn.asia/d/8cQjTrU ↩︎

  2. https://docs.anthropic.com/en/docs/claude-code/memory#determine-memory-type ↩︎

  3. https://arxiv.org/pdf/2507.13334 ↩︎

  4. https://docs.anthropic.com/en/docs/claude-code/memory#how-claude-looks-up-memories ↩︎

  5. https://docs.anthropic.com/en/docs/claude-code/slash-commands#custom-slash-commands ↩︎

  6. https://docs.anthropic.com/en/docs/claude-code/sub-agents ↩︎

  7. https://www.anthropic.com/engineering/claude-code-best-practices ↩︎

株式会社エスマット

Discussion