何が紛らわしいのか
オフィス業務ではフォルダを何重にも入れ子にする。「2026 > 第3四半期 > 契約書 > 最終版」のように深く掘るのが自然だ。だからコーディングを始めた頃は、プロジェクトも同じようにフォルダの中にフォルダで整理すればよいと思える。
ところが Claude Code のような AI コーディングツールは、1つのプロジェクトを1つの「フラットな」フォルダに置き、そのフォルダから作業を始めよと言う。なぜか。答えは1つだ。ソフトウェアを動かす3つの核心装置が、すべて「フォルダ」という同じ境界を共有しているからだ。
まず3つの用語——git・ハーネス・デプロイとは
git はコードの「バージョン保存ツール」だ。今この瞬間のファイル状態をまるごと撮り(コミット)、後で戻したり比較したりできるようにする。保存の単位ひとつを「リポジトリ(repo)」と呼ぶ。
ハーネスは、AI がうまく働けるようプロジェクトをあらかじめ整えておくことだ。新人に渡すオンボーディング文書のようなもの。その中核が CLAUDE.md・AGENTS.md というルール文書で、AI がそのフォルダを開くと自動で読み、「このプロジェクトはこういうもの、これはするな」を毎回説明せずに済む。
デプロイは、作ったコードをインターネットに載せて他人が見られるようにすることだ。Vercel・Railway などが代表例。以下でこの3つが1つのフォルダにどう束ねられるかを順に見る。
出発点:ファイルシステムは木だ
コンピュータのファイル構造は逆さにした木だ。上から下へ枝が伸び、1つのフォルダはその木の「枝1本まるごと」を意味する——そのフォルダとその下のすべてのサブフォルダ・ファイルを1つの塊として。これを閉じた枝、つまり subtree という。
なぜ重要か。1つのフォルダが「ここからここまでが1まとまり」という境界をタダで与えてくれるからだ。後に出る git・ハーネス・デプロイはいずれも境界の明確なファイルの束を必要とするが、フォルダがすでにその境界を提供している。だから車輪を再発明せず、フォルダの上に乗せる。
git:フォルダがそのままリポジトリ
git はフォルダの中に隠れた .git フォルダを1つ作り、その .git の親フォルダを「ルート」とみなし、その下すべてを追跡対象とする。つまり .git 1つ = リポジトリ1つ = フォルダ1つだ。
コミット(スナップショット)は「このフォルダ下のすべてのファイルの状態」をアトミックに、つまりまるごと一度に撮る。境界がなければ「何を撮るか」を定義できない。さらに git の中でファイルの位置はすべてルート基準の相対パス(src/app.js のような)で保存される。共通のルート——フォルダ——がなければ、この相対パス体系そのものが成り立たない。だからリポジトリが1つのフォルダであることは設計上の必然だ。
ハーネス:ルールはフォルダのルートに錨を下ろす
AI ツールはセッション開始時、作業フォルダのルートにある CLAUDE.md・AGENTS.md を自動で読む。だからフォルダさえ正しく開けば、AI は「プロジェクトを理解した状態」で始められる——スタックや禁止事項、検証コマンドを毎回説明し直す必要がない。
ルールの読み込みは上書きではなく「累積」だ。グローバル(~/.claude/CLAUDE.md)→ プロジェクトルート → サブフォルダの順に積み上がり、下へ行くほど上位ルールに細部を足す。だからフォルダ構造がそのままルールの適用範囲になる。フォルダがルールの錨というわけだ。CLAUDE.md は Claude 専用、AGENTS.md は Codex・Gemini など他エージェントまでの共通標準なので、シンボリックリンクで1つに束ねれば、どの AI を使っても同じルールが効く。
デプロイ:git コミットをそのままデプロイ成果物に使う
Vercel のようなデプロイサービスは git リポジトリを1つ繋いでおく。そのリポジトリに push すると webhook(自動シグナル)がサービスを起こし、サービスはそのコミット時点のリポジトリをまるごと取得し、ルートでビルドしてインターネットに載せる。
ここでデプロイは車輪を再発明しない。git コミットがすでに「コードの特定の状態」を完全に定義しているので、そのコミットをそのままデプロイの単位(成果物)として再利用する。デプロイごとにコミットハッシュ(SHA)が付き、ロールバックは古いコミットを再デプロイすることだ。push 一回で「バージョン保存 + ルール適用 + ウェブ反映」が同時に走る理由がここにある。
5つの軸で整理
5つの軸を並べれば、1つのフォルダがなぜこれほど多くの役割を兼ねるのか一目でわかる。すべては1つの事実でつながる——どれも境界を持つファイルの束を必要とし、フォルダがその境界を与える。
| 軸 | 単位 | 錨 | なぜフォルダでなければならないか |
|---|---|---|---|
| ファイルシステム | 木の閉じた枝 | フォルダのルート | フォルダ = 境界を持つ subtree。すべての上位概念が立つ土台。 |
| git バージョン管理 | リポジトリ(repo) | .git/(ルートごとに1つ) | コミット = ルート下のワーキングツリー全体のアトミックなスナップショット。パスもすべてルート相対。 |
| ハーネス(AI ルール) | ルールのスコープ | CLAUDE.md · AGENTS.md | AI がセッション開始時にルート文書を自動ロード。グローバル→ルート→サブへ累積。 |
| セッション(cwd) | AI の作業範囲 | Claude の起動位置 | 検索・権限・影響範囲が cwd 基準。フォルダがそのままスコープであり安全境界。 |
| デプロイ(Vercel 等) | デプロイ成果物 | commit SHA | push でそのコミット時点のリポをビルド・デプロイ。git コミットをそのままデプロイ単位に再利用。 |
推奨するフォルダ構成
だから実務の標準はシンプルだ。プロジェクトは入れ子にせず横に並べ、各プロジェクトのルートに .git と CLAUDE.md を置き、そのルートから AI 作業を始める。3つを1つのフォルダに揃える——git ルート = ルール文書の場所 = AI の起点。
逆に、プロジェクトフォルダの中にもう1つ独立したプロジェクトを入れ子にすると、リポジトリの中にリポジトリができ、git コマンドがどのリポジトリを対象にするか混乱し、AI を誤った深さで起動しやすくなり、ルールや検索範囲がずれる。
workspace/
├── project-A/ <- ここで Claude を起動
│ ├── .git/ (バージョン管理の境界)
│ ├── CLAUDE.md (ハーネスのルール)
│ └── src/
├── project-B/ <- ここで Claude を起動
│ ├── .git/
│ ├── CLAUDE.md
│ └── src/
└── project-C/
├── .git/
├── CLAUDE.md
└── src/workspace/
└── project-A/
├── .git/
├── CLAUDE.md
└── project-B/ <- リポの中にリポ · cwd の混乱
├── .git/
└── CLAUDE.mdではフォルダの中のフォルダは絶対だめか
誤解のないように。1つのプロジェクト「の中で」フォルダを分けるのは正常で推奨される。src/・docs/・tests/ のようにファイルを系統立てて整理するのは存分にやってよい。問題は「独立したプロジェクト(=それぞれの境界)どうし」を入れ子にすることだ。
例外に見える3つも原則を破らない。monorepo は1つのリポジトリ(1つのフォルダ)の中で複数のパッケージを論理的に分けるだけで、リポジトリは依然1つだ(デプロイは Root Directory 設定でパッケージごとに指定)。submodule はリポジトリの中から別のリポジトリを「参照」するだけで、それぞれ独立した .git を保つ。worktree は1つの履歴を複数のフォルダに同時に広げるだけで、源の .git は1つだ。3つとも「リポジトリ = 1つのフォルダ」の原則の上で組み合わせるものであって、破るものではない。
一言でまとめると
すべては境界を持つファイルの束を必要とし、フォルダがその境界を最も自然に与える。だから git・ハーネス・デプロイは車輪を再発明せず、1つのフォルダに乗る。バイブコーディングで「フォルダ = 境界」を理解すれば、ツールがなぜそう動くのかが一度に腑に落ちる。
