CLAUDE.mdをきちんと整備するのはClaude Codeワークフローで最も費用対効果が高い投資の1つだ。同時に、タイポを直すだけのセッションも含めて毎回確実にトークンを消費する原因でもある。
この記事では上級テクニックを扱う。@import構文によるファイル合成、分割パターン、プロンプトキャッシュとの相性、最適化前後の実際のトークン数の計測方法だ。
「不要な説明を削る」「箇条書きにする」といった基礎はトークンバジェット最適化ガイドで扱っている。本記事はその続き。
ベースライン: CLAUDE.mdの実際のコストを計測する
最適化の前に計測する。Claude Codeは直接確認する方法を提供している。
# CLAUDE.mdのトークン数を確認
claude -p "CLAUDE.mdのトークン数を数えて教えてください"
# Pythonで直接計測する場合
python3 -c "
import anthropic
client = anthropic.Anthropic()
with open('CLAUDE.md') as f:
content = f.read()
result = client.messages.count_tokens(
model='claude-opus-4-5',
messages=[{'role': 'user', 'content': content}]
)
print(f'トークン数: {result.input_tokens}')
"
コンテキストの感覚を持つために: Claude Codeの200Kコンテキストウィンドウは広大に見えるが、複雑なコードベースでClaude Opusセッションを開くと、最初のプロンプトを入力する前にオープンファイル・gitログ・ターミナル出力等で40,000〜80,000トークンが消費される。CLAUDE.mdのトークンはその上に乗ってくる。
典型的な3,000トークンのCLAUDE.mdを月に100セッション使うと、毎月30万トークンのCLAUDE.md読み込みが発生する。その多くは、その内容の大半が必要ない軽いセッションだ。
@import: CLAUDE.mdを分割する正しい方法
@importディレクティブを使うと、CLAUDE.md読み込み時に追加ファイルを読み込むことができる。
# CLAUDE.md
@import .claude/context/architecture.md
@import .claude/context/commands.md
@import .claude/context/conventions.md
Claude は各インポートファイルを順番に読み、合成した内容を単一の指示セットとして扱う。重要な点: インポートファイルはセッション開始時にディスクから読まれるが、プロンプトキャッシュシステムでは独立してキャッシュされる(後述)。
ルートCLAUDE.mdに残すものと、分割ファイルに移すもの:
| ルートCLAUDE.md | インポートファイル |
|---|---|
| コア動作指示(短く、高インパクト) | アーキテクチャドキュメント |
| インポートディレクティブ | ドメイン固有の規約 |
| Claude Codeのhooksとパーミッション | 技術スタックの詳細 |
| セッション開始時の指示 | 参照テーブルとコード例 |
判断の目安: 「これがないとほぼ全タスクでClaudeが間違った動作をする」ならルートに残す。「特定のタスクやファイルにだけ関係する」ならインポートファイルの候補。
構成例:
project-root/
├── CLAUDE.md # 200〜400トークン(コアのみ)
└── .claude/
├── context/
│ ├── architecture.md # システム設計、ディレクトリ構造
│ ├── commands.md # ビルド・テスト・Lintコマンド
│ ├── conventions.md # 命名・スタイル・パターン
│ └── api-conventions.md # API固有ルール
└── CLAUDE.local.md # コミットしない、個人設定
2,800トークンのルートCLAUDE.mdを280トークンに削減し、詳細をインポートファイルに移動した実例がある。Claudeは同じ合計コンテンツを読み込むが、動作を制御するルートファイルが精鋭化される。
プロンプトキャッシュとの相性
ほとんどの最適化ガイドが省略する部分だ。Claudeのプロンプトキャッシュはコンテキストのプレフィックスを保存し、繰り返し呼び出しで再処理を避ける。CLAUDE.mdがセッション間で同一であれば(通常はそう)キャッシュにヒットし、フル処理の約10分の1のコストになる。
CLAUDE.mdに影響するキャッシュのルール:
プレフィックスが同一の時にキャッシュヒットする。 CLAUDE.mdがセッション間で変わると(タイムスタンプ1行でも、動的な内容でも)キャッシュが破れる。静的ファイルはキャッシュされる。動的コンテンツはキャッシュされない。
Claude Codeのデフォルトキャッシュ有効期間は5分。 連続セッションはキャッシュにヒットする。長い間隔を置いたセッションはコールドスタートになる。
インポートファイルは独立してキャッシュされる。 @importを使うと、各インポートファイルが別々のキャッシュエントリになる。commands.mdを変更してもarchitecture.mdはキャッシュにヒットする。これが分割ファイルアプローチのモノリシックCLAUDE.mdに対する大きなメリットだ。
キャッシュ動作を計測する:
response = client.messages.create(
model="claude-opus-4-5",
max_tokens=100,
system=[{
"type": "text",
"text": claude_md_content,
"cache_control": {"type": "ephemeral"}
}],
messages=[{"role": "user", "content": "主要な規約は?"}]
)
print(f"キャッシュ読み込みトークン: {response.usage.cache_read_input_tokens}")
print(f"キャッシュ書き込みトークン: {response.usage.cache_creation_input_tokens}")
total = response.usage.cache_read_input_tokens + response.usage.cache_creation_input_tokens
print(f"キャッシュヒット率: {response.usage.cache_read_input_tokens / total:.1%}")
3,000トークンのCLAUDE.mdの場合: コールドキャッシュでは全トークンコストを払う。ウォームキャッシュヒットでは約270トークン(キャッシュ読み込みレートで全コストの9%)。1日あたり100セッションで、CLAUDE.md読み込みのキャッシュヒットは桁違いのコスト削減になる。
ディレクトリスコープのCLAUDE.md: ディレクトリ分割のタイミング
Claude Codeはサブディレクトリのマウスに対応している。各サブディレクトリのCLAUDE.mdは、そのディレクトリで作業する際にルートCLAUDE.mdに加えて読み込まれる。
ディレクトリ分割が有効なケース:
- 異なる技術スタックを持つ複数アプリ/パッケージのモノレポ
/src/api/と/src/web/で規約が本質的に異なるプロジェクト- テスト固有のルールがあるテストディレクトリ
- コードスタイルが異なるスクリプト・ツールディレクトリ
コストが割に合わないケース:
- 規約の差異が軽微な単一アプリプロジェクト
- ルートCLAUDE.mdが既にタイトな小規模リポジトリ
- 追加コンテキストのロードコストが特異性のメリットを上回る場合
ディレクトリ分割の効果計測(典型的な3パート構成モノレポの例):
| アプローチ | ルート時の総トークン | /apiにいる時 | /webにいる時 |
|---|---|---|---|
| ルート1ファイル | 2,400 | 2,400 | 2,400 |
| ルート + ディレクトリファイル | 400(ルート) | 400 + 600 = 1,000 | 400 + 550 = 950 |
ディレクトリ分割により、特定ディレクトリ作業時に1,400トークンの節約。ただしディレクトリ横断のコンテキストが必要な場面では全て読み込む。
40%削減チェックリスト
実プロジェクトへの適用で、動作を維持したまま35〜45%のトークン削減が一貫して達成できる。
パス1: 説明・背景を削除(〜15%節約)
CLAUDE.mdの「〜だから」「〜のため」「〜するために」を全て探す。説明を削除するかコメントブロックに移す。AIモデルは指示に従って動作する——説明は指示の密度を薄めるだけだ。
修正前(38トークン):
外部データには`any`ではなく`unknown`を使うこと。`any`はTypeScriptの型チェックを
無効化し、デバッグが難しいランタイムエラーを引き起こすため。
修正後(12トークン):
外部データには`any`でなく`unknown`を使う。
パス2: リスト項目を圧縮(〜10%節約)
まとめられる箇条書きや冗長な記述を探す。
修正前(45トークン):
- `pnpm test`でテストスイートを実行する
- `pnpm lint`でコードスタイルをチェックする
- `pnpm build`でプロダクションビルドを行う
- `pnpm dev`で開発サーバーを起動する
修正後(25トークン):
コマンド: `pnpm dev`(開発)、`pnpm test`(テスト)、`pnpm lint`(Lint)、`pnpm build`(本番ビルド)
パス3: @importで外部化(〜20%節約)
アーキテクチャドキュメント、詳細なコード例、参照テーブルをインポートファイルに移す。ルートには要点だけを残す。
パス4: コード例を見直す(〜10%節約)
CLAUDE.mdのコード例はトークンを多く使う(コードはトークン密度が高い)。明白なコンセプトを示す例は削除。Claudeが例なしで一貫して間違えるパターンの例だけを残す。
パス5: 重複指示を統合する
同じコンセプトが複数回表現されていないか検索。最も明確な表現を1つ残して他を削除。
最適化の前後計測
各パスの前後でこれらの指標を追跡する。
# 最適化前のトークン数
python3 -c "
import anthropic, os, re
client = anthropic.Anthropic()
main_content = open('CLAUDE.md').read()
imports = re.findall(r'^@import (.+)$', main_content, re.MULTILINE)
for imp in imports:
if os.path.exists(imp):
main_content += '\n' + open(imp).read()
result = client.messages.count_tokens(
model='claude-opus-4-5',
messages=[{'role': 'user', 'content': main_content}]
)
print(f'総トークン数(CLAUDE.md + インポート): {result.input_tokens}')
"
最適化が動作に影響していないことを検証する:
# 動作テスト——主要なルールを列挙させる
claude -p "CLAUDE.mdの最重要制約をTop5で教えてください"
# タスクテスト——典型的なコーディングタスクを実行して規約が守られているか確認
claude -p "ISOの日付文字列をDateオブジェクトにパースするユーティリティ関数を新規作成して"
最適化前後の出力を比較する。動作が同一なら、削除したトークンは動作に必要ない内容だったということだ。
実測値: 3プロジェクトの最適化前後
プロジェクト1: TypeScript/Next.js SaaS(開発者4名)
- 最適化前: 3,200トークン(CLAUDE.md 1ファイル)
- 最適化後: 480トークン(ルート) + 1,100トークン(インポート) = 1,580合計(51%削減)
- 動作変化: なし——同じテストプロンプトで確認
- 1日200セッションでの月次節約: CLAUDE.md読み込みから33万トークン削減
プロジェクト2: Python/FastAPI バックエンド
- 最適化前: 1,800トークン
- 最適化後: 380トークン(ルート) + 620トークン(インポート) = 1,000合計(44%削減)
- 主な最適化: 大量の説明文を削除、12行のコマンドリストを1行に圧縮
プロジェクト3: モノレポ(Node API + React フロントエンド + 共有パッケージ)
- 最適化前: 2,600トークン(全体を1ファイルで管理)
- 最適化後: 350トークン(ルート) + 計900トークン(3つのディレクトリCLAUDE.md)
- 特定ディレクトリ作業時: Claudeが読み込むのは350 + 300 = 650トークン(元の2,600から75%削減)
繰り返し現れるパターン: 最初の最適化パスで説明文削除と散文圧縮だけで20〜25%の節約が見つかる。@import分割でさらに15〜25%。合計35〜50%の削減が動作ロスなしで一貫して達成できる。