モノレポでAGENTS.mdをネストして管理する方法
モノレポのルートに巨大なAGENTS.mdを置くと、コンテキスト消費や情報の陳腐化を招きます。各ディレクトリにファイルを分散配置し、必要な情報だけをエージェントに読み込ませる効率的な管理手法を解説します。
モノレポにおけるネストされた AGENTS.md の意味
モノレポにおけるネストされた AGENTS.md とは、リポジトリのルートに小さなファイルを1つ、各サービスディレクトリ内にさらに1つずつファイルを配置することを指します。ルートファイルには、リポジトリ全体で共通する少数のルールと、他のファイルがどこにあるかを示すマップを記述します。各サービス内のファイルには、そのディレクトリ固有のコマンドや規約を記述します。services/worker/queue.py を編集するエージェントは、ルートファイルと対象のワークファイルのみを読み込むため、一切関与しないフロントエンドのコンテキストを消費することはありません。
インストール作業は不要です。AGENTS.md は規約であり、アップストリームプロジェクトでも以下のように明記されています。
AGENTS.md は標準的な Markdown です。見出しは自由に使用してください。エージェントは提供されたテキストを解析するだけです。
このため、この手法を正しく習得する価値があります。フォーマットが変更されることはありません。問題となるのは配置とメンテナンスであり、これらは管理者の責務です。
なぜルート直下の巨大な AGENTS.md は機能しなくなるのか
Web アプリ、バックグラウンドワーカー、Terraform ディレクトリを保持するリポジトリのルートに 600 行の AGENTS.md を置くと、4 つの点で問題が発生します。
所有者が不在のため、陳腐化する。 apps/web 内のテストスクリプト名を変更するエンジニアは、apps/web 配下のファイルを編集します。ルートの AGENTS.md はその差分に含まれないため、レビュー担当者は不整合に気づきません。6 週間後、そのファイルには存在しないビルド手順が記述されており、変更を加えた本人もその事実を忘れています。
タスクのたびにコンテキストを消費する。 これらのファイルは、エージェントが何を尋ねられるかを知る前に、セッション開始時に読み込まれます。Claude Code のドキュメントにはこうあります。「CLAUDE.md ファイルは 1 ファイルあたり 200 行未満に抑えること。長すぎるファイルはコンテキストを過剰に消費し、指示への準拠率を下げる」。Codex は、指示ファイルの合計サイズがデフォルトの project_doc_max_bytes である 32 KiB に達すると、それ以上の読み込みを停止します。4 つのサービスを記述したルートファイルは、すべてのタスクにおいて、そのうち 3 つ分の予算を無駄に消費します。
指示同士が矛盾し始める。 Web ディレクトリは pnpm test を要求し、ワーカーは pytest -q を要求します。1 つのファイルに記述されると、各ルールは一部の状況でしか正しくないため、エージェントはどちらを適用すべきか推測しなければなりません。Claude Code のドキュメントは結果をこう説明しています。「2 つのルールが矛盾する場合、Claude は任意に一方を選択する可能性がある」。ディレクトリごとのファイルであれば、その文脈で有効なルールのみがコンテキストに入るため、推測の余地はなくなります。
エージェントがコードから読み取れる事実で埋め尽くされる。 ディレクトリツリー、依存関係リスト、各パッケージの概要などです。Claude Code の /doctor チェックは、まさにこれを除去するために存在します。これは「ディレクトリ構成、依存関係リスト、アーキテクチャの概要など、Claude がコードベースから導き出せる内容を削除」し、「ツールのデフォルトとは異なる落とし穴、根拠、慣習」のみを残します。その一文こそ、ある行がファイルに記述されるべきかどうかを判断する最良の基準です。
エージェントはルートのファイルを読み込みますか、それとも最も近いファイルのみを読み込みますか?
この点は多くのユーザーが誤解しやすいため、言い換えではなくアップストリームの規約を引用します。
各パッケージ内に個別の AGENTS.md を配置してください。エージェントはディレクトリツリー内で最も近いファイルを自動的に読み込むため、最も近いファイルが優先され、各サブプロジェクトで個別の指示を組み込むことが可能です。
競合については以下の通りです。
編集中のファイルに最も近い AGENTS.md が優先されます。ユーザーによる明示的なチャットプロンプトは、すべての設定を上書きします。
「優先される」という表現から「ルートのファイルは無視される」と解釈する人が多くいますが、そうではありません。この規約を実装しているツールでは、リポジトリのルートから作業ディレクトリまでのパス上にあるすべてのファイルが読み込まれ、結合されます。最も近いファイルが優先されるのは、同じ項目について異なる指示が記述されている場合のみです。
Codex はこの仕組みについて、「Codex はルートから順にファイルを連結し、空行で結合します。現在のディレクトリに近いファイルほど、以前のガイダンスを上書きします」と明記しています。Claude Code も自身のファイル名に対して同様の処理を行います。作業ディレクトリより上位のディレクトリにあるファイルは「起動時にすべて読み込まれ」、「発見されたすべてのファイルは、互いに上書きし合うのではなく、コンテキストとして連結されます」。作業ディレクトリより「下位」のディレクトリは挙動が異なり、Claude Code は「Claude がそれらのディレクトリ内のファイルを読み込む際」にオンデマンドでファイルを読み込みます。
ここから2つの実用的な結論が導かれます。ルートのファイルはリポジトリ内のすべてのセッションでプレフィックスとして機能するため、そこに記述する各行は週に100回コストを支払うものと考えてください。ディレクトリごとのファイルは、エージェントが別の場所で作業している間はコストがかかりません。つまり、詳細な指示はそこに記述するのが低コストであり、適切です。
この挙動は 2026 年 8 月時点の Codex および Claude Code のドキュメントに基づき確認されたものです。ツールによって実装がわずかに異なり、仕様変更も行われるため、チームが使用しているエージェントの読み込みルールを必ず確認してください。
3つのサービスを運用するためのリポジトリ構成例
repo/
AGENTS.md rules true everywhere, plus the map
apps/web/AGENTS.md TypeScript client, Vite, Vitest
services/worker/AGENTS.md Python queue consumer, pytest
infra/AGENTS.md Terraform and the deploy scriptsルートディレクトリのファイルは意図的に短くしています。参照先を定義し、すべてのディレクトリに共通するルールのみを記述します。
# AGENTS.md
This is a monorepo. Each top-level directory ships its own AGENTS.md.
Read this file and the AGENTS.md nearest the code you are editing
before you change anything.
- `apps/web` browser client
- `services/worker` queue consumer
- `infra` Terraform and deploy scripts
## Rules for the whole repository
- The package manager is `pnpm`. `npm install` writes a second lockfile
that CI ignores, so the install you tested is not the install that ships.
- Any `generated/` directory is build output. Edit the schema in
`schemas/` and run `pnpm codegen` instead.
- `.env.local` holds real credentials. Do not read it and do not print it.
- If you change code in a directory, update that directory's AGENTS.md
in the same commit.ディレクトリごとのファイルに詳細を記述します。ディレクトリの規模に応じて必要な長さを確保します。
# apps/web
Browser client. Vite and React, TypeScript with `strict` on.
## Commands
- `pnpm dev` serves on port 5173.
- `pnpm test` runs Vitest once and exits.
- `pnpm typecheck` runs `tsc --noEmit`.
## Conventions
- One component per file under `src/components/`.
- All HTTP goes through `src/api/client.ts`. Do not call `fetch` directly,
because the client attaches the auth header and retries on 429.
## Traps
- `pnpm build` does not type check. Vite strips the types instead of
checking them, so a broken type still produces a green build.
Run `pnpm typecheck` as a separate step.worker ファイルも同様の形式ですが、内容は異なります。インストールコマンド、pytest -q、コンシューマーが冪等性を維持すべき理由、テスト通過前に実行が必要なマイグレーションなどが含まれます。infra ファイルには、エージェントによる損害を防ぐためのルールを記述します。terraform apply は決して実行しないでください。terraform plan を実行して停止し、すでに設定済みのステートバックエンドを指定することで、エージェントが新しいバックエンドを初期化しようとするのを防ぎます。
これらのファイルに共通して記載されていない点に注目してください。各サービスが何のためのものかという説明は含まれていません。それは人間が理解すべき情報です。Upstream も同様の境界線を引いており、「README.md は人間用(クイックスタート、プロジェクト概要、貢献ガイドライン)」とし、AGENTS.md には「コーディングエージェントが必要とする詳細なコンテキスト(ビルド手順、テスト、規約)」を記述するよう推奨しています。AGENTS.md と人間向け README の分離ではその境界線について文単位で解説しており、コードの設計意図を記録する DESIGN.md では、コマンドではなく決定事項の理由を説明する3つ目のファイルについて解説しています。
コード変更時にファイルを更新するのは誰か?
ルールは1つです。ルートディレクトリのファイルに記述します。ディレクトリ内のコードを変更した担当者が、同じコミットでそのディレクトリの AGENTS.md を更新します。
これは文化的な理由ではなく、機械的な理由で機能します。ディレクトリごとのファイルはコードと同じ差分に含まれるため、プルリクエストのレビュアーは両方を同時に確認できます。ルートファイルは「全員のもの」であり、実質的に「誰のものでもない」ため、誰も読んでいない差分の中に埋もれてしまいます。
このルールをプルリクエストのチェックで補強します。変更された各ファイルの直近にある AGENTS.md を探し、そのファイルが更新されていない場合に報告します。
#!/usr/bin/env bash
# Warn when code changed but the nearest AGENTS.md above it did not.
changed=$(git diff --name-only origin/main...HEAD)
nearest_doc() {
d=$(dirname "$1")
while [ "$d" != "." ]; do
if [ -f "$d/AGENTS.md" ]; then echo "$d/AGENTS.md"; return; fi
d=$(dirname "$d")
done
echo "AGENTS.md"
}
printf '%s\n' "$changed" | while read -r f; do
[ -n "$f" ] || continue
case "$f" in AGENTS.md|*/AGENTS.md) continue ;; esac
doc=$(nearest_doc "$f")
printf '%s\n' "$changed" | grep -Fqx "$doc" && continue
echo "note: $f changed but $doc was not updated"
doneドキュメントを更新せずに API クライアントを修正したブランチでは、出力は以下のようになります。
note: apps/web/src/api/client.ts changed but apps/web/AGENTS.md was not updatedこれをエラーではなく警告にとどめてください。厳格なゲートを設けると、CI を通過させるためだけに空行を追加するような事態を招きます。ロボットのために編集されたファイルには、ファイルが存在しない場合よりも価値がありません。警告であれば、レビュアーが質問を投げかけるきっかけとなり、それこそが実際に機能するプロセスです。
AGENTS.md が古くなっているかどうかを見分けるには?
今日実行できるチェックが2つと、セッション内で確認できる兆候が1つあります。
各ファイルの更新日時と、それが説明しているコードの更新日時を比較します。 %cs はコミット日時を YYYY-MM-DD として出力します。
for f in $(git ls-files '*AGENTS.md'); do
d=$(dirname "$f")
printf '%s doc:%s code:%s\n' "$f" \
"$(git log -1 --format=%cs -- "$f")" \
"$(git log -1 --format=%cs -- "$d")"
doneapps/web/AGENTS.md doc:2026-02-11 code:2026-08-07
services/worker/AGENTS.md doc:2026-07-29 code:2026-08-09
infra/AGENTS.md doc:2026-08-01 code:2026-08-01ドキュメントの日付がコードの日付より6か月古くても、そのファイルが間違っているとは限りません。これは、どのファイルを最初に読むべきかを示しているに過ぎず、1秒で終わるチェックとしてはそれで十分です。
存在しなくなったパスを探します。 ドキュメントは非常に特定の形で劣化します。それは、削除されたコードを説明し続けることです。これらのファイル内のすべてのパスはバッククォートで囲まれているため、簡単に抽出してテストできます。
grep -o '`[^`]*`' apps/web/AGENTS.md | tr -d '`' | grep '/' | while read -r p; do
[ -e "$p" ] || [ -e "apps/web/$p" ] || echo "missing: $p"
doneこのチェックは CI に組み込むのではなく、出力を直接確認してください。このコマンドは src/**/*.ts のようなグロブや引用した URL もフラグとして検出します。これらにはスラッシュが含まれており、ディスク上のファイルではないためです。
セッション内での兆候。 エージェントがファイルを読み込み、ファイルに記述されている通りに src/api/client.ts を開こうとすると、ツールは以下を返します。
No such file or directoryそのため、エージェントは妥当な判断として、独自の fetch ラッパーを作成します。これこそが、古いファイルがもたらす真のコストです。エージェントはドキュメントを無視するわけではありません。ドキュメントに従い、3か月前に削除されたパスに到達し、すでに存在するコードを再構築してしまうのです。Ponytail(エージェントに最小限の変更のみを許可するツール)のようなスキルがあれば、こうした再構築の衝動は抑えられますが、ファイルが誤った場所を指し示しているヘルパーを見つけることはできません。
Claude Code は AGENTS.md ファイルを読み込みますか?
いいえ。ネストされたレイアウトはこの仕様に依存しているため、明言しておく必要があります。2026年8月現在、ドキュメントには「Claude Code は CLAUDE.md を読み込み、AGENTS.md は読み込まない」と記載されています。このパターンは依然として有効ですが、各 AGENTS.md の横に CLAUDE.md を配置する必要があります。
共有設定にツール固有の行を追加したい場合は、import 形式が適しています。services/worker/CLAUDE.md に以下を記述してください。
@AGENTS.md
## Claude Code
Use plan mode for changes under `services/worker/migrations/`.ツール固有の追加事項がない場合は、シンボリックリンク形式が適しています。
git ls-files '*AGENTS.md' | while read -r f; do
ln -s AGENTS.md "$(dirname "$f")/CLAUDE.md"
done
ls -l apps/web/CLAUDE.mdln は成功時に何も出力しないため、apps/web/CLAUDE.md -> AGENTS.md で一覧を確認してください。その後、セッションを開始して /context を実行すると、読み込まれたファイルが Memory files の下に表示されます。Windows ではシンボリックリンクの作成に管理者権限または開発者モードが必要なため、その場合は @AGENTS.md の import を使用してください。
これには1つ注意点があります。/compact の実行後、ルートファイルはディスクから再読み込みされますが、サブディレクトリ内のネストされたファイルは再注入されません。これらは、エージェントがそのディレクトリ内のファイルを次に読み込む際に反映されます。ディレクトリごとのルールが長いセッションの途中で適用されなくなったように見える場合、通常はこの仕様が原因です。そのディレクトリ内のいずれかのファイルに touch を実行すれば、ルールが再適用されます。
他のエージェントを AGENTS.md に向ける設定
Codex は AGENTS.md をネイティブで読み込みます。各階層で最初に AGENTS.override.md を確認するため、共有ファイルを編集することなく、特定のディレクトリにローカルな上書き設定を適用できます。結合後のサイズがデフォルトの project_doc_max_bytes である 32 KiB に達するとマージを停止します。ルートファイルを小さく保つべき理由はここにあります。
Aider は .aider.conf.yml を介して read: AGENTS.md という行でこれを取り込みます。
Gemini CLI は .gemini/settings.json を介して { "context": { "fileName": "AGENTS.md" } } でこれを取り込みます。
アップストリームでは、古い単数形の名前を使い続けているリポジトリ向けに、後方互換性のあるリネーム方法がドキュメント化されています:mv AGENT.md AGENTS.md && ln -s AGENTS.md AGENT.md。
非常に大規模なモノレポにおいて、Claude Code の claudeMdExcludes 設定はパスやグロブによって上位階層のファイルをスキップします。これは、他のチームのディレクトリが自身のディレクトリの上位に存在する場合に有用です。
エージェントのメモリやスキルとは何が違うのですか?
これらの仕組みは似ていますが、失敗する原因が全く異なるため、どれを選択すべきかを正確に理解しておく必要があります。
AGENTS.md はユーザーが作成し、git にコミットし、プルリクエストでレビューされるものであり、リポジトリをクローンした全員に対して同一です。一方、エージェントのメモリはエージェント自身が書き込み、リポジトリの外に保存され、特定の1台のマシンに限定されます。Claude Code のドキュメントでも同様の線引きがなされています。CLAUDE.md にはユーザーが記述する「指示とルール」が格納され、自動メモリには Claude が書き込む「学習とパターン」が格納されます。また、メモリディレクトリはマシン間で共有されません。判断基準は単純です。ある事実が、新しくクローンした同僚にとっても真実である必要があるならば、それはメモリに含めるべきではありません。エージェントのメモリがセッション間でどのように永続化されるかで、その側面について解説しています。
スキルはまた別の概念です。AGENTS.md はすべてのセッションで読み込まれるコンテキストですが、スキルは必要な時に読み込まれる手順です。Claude Code のドキュメントには、「エントリが複数ステップの手順である場合や、コードベースの一部にのみ関係する場合は、スキルまたはパススコープのルールに移動する」という有用なルールが記載されています。この文の後半部分は、まさにネストされた AGENTS.md が解決する内容です。前半部分は エージェントスキル の役割であり、同じ手順が複数のリポジトリで必要な場合は、10個の異なる AGENTS.md ファイルに同じ段落を貼り付けるのではなく、リポジトリ間でスキルを共有してください。
アップストリームでは、「執筆時点でメインの OpenAI リポジトリには 88 個の AGENTS.md ファイルが存在する」と指摘されています。その数字こそが、この議論のすべてを物語っています。大規模なリポジトリには、より大きなファイルは必要ありません。必要なのは、記述対象のコードの隣に配置され、そのコードを最後に変更した担当者が管理する、小さなファイルを増やすことです。
FAQ
ネストされた AGENTS.md はルートファイルを置き換えますか、それとも追加しますか?
追加されます。アップストリームの仕様では「最も近いファイルが優先される」とされており、これは競合時の挙動を指すものであり、読み込み対象を指すものではありません。Codex は「ルートから順にファイルを連結し、空行で結合する」仕様であり、Claude Code は作業ディレクトリから上位へ向かって探索したすべてのファイルを連結します。最も近いファイルが優先されるのは、同一の項目に対して異なる指示がある場合のみです。共通ルールはルートに一度だけ記述し、各ディレクトリで繰り返さないでください。
ルートの AGENTS.md はどの程度のサイズが適切ですか?
リポジトリ内のすべてのリクエストに対して、その内容が先頭に付与されても気にならないサイズに留めてください。実際、そのように動作するためです。Claude Code のドキュメントでは、1ファイルあたり200行未満を推奨しており、長すぎると「指示への準拠度が低下する」と警告しています。Codex はデフォルトで合計32 KiBに達すると指示ファイルの結合を停止します。ルートファイルで4つのサービスを網羅している場合、個別のタスクにとっては大部分が不要な情報となります。詳細はディレクトリごとのファイルへ分割し、ルートには目次を残す構成にしてください。
これらのファイルが陳腐化するのを防ぐにはどうすればよいですか?
ルートファイルに「ディレクトリ内のコードを変更する際は、同一コミットでそのディレクトリの AGENTS.md も更新する」というルールを1つ追加してください。コードの隣にファイルを配置することでルールが定着します。変更が人間によるレビュー対象であるプルリクエストの差分に含まれるためです。変更されたパスから最も近い上位の AGENTS.md を特定する CI 警告を追加し、定期的に各ファイルの git log -1 --format=%cs を、そのファイルが対象とするディレクトリで実行した同一コマンドの結果と比較してください。
Claude Code は AGENTS.md ファイルを読み込みますか?
いいえ。2026年8月現在、ドキュメントには「Claude Code は CLAUDE.md を読み込むが、AGENTS.md は読み込まない」と明記されています。同一ディレクトリに CLAUDE.md を作成し、1行目に @AGENTS.md を記述してください。これにより共有ファイルが読み込まれ、その下に Claude 特有の指示を追加できます。追加の指示がない場合は ln -s AGENTS.md CLAUDE.md で作成したシンボリックリンクも有効ですが、Windows では管理者権限または開発者モードが必要です。セッション内で /context を実行し、Memory files 配下にファイルが表示されることを確認してください。
時折しか適用されないルールはどこに記述すべきですか?
AGENTS.md には記述しないでください。このファイルはすべてのセッションで読み込まれるため、記述されたすべての行が、ユーザーが実際に入力したリクエストと競合して注意を分散させます。時折必要となる複数の手順からなる処理は、オンデマンドで読み込まれるスキルとして定義してください。特定のディレクトリにのみ適用されるルールは、そのディレクトリの AGENTS.md に記述します。ディレクトリツリーや依存関係リストなど、エージェントがコードから直接読み取れる事実は、どちらにも記述する必要はありません。