SSD Nodes Learn Hosting plans →
ガイド Matt Connor著者 Matt Connor ・更新日 2026-08-26

モノレポのAGENTS.mdをネストする構成と書き方

600行のルートAGENTS.mdが古くなり、不要な情報でコンテキストを消費する問題を解決します。サービスごとに配置する構成と、Codexの32 KiB制限を解説します。

モノレポでネストした AGENTS.md が意味すること

モノレポでネストした AGENTS.md を使う場合、リポジトリのルートに小さなファイルを 1 つ置き、各サービスディレクトリ内にもう 1 つずつファイルを置きます。ルートのファイルには、全体に適用される少数のルールと、ほかのファイルの配置場所を示すマップを記載します。各サービスのファイルには、そのディレクトリだけで使うコマンドと規約を記載します。エージェントが services/worker/queue.py を編集するときは、ルートのファイルと worker のファイルを読み取ります。編集しないフロントエンドの情報にコンテキストを使うことはありません。

インストールするものはありません。AGENTS.md は規約であり、upstream project も明確にそう説明しています。

AGENTS.md は標準的な Markdown にすぎません。見出しは自由に使用できます。エージェントは、提供されたテキストをそのまま解析します。

この手法を正しく学ぶ価値があるのは、そのためです。形式が途中で変わることはありません。問題になるのは配置と保守であり、どちらも担当するのはあなたです。

大きなルート AGENTS.md はなぜ機能しなくなるのか?

Web アプリケーション、バックグラウンドワーカー、Terraform ディレクトリを含むリポジトリのルートに、600 行の AGENTS.md を 1 つだけ置く構成は、4 つの問題を引き起こします。

誰も管理しないため、内容が古くなります。 apps/web 内のテストスクリプト名を変更したエンジニアは、apps/web 配下のファイルを編集しています。ルートの AGENTS.md はその差分に含まれないため、レビュー担当者は不整合に気付きません。6 週間後、そのファイルには既に存在しないビルド手順が記載されたままになり、変更を加えた本人もその経緯を忘れています。

すべてのタスクでコンテキストを消費します。 これらのファイルは、エージェントが依頼内容を把握する前のセッション開始時に読み込まれます。Claude Code のドキュメントには、具体的な目安として「CLAUDE.md ファイル 1 つにつき 200 行未満を目標にしてください。長いファイルはより多くのコンテキストを消費し、指示への準拠率を下げます」と記載されています。Codex は、指示ファイルの合計サイズが 32 KiB(デフォルトの project_doc_max_bytes)に達すると、それ以降のファイルを結合しません。4 つのサービスを説明するルートファイルでは、各タスクでそのうち 3 つ分の予算を無駄に使うことになります。

指示同士が矛盾し始めます。 Web ディレクトリでは pnpm test が必要です。ワーカーでは pytest -q が必要です。これらを 1 つのファイルに記述すると、各ルールは一部の状況でしか正しくないため、エージェントはどちらを適用すべきか推測しなければなりません。Claude Code のドキュメントでは、その結果を「2 つのルールが矛盾する場合、Claude は一方を恣意的に選ぶことがあります」と説明しています。ディレクトリ単位のファイルに分ければ、2 つのルールが同時にコンテキストへ入ることはないため、推測が不要になります。明確に記述したはずのルールが無視された場合は、文言を 4 回目に書き直すよりも、指示が反映されない理由を確認するほうが有効です。

エージェントがコードから読み取れる事実で埋まります。 ディレクトリツリー、依存関係の一覧、各パッケージの機能概要などです。Claude Code の /doctor チェックは、まさにこの内容を削除するためにあります。このチェックは「ディレクトリ構成、依存関係の一覧、アーキテクチャの概要など、Claude がコードベースから導出できる内容を削除」し、「ツールのデフォルトと異なる落とし穴、理由、規約」を残します。どの行をファイルに記載すべきか判断するうえで、この説明が最も優れた基準です。

エージェントは root のファイルを読みますか、それとも最も近いファイルだけを読みますか?

ここは多くの人がモデルを誤解する部分なので、言い換えるのではなく、上流の規約を引用する価値があります。

各パッケージ内に別の AGENTS.md を配置します。エージェントはディレクトリツリー内で最も近いファイルを自動的に読み込むため、最も近いファイルが優先され、各サブプロジェクトで固有の指示を使用できます。

競合については、次のように説明されています。

編集対象ファイルに最も近い AGENTS.md が優先されます。明示的なユーザーのチャット指示は、すべてに優先します。

「優先される」という表現から、「root のファイルは無視される」と考える人が多くいます。しかし、そうではありません。この規約を実装するツールでは、リポジトリの root から作業ディレクトリまでのパス上にあるすべてのファイルを読み込み、連結します。同じ事項について異なる指示がある場合に限り、最も近いファイルの内容が優先されます。

Codex はこの仕組みを明確に説明しています。「Codex は root から順にファイルを連結し、空行で結合します。現在のディレクトリに近いファイルが、先行する指示を上書きします」。Claude Code も、独自のファイル名について同じパスをたどります。作業ディレクトリより上位のディレクトリにあるファイルは「起動時に完全な内容が読み込まれ」、「検出されたすべてのファイルは相互に上書きされるのではなく、コンテキストに連結されます」。

作業ディレクトリより下位のディレクトリでは動作が異なります。Claude Code は、そのディレクトリ内のファイルを「Claude がそれらのディレクトリ内のファイルを読み込んだ時点」でオンデマンドに読み込みます。

ここから、実務上の重要な点が 2 つ導かれます。root のファイルはリポジトリ内のすべてのセッションに先頭部分として追加されるため、そこに書く各行は、週に 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、consumer を冪等に保つ必要がある理由、テストを通過させる前に実行する必要があるマイグレーションを記載します。infra のファイルには、agent による破壊的な操作を防ぐルールを記載します。terraform apply は絶対に実行しないでください。terraform plan だけを実行して終了し、すでに設定済みの state backend の名前も記載します。これにより、agent が新しい state backend を初期化しようとするのを防げます。

これらのファイルのどれにも、各サービスの用途の説明はありません。これは人間向けの情報です。Upstream も同じ線引きを示しており、「README.md files are for humans: quick starts, project descriptions, and contribution guidelines」とし、AGENTS.md には「the extra, sometimes detailed context coding agents need: build steps, tests, and conventions」を記載すると説明しています。AGENTS.md と人間向け README の使い分けでは、この境界を文ごとに説明しています。また、コードの構成理由を記録する DESIGN.mdでは、コマンドではなく設計上の判断を説明する3つ目のファイルを扱います。

コードが変更されたとき、誰がファイルを更新するのか

ルールは1つだけです。root ファイルに記載します。あるディレクトリ内のコードを変更した人は、同じコミットで、そのディレクトリの AGENTS.md も更新します。

これは文化的な理由ではなく、機械的な理由で機能します。ディレクトリごとのファイルはコードと同じ差分に含まれるため、pull request のレビュー担当者は両方を同時に確認できます。root ファイルは全員のものです。そのため、実質的には誰のものでもなく、誰かがすでに確認している差分に含まれることもありません。

pull request のチェックでこのルールを適用します。変更された各ファイルについて、上位にある最も近い 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")"
done
apps/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秒で終わる確認から得る情報としては、それで十分です。

現在存在しないパスを探します。 ドキュメントが劣化する具体的な形の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 のような glob や、引用した 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/`.

ツール固有の追加設定がない場合は、symlink 形式を使用します。

git ls-files '*AGENTS.md' | while read -r f; do
  ln -s AGENTS.md "$(dirname "$f")/CLAUDE.md"
done
ls -l apps/web/CLAUDE.md

ln は成功時に何も出力しないため、apps/web/CLAUDE.md -> AGENTS.md で一覧を確認します。次にセッションを開始して /context を実行すると、読み込まれたファイルが Memory files の下に表示されます。Windows では symlink の作成に Administrator 権限または Developer Mode が必要です。そのため、Windows では代わりに @AGENTS.md import を使用します。

この動作には、もう 1 つ注意点があります。/compact の後、root ファイルはディスクから再読み込みされますが、サブディレクトリ内のネストしたファイルは再注入されません。エージェントがそのディレクトリ内のファイルを次に読み取った時点で再び読み込まれます。長時間のセッション中にディレクトリ単位のルールが途中から適用されなくなったように見える場合、通常はこれが原因です。ディレクトリ内の任意のファイルに touch を実行すると、ルールが再び読み込まれます。

他のエージェントに AGENTS.md を参照させる設定

Codex は AGENTS.md をネイティブに読み取ります。各階層で最初に AGENTS.override.md を確認するため、共有ファイルを編集せずに、特定のディレクトリだけローカル設定で上書きできます。結合後のサイズが 32 KiB(デフォルトの project_doc_max_bytes)に達するとマージを停止します。そのため、root ファイルは小さく保つ必要があります。

Aider では .aider.conf.yml を通じて設定し、行 read: AGENTS.md を追加します。

Gemini CLI では .gemini/settings.json を通じて設定し、{ "context": { "fileName": "AGENTS.md" } } を指定します。

Upstream のドキュメントには、古い単数形の名前を引き続き使用しているリポジトリ向けに、後方互換性のある名前変更が記載されています: mv AGENT.md AGENTS.md && ln -s AGENTS.md AGENT.md。

非常に大規模な monorepo では、Claude Code の claudeMdExcludes 設定で、パスまたは glob によって祖先ディレクトリのファイルをスキップできます。自分のディレクトリの上位に別チームのディレクトリがある場合に便利です。

エージェントメモリや skill との違いは何ですか?

これらの仕組みは似て見えますが、失敗する理由は大きく異なります。どの仕組みを使うべきか、正確に判断することが重要です。

AGENTS.md はユーザーが作成し、git にコミットして、pull request でレビューします。リポジトリを clone する全員に対して同一です。エージェントメモリはエージェントが作成し、リポジトリの外部に保存され、1 台のマシン内でのみ利用されます。Claude Code のドキュメントでも同じ区別が示されています。CLAUDE.md にはユーザーが記述する「Instructions and rules」が含まれ、自動メモリには Claude が記述する「Learnings and patterns」が含まれます。メモリディレクトリはマシン間で共有されません。判断基準は簡単です。新しい clone を使う同僚にも真である必要がある事実は、メモリに保存できません。セッション間でエージェントメモリを保持する方法では、この仕組みの一側面を説明しています。

skill は 3 つ目の仕組みです。AGENTS.md は毎回のセッションで読み込まれるコンテキストです。一方、skill は必要になったときに読み込まれる手順です。Claude Code のドキュメントには、実用的な判断基準があります。「項目が複数の手順からなる場合、またはコードベースの一部にしか関係しない場合は、skill またはパス単位のルールに移してください」。この文の後半が、ネストした AGENTS.md で解決できる内容です。前半が エージェントの skill の用途です。同じ手順を複数のリポジトリで使う場合は、同じ段落を 10 個の AGENTS.md に貼り付けるのではなく、リポジトリ間で skill を共有するべきです。

Upstream には、「執筆時点で、OpenAI のメインリポジトリには AGENTS.md ファイルが 88 個あります」と記載されています。この数字が主張全体を示しています。大規模なリポジトリに必要なのは、より大きなファイルではありません。必要なのは、より多くの小さなファイルです。それぞれが説明対象のコードの隣に置かれ、そのコードを最後に変更した担当者が管理します。

FAQ

ネストした AGENTS.md はルートのファイルを置き換えますか、それとも追加されますか?

追加されます。Upstream の「最も近いファイルが優先される」という説明は、競合時の動作を示したものであり、読み込まれる内容を示したものではありません。Codex はルートから下へファイルを連結し、空行で区切って結合します。Claude Code も、作業ディレクトリから上へたどって見つかったすべてのファイルを連結し、上書きはしません。同じ対象について異なる指示がある場合に限り、最も近いファイルの指示が優先されます。共通ルールはルートに一度だけ記述し、各ディレクトリで繰り返さないでください。

ルートの AGENTS.md はどの程度の大きさにすべきですか?

そのリポジトリで行うすべてのリクエストの先頭に貼り付けられても気にならない程度に小さくしてください。実際にそのように処理されるためです。Claude Code のドキュメントでは、1 ファイルあたり 200 行未満を目標にすることを推奨し、長いファイルは「遵守率を下げる」と警告しています。Codex は、デフォルトでは合計 32 KiB で命令ファイルの統合を停止します。ルートファイルで 4 つのサービスを説明している場合、1 つのタスクでは大部分が不要になります。詳細をディレクトリごとのファイルへ移し、ルートには構成を示す案内だけを残してください。

これらのファイルが古くならないようにするにはどうすればよいですか?

ルートファイルに次のルールを 1 つ記述します。あるディレクトリのコードを変更した人は、同じコミットでそのディレクトリの AGENTS.md も更新する、というルールです。ファイルをコードの隣に置くと、このルールが定着しやすくなります。変更が、人間が確認する同じ pull request の差分に含まれるためです。変更された各パスを、その上位にある最も近い 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 では Administrator 権限または Developer Mode が必要です。セッションで /context を実行し、Memory files の下にファイルが表示されることを確認してください。

一時的にしか必要ないルールはどこに置けばよいですか?

AGENTS.md には置かないでください。このファイルはすべてのセッションで読み込まれるため、記述したすべての行が、実際に入力したリクエストと注意を奪い合うことになります。複数の手順から成り、必要になることがある手順は、必要なときに読み込まれる skill に置いてください。1 つのディレクトリにだけ適用されるルールは、そのディレクトリの AGENTS.md に置きます。ディレクトリツリーや依存関係一覧など、エージェントがコードから直接読み取れる事実は、どちらにも置く必要がありません。