はじめに
はじめまして、テックバディ運営の大下です。
Claude Codeを使い始めると、だいたい1週間くらいで CLAUDE.md を書き始めます。「毎回同じ説明をするのが面倒だから、ルールをファイルに書いておこう」。動機としては100点です。
ところが、しばらく運用していると、こういう状態になりがちです。
- 気づけば300行を超えていて、もはや誰も読み返していない
- 「テストをちゃんと書くこと」と書いたのに、書かれない
- 「本番環境には触らないこと」と書いたのに、触られてヒヤッとした
- 情報を分割したくて
@importを並べたが、何も軽くならなかった
これらは全部、CLAUDE.md が何であって何でないかを取り違えたことから来ています。この記事では、初心者がやりがちな失敗を5つ取り上げ、それぞれ「Before → After」の形で改善例を示します。
本記事の内容は、2026年8月時点の Claude Code公式ドキュメント(How Claude remembers your project) を根拠にしています。
1. 失敗①:コードベースを読めば分かることを、全部書いてしまう
Before
初めて書く CLAUDE.md は、たいていこうなります。
# プロジェクト概要
このプロジェクトはNext.js 15とTypeScriptで作られたECサイトです。
バックエンドはFastAPI、DBはPostgreSQLを使用しています。
## ディレクトリ構成
- src/app/ … App Routerのページ
- src/components/ … Reactコンポーネント
- src/lib/ … ユーティリティ
- src/api/ … APIクライアント
- tests/ … テストコード
(以下、40行続く)
## 依存パッケージ
- next: 15.x
- react: 19.x
- zod: 3.x
(以下、30行続く)
一見よさそうに見えますが、ここに書かれた情報のほぼ全部を、Claudeは自分で調べられます。 ls すればディレクトリ構成は分かるし、package.json を読めば依存関係は分かります。
なぜ問題なのか
CLAUDE.md は毎セッションの開始時にコンテキストウィンドウへ読み込まれます。つまり、書いた分だけ毎回トークンを消費します。しかも公式ドキュメントは、こう明記しています。
Size: target under 200 lines per CLAUDE.md file. Longer files consume more context and reduce adherence.
(サイズ:1ファイルあたり200行未満を目標に。長いファイルはコンテキストを消費し、遵守率を下げる)
長く書くほど守られなくなる、というのがポイントです。「念のため全部書いておく」は、逆効果になります。
After
「調べれば分かること」を削り、「調べても分からないこと」だけを残します。
# プロジェクト固有のルール
## 注意点
- `src/lib/legacy/` は旧実装。新規コードから import しない(移行中)
- 決済まわりの金額は必ず整数(最小通貨単位)で扱う。float 禁止
- `zod` のスキーマは `src/schemas/` に集約。コンポーネント内で定義しない
## コマンド
- テスト: `pnpm test`(`npm test` ではない)
- 型チェック: `pnpm typecheck`
- DBマイグレーション: `pnpm db:migrate`(本番向けは手動承認が必要)
判断基準はシンプルです。「新しくチームに入った人に、口頭で説明することになる内容か?」 ディレクトリ構成は説明しません(見れば分かるので)。「legacy/ は触るな」は説明します。
なお、Claude Code v2.1.206以降では、/doctor がリポジトリにコミット済みの CLAUDE.md に対してトリム案を出してくれます。ディレクトリ構成・依存一覧・アーキテクチャ概要といったコードから導出できる内容を削り、落とし穴・設計理由・ツール既定と異なる規約を残す方向に整理してくれます。
【スクショ指定】長い
CLAUDE.mdをコミットした状態で/doctorを実行し、CLAUDE.mdのトリム提案が表示されている画面のスクリーンショットを掲載する。削除候補として挙がっている項目が読めるように。
2. 失敗②:抽象的すぎて、守りようがない
Before
- コードは読みやすく書くこと
- テストはちゃんと書くこと
- ファイルは整理して配置すること
- エラーハンドリングを適切に行うこと
これは「守られなかった」のではなく、そもそも守れる形になっていません。 「適切に」の基準がどこにも書かれていないからです。
After
公式ドキュメントが挙げている書き換えの原則は、**「検証できる粒度まで具体化する」**です。
| ❌ 抽象的 | ✅ 具体的 |
|---|---|
| Format code properly | Use 2-space indentation |
| Test your changes | Run npm test before committing |
| Keep files organized | API handlers live in src/api/handlers/ |
これを踏まえて書き直すとこうなります。
- インデントはスペース2つ。`.editorconfig` に従う
- 新しい関数を追加したら、同じ階層の `__tests__/` に必ずテストを1本追加する
- APIハンドラは `src/api/handlers/` にのみ置く
- API呼び出しの失敗は握りつぶさず、`AppError` でラップして再スローする
コツは、その指示が守られたかどうかを、あとから機械的に確認できるかを考えることです。「読みやすく」は確認できませんが、「インデントはスペース2つ」は確認できます。
3. 失敗③:CLAUDE.md を「設定ファイル」だと思っている
これが最も重大な誤解です。
Before
- 本番環境には絶対にデプロイしないこと
- `.env` ファイルは絶対に読まないこと
- `rm -rf` は絶対に実行しないこと
気持ちは分かりますが、これは安全装置になりません。
なぜ問題なのか
公式ドキュメントの記述が決定的です。
CLAUDE.md content is delivered as a user message after the system prompt, not as part of the system prompt itself. Claude reads it and tries to follow it, but there's no guarantee of strict compliance.
(CLAUDE.mdの内容は、システムプロンプトの一部としてではなく、システムプロンプトの後のユーザーメッセージとして渡される。Claudeはそれを読み、従おうとするが、厳格な遵守は保証されない)
つまり CLAUDE.md は「お願い」であって「ロック」ではありません。強い言葉で書いても強制力は増えません。
After
「絶対に」で始まる行を見つけたら、それは CLAUDE.md ではなく別の仕組みに移すサインです。
具体的な使い分けは次の通りです。
| やりたいこと | 書く場所 |
|---|---|
| 特定のツール・コマンド・パスをブロックする | 設定ファイルの permissions.deny
|
| コミット前に必ずlintを走らせる | hooks(PreToolUseなど) |
| コーディング規約・命名規則を伝える | CLAUDE.md |
| 「なぜこの設計なのか」という背景を伝える | CLAUDE.md |
| リリース手順のような多段階の作業手順 | Skills |
先ほどのBeforeを書き換えると、こうなります。
// .claude/settings.json ── 強制力があるのはこちら
{
"permissions": {
"deny": [
"Read(.env)",
"Bash(rm *)",
"Bash(vercel deploy *)"
]
}
}
<!-- CLAUDE.md ── 判断の指針を伝えるのはこちら -->
- 本番デプロイは人間が手動で行う。デプロイ手順を提案するのは構わないが、実行しない
- 環境変数が必要な場合は `.env.example` を参照し、実際の値は求めない
deny で境界を作り、CLAUDE.md で意図を伝える。 この二段構えが正解です。
4. 失敗④:全部1ファイルに詰め込む(@import は軽くならない)
Before
ファイルが肥大化してくると、多くの人がこう考えます。
# CLAUDE.md
@docs/coding-style.md
@docs/testing-guide.md
@docs/api-conventions.md
@docs/deployment.md
「分割したから軽くなったはず」──なりません。
Splitting into
@pathimports helps organization but doesn't reduce context, since imported files load at launch.
(@pathによるインポートへの分割は整理には役立つが、コンテキストの削減にはならない。インポートされたファイルは起動時に読み込まれるため)
@import は「複数ファイルに分けて管理できる」だけで、最終的に全部が起動時に展開されてコンテキストに入ります。ちなみにインポートの再帰は最大4ホップまでです。
After:.claude/rules/ とパススコープを使う
本当にコンテキストを節約したいなら、.claude/rules/ のパススコープ機能を使います。
your-project/
├── .claude/
│ ├── CLAUDE.md # 常に読まれる。全体に効くことだけ
│ └── rules/
│ ├── code-style.md # paths なし → 常に読まれる
│ ├── api.md # paths あり → 該当ファイルを触るときだけ
│ └── frontend.md # paths あり → 該当ファイルを触るときだけ
paths フロントマターを付けたルールは、Claudeが該当するファイルを読んだときにだけコンテキストに入ります。
---
paths:
- "src/api/**/*.ts"
---
# APIの実装ルール
- すべてのエンドポイントで入力バリデーションを行う
- エラーレスポンスは共通フォーマット(`ErrorResponse`)に揃える
- OpenAPIのコメントを必ず付ける
これで、フロントエンドの作業をしている間はAPIのルールがコンテキストを消費しません。paths を書かないルールファイルは、.claude/CLAUDE.md と同じ扱いで起動時に読み込まれます。
パターンは **/*.ts のようなglobで書け、src/**/*.{ts,tsx} のようなブレース展開も使えます。
手順ものは Skill へ
もう1つの逃がし先が Skills です。公式ドキュメントの整理はこうです。
Rules load into context every session or when matching files are opened. For task-specific instructions that don't need to be in context all the time, use skills instead.
「リリース手順」「障害対応手順」のような、特定の作業のときだけ必要な多段階の手順は、CLAUDE.md でも rules でもなく Skill にします。Skillは呼び出されたとき、あるいはClaudeが関連すると判断したときにだけ読み込まれます。
5. 失敗⑤:置き場所を間違える/矛盾したまま育つ
5-1. 個人の好みをチーム共有ファイルに書いてしまう
CLAUDE.md には複数の置き場所があり、すべてが上書きではなく連結されます。読み込み順は「広い→狭い」です。
ここでよくあるのが、個人の好み(「日本語で応答して」「コミットメッセージは英語で」など)をチーム共有の ./CLAUDE.md に書いてコミットしてしまうケースです。チーム全員に自分の好みが配られます。
- 全プロジェクトで効かせたい個人設定 →
~/.claude/CLAUDE.md - このプロジェクトだけの個人設定 →
./CLAUDE.local.md(.gitignoreに追加する) - チームで共有すべき規約 →
./CLAUDE.md(コミットする)
さらに、ディレクトリ階層を上に遡って読み込まれる点にも注意してください。foo/bar/ で起動すると、foo/CLAUDE.md と foo/bar/CLAUDE.md の両方が読まれます(順序は上位が先、起動ディレクトリに近いものが後)。
5-2. 矛盾を放置する
連結される以上、古い指示と新しい指示が両方コンテキストに入ります。
Consistency: if two rules contradict each other, Claude may pick one arbitrarily.
(一貫性:2つのルールが矛盾している場合、Claudeはどちらか一方を任意に選ぶ可能性がある)
「言うことを聞かない」の原因が、実は3階層上の CLAUDE.md に書かれた古い指示だった、というのは珍しくありません。定期的に棚卸しをしてください。
5-3. 「本当に読み込まれているか」を確認する
指示が効かないとき、まず疑うべきはそもそも読み込まれていない可能性です。確認コマンドは2つあります。
| コマンド | 用途 |
|---|---|
/context |
実際にこのセッションで読み込まれたメモリファイルの一覧を見る |
/memory |
メモリファイルの場所を一覧し、選択してエディタで開く |
/memory は「置き場所の一覧」、/context は「実際に読み込まれた結果」 です。デバッグに使うのは /context のほうです。
【スクショ指定】セッション中に
/contextを実行し、「Memory files」のセクションにCLAUDE.mdなどが列挙されている部分のスクリーンショットを掲載する。読み込まれているファイルのパスが読める解像度で。
5-4. 小ワザ:メンテナ向けメモはHTMLコメントで書く
地味に便利な仕様です。ブロックレベルのHTMLコメントは、コンテキストに注入される前に除去されます。
<!-- 2026-08 更新: 決済リファクタ完了後にこの節を見直すこと -->
- 決済まわりの金額は必ず整数で扱う
このコメントは人間には見えますが、Claudeのコンテキストは消費しません。「なぜこのルールがあるのか」「いつ見直すか」といったメンテナンス用のメモを、トークンを使わずに残せます(コードブロック内のコメントは除去されません)。
まとめ
CLAUDE.md を書くときの原則を5つにまとめます。
- 調べれば分かることは書かない。 200行未満を目標に。長いほど遵守率は下がる
- 検証できる粒度まで具体化する。 「適切に」ではなく「スペース2つ」
-
CLAUDE.mdに強制力はない。 止めたいものはpermissions.deny、必ず走らせたいものは hooks -
@importでは軽くならない。 コンテキストを減らしたいなら.claude/rules/のパススコープ、手順ものは Skill へ -
置き場所を使い分け、定期的に棚卸しする。 効いているかは
/contextで確認する
そして、育て方についても一言。公式ドキュメントは、CLAUDE.md に追記すべきタイミングをこう定義しています。
- Claudeが同じ間違いを2回したとき
- コードレビューで、Claudeが知っておくべきだった指摘が出たとき
- 前のセッションでも入力した同じ訂正を、また入力したとき
- 新しいチームメンバーなら同じ説明が必要になるとき
つまり、最初から完璧な CLAUDE.md を書こうとしないことです。まずは /init で叩き台を作り、実際に困ったことだけを追記していく。これが結局いちばん短く、いちばん効く CLAUDE.md になります。
【スクショ指定】新規プロジェクトで
/initを実行し、生成されたCLAUDE.mdのプレビューが表示されている画面のスクリーンショットを掲載する。
参考リンク
- How Claude remembers your project — Claude Code Docs — CLAUDE.mdの階層、rules、import、auto memory
- Skills — 必要なときだけ読み込まれる手順の置き場所
- Hooks — 決まったタイミングで確実に実行する仕組み
- Configure permissions — 強制力のある禁止ルールの書き方
- Context window — CLAUDE.mdがコンテキストのどこに入るか
宣伝
最後に少しだけ宣伝させてください。
私たちは テックバディ という、フルスタックAIエンジニア育成コースを運営しています。
この記事で扱った CLAUDE.md は、カリキュラムのPhase 0で基礎を学び、その後のフェーズを通してずっと育て続ける位置づけにしています。AI駆動開発では、コードを書く力と同じくらい、AIに渡す文脈を設計する力が成果を左右するからです。
- コンテキストウィンドウの仕組みと「Lost in the Middle」への対処
-
CLAUDE.md・rules・Skills・hooks・パーミッションの使い分け - Next.js / TypeScript / FastAPI / PostgreSQL といった実務スタックでの開発演習
- メンターとの週1回の1on1
といった内容で構成しています。
「AIに指示は出せるが、毎回同じことを説明していて効率が上がらない」という方は、ぜひ一度ご覧ください。
最後までお読みいただきありがとうございました。