最近、Twitterで「Claude Codeはフォルダ構造によって精度が大きく変わる」という投稿が流れてきて、めちゃくちゃ頷いてしまった。
あれ、本当にそうなんですよね。私もこの3ヶ月でそれを痛感した一人なので、自分が実際に試してみた内容を共有しようと思います。
TL;DR
- フォルダが深すぎると Claude Codeがコンテキストを迷子にする
- CLAUDE.mdに「やってほしいこと」より「やってはいけないこと」を書く方が効く
- プロジェクトルートのCLAUDE.mdと、サブディレクトリのCLAUDE.mdを使い分けると精度が上がった
背景
私はフリーランスでWebアプリ開発をやっていて、今年の1月ごろからClaude Codeをメインの開発ツールとして使い始めた。最初は「コード補完ツール」くらいに思ってたんだけど、使い込むほど「Claude Codeはプロジェクトの構造を読んで振る舞いを変えている」ことに気づいた。
で、ある日やらかした。
やらかしその1:ネスト6層のプロジェクト
あるプロジェクトで、こんな構造を作っていた。
project/
├── src/
│ ├── features/
│ │ ├── auth/
│ │ │ ├── components/
│ │ │ │ ├── forms/
│ │ │ │ │ └── LoginForm.tsx
│ │ │ │ └── ...
│ │ │ ├── hooks/
│ │ │ └── services/
│ │ └── dashboard/
│ │ └── ...
├── tests/
└── CLAUDE.md
「設計としては正しい」と思ってたんだけど、Claude Codeに LoginForm.tsx を修正してもらおうとすると、毎回 src/features/auth/components/forms/LoginForm.tsx のフルパスを指定しないとうまく見つけてくれない。しかも、「この LoginForm は useAuth フックを使ってるから〜」みたいな横断的な理解がグラグラになってた。
試しにプロジェクト構造をフラットにしてみた。
project/
├── src/
│ ├── auth-form.tsx ← LoginFormを移動
│ ├── auth-hook.ts ← useAuthを移動
│ ├── auth-service.ts
│ ├── dashboard.tsx
│ └── ...
├── tests/
└── CLAUDE.md
これは「設計的にどうなんだ」という気持ちはあったけど、Claude Codeの精度は明らかに上がった。
同じ指示を出しても、修正箇所の特定が速い・関連ファイルを自分で辿れる・「LoginFormとuseAuthの関係」を理解した上でコードを変えてくれる、という差が出た。
ネスト深すぎ問題の原因は何かと考えると、おそらくコンテキストウィンドウの中でファイルパスが占める文字数が増えること、それとClaudeが「このファイルが他のどのファイルと関係しているか」を推論するのに必要な情報が分散すること、じゃないかと思ってる。正確なところはわからないけど、体感的にこれが一番大きい。
やらかしその2:CLAUDE.mdに「こうしてほしい」を書きすぎた
最初のCLAUDE.mdはこんな感じだった。
# プロジェクト設定
## コーディングスタイル
- TypeScriptを使う
- 関数コンポーネントで書く
- propsはinterfaceで定義する
- コメントは日本語で書く
- エラーハンドリングは必ず実装する
- ログは console.log ではなく logger を使う
- テストはvitest + testing-libraryで書く
- 変数名はcamelCase
- ファイル名はkebab-case
...(20行以上続く)
これ、全然守られなかった。
Claude Codeって、「やってほしいこと」の羅列が長くなると、どこかが漏れる。20個のルールを全部守るのは人間でもしんどい。
で、試行錯誤した結果、「やってはいけないこと」を中心に書く方が効果があるとわかった。
# このプロジェクトのルール
## 絶対にやってはいけないこと
- `console.log` を使わない(代わりに `import { logger } from '@/lib/logger'` を使う)
- `any` 型を使わない(`unknown` を使って型ガードで絞る)
- テストなしでUIコンポーネントを追加しない
- `useEffect` の依存配列を空にしない
## 重要なコンテキスト
- 認証は `src/auth-service.ts` の `AuthService` クラスで一元管理している
- API呼び出しは `src/api-client.ts` を経由する(直接fetchしない)
否定形の制約の方が「何がNGか」が明確だから、Claude Codeが判断しやすいんだと思う。あと、「重要なコンテキスト」としてプロジェクト独自のアーキテクチャ決定を書くのが効いた。
ルートCLAUDE.md + サブディレクトリCLAUDE.mdの使い分け
もう一つ気づいたのが、Claude Codeはサブディレクトリに置いた CLAUDE.md も読んでくれるということ。
これを使って、以下のような構成にした。
project/
├── CLAUDE.md ← プロジェクト全体のルール
├── src/
│ ├── CLAUDE.md ← フロントエンド固有のルール
│ └── ...
└── api/
├── CLAUDE.md ← API固有のルール(DBスキーマ情報など)
└── ...
ルートの CLAUDE.md はこう:
# プロジェクト概要
ECサイトのフルスタックアプリ。Next.js + FastAPI構成。
## ディレクトリ構造
- `src/` → Next.jsフロントエンド
- `api/` → FastAPI バックエンド
- `tests/` → E2Eテスト(Playwright)
## やってはいけないこと
- `src/` と `api/` 間で直接importしない(APIはHTTP経由)
api/CLAUDE.md にはDBスキーマのサマリーを書く:
# APIディレクトリのルール
## データモデル(重要)
- User: id, email, created_at(パスワードはハッシュ済み、生値は保持しない)
- Order: id, user_id, status(status: pending/paid/shipped/cancelled)
- OrderItem: id, order_id, product_id, quantity, price_at_order
## やってはいけないこと
- 生のSQLを書かない(SQLAlchemyのORMを使う)
- User.passwordを返すエンドポイントを作らない
こうすると、APIディレクトリで作業しているときはそのコンテキストが優先される。DBスキーマを毎回説明しなくても、Order モデルの構造を理解した上でコードを書いてくれるようになった。
まとめ
3ヶ月使い込んで出た結論:
| 工夫 | 効果 |
|---|---|
| フォルダのネストを浅くする(3層以内推奨) | 関連ファイルの発見・理解が速くなる |
| CLAUDE.mdは「やってはいけないこと」中心に | 制約が守られやすくなる |
| サブディレクトリにもCLAUDE.mdを置く | ローカルコンテキストが優先される |
| 独自アーキテクチャ決定をCLAUDE.mdに書く | 「このプロジェクトの流儀」が伝わる |
Claude Codeは「よきに計らって」というより「ちゃんと制約と文脈を与えた上で動かす」ツールだなと最近思っている。CLAUDE.mdが第一のインターフェイスで、フォルダ構造が第二のインターフェイス。この2つを整えると、出力が別物になる。
まだ自分でも実験中なので、「こういうやり方の方が効いたよ」という知見があればぜひコメントで教えてください。