Вкладені AGENTS.md для монорепозиторію
Дізнайтеся, як розподілити правила між кореневим і сервісними AGENTS.md, щоб не витрачати контекст агента на каталоги, яких він не відкриває.
Що означає вкладений AGENTS.md у монорепозиторії
Вкладений AGENTS.md у монорепозиторії означає, що один невеликий файл розміщено в корені репозиторію, а ще по одному файлу — у каталозі кожного сервісу. У кореневому файлі містяться кілька правил, чинних у всьому репозиторії, а також карта розташування інших файлів. У файлі кожного сервісу містяться команди та правила, що стосуються лише цього каталогу. Агент, який редагує services/worker/queue.py, читає кореневий файл і файл worker-сервісу та не витрачає контекст на front end, якого він не змінюватиме.
Нічого встановлювати не потрібно. AGENTS.md — це домовленість, і upstream-проєкт прямо це зазначає:
AGENTS.md — це звичайний Markdown. Використовуйте будь-які потрібні заголовки; агент просто аналізує наданий вами текст.
Саме тому цю техніку варто опанувати належним чином. Формат не зміниться без вашого відома. Проблеми виникають через розташування та супровід файлів, і за обидва аспекти відповідаєте ви.
Чому один великий кореневий AGENTS.md перестає працювати?
Один AGENTS.md на 600 рядків у корені репозиторію, що містить web app, background worker і каталог Terraform, має чотири окремі проблеми.
Він застаріває, бо ніхто за нього не відповідає. Інженер, який перейменовує тестовий скрипт у apps/web, редагує файли в apps/web. Кореневий AGENTS.md не входить до цього diff, тому жоден reviewer не бачить невідповідність. Через шість тижнів файл описує крок build, якого вже не існує, а людина, яка його зламала, уже забула про цю зміну.
Він витрачає context на кожне завдання. Ці файли завантажуються на початку сесії, ще до того, як agent дізнається, що саме ви попросите. У документації Claude Code наведено конкретну рекомендацію: «для кожного файла CLAUDE.md рекомендується менше 200 рядків. Довші файли споживають більше context і знижують дотримання інструкцій». Codex припиняє об’єднувати файли інструкцій, коли їхній сукупний розмір досягає 32 KiB, що є типовим значенням project_doc_max_bytes. Кореневий файл, який документує чотири сервіси, витрачає цей ліміт на три з них під час кожного завдання.
Інструкції починають суперечити одна одній. Web directory потребує pnpm test. Worker потребує pytest -q. В одному файлі кожне правило правильне лише в окремих випадках, тому agent має вгадувати, яке з них застосовується. У документації Claude Code описано результат: «якщо два правила суперечать одне одному, Claude може довільно вибрати одне з них». Файл для окремого каталогу усуває цю невизначеність, оскільки в context завжди потрапляє лише одне з двох правил.
Він заповнюється фактами, які agent може прочитати з коду. Дерево каталогів, список залежностей, короткий опис призначення кожного пакета. Перевірка /doctor у Claude Code призначена саме для видалення такого вмісту. Вона «видаляє відомості, які Claude може отримати з codebase, наприклад структуру каталогів, списки залежностей і огляди архітектури», та залишає «потенційні проблеми, обґрунтування і правила, що відрізняються від типових параметрів інструментів». Це найкращий відомий мені критерій для визначення, чи має конкретний рядок узагалі бути у файлі.
Агент читає кореневий файл чи лише найближчий?
Саме тут більшість людей неправильно розуміє модель, тому варто процитувати висхідну конвенцію, а не переказувати її:
Розмістіть ще один AGENTS.md у кожному пакеті. Агенти автоматично читають найближчий файл у дереві каталогів, тому найближчий файл має вищий пріоритет, а кожен підпроєкт може містити власні спеціальні інструкції.
Щодо конфліктів:
Найближчий до редагованого файлу AGENTS.md має вищий пріоритет; явні запити користувача в чаті мають пріоритет над усім іншим.
Формулювання «має вищий пріоритет» багато хто розуміє як «кореневий файл ігнорується». Це не так. У засобах, що реалізують цю конвенцію, читаються всі файли на шляху від кореня репозиторію до робочого каталогу, після чого їхній вміст об’єднується. Найближчий файл має вищий пріоритет лише тоді, коли два файли містять різні вказівки щодо одного питання.
Codex чітко описує цей механізм: «Codex об’єднує файли від кореня вниз, розділяючи їх порожніми рядками. Файли, розташовані ближче до поточного каталогу, замінюють попередні вказівки». Claude Code проходить тим самим шляхом для власного імені файлу. Файли в ієрархії каталогів вище за робочий каталог «повністю завантажуються під час запуску», а «всі знайдені файли додаються до контексту, а не замінюють один одного». Каталоги нижче за робочий каталог працюють інакше: Claude Code завантажує такі файли на вимогу, «коли Claude читає файли в цих каталогах».
З цього випливають два практичні наслідки. Кореневий файл є префіксом кожного сеансу в репозиторії, тому сприймайте кожен його рядок як рядок, за який ви платите сто разів на тиждень. Файл для окремого каталогу не створює витрат, коли агент працює в іншому місці. Отже, детальні вказівки краще розміщувати саме там.
Цю поведінку перевірено за документацією Codex і Claude Code у серпні 2026 року. Засоби реалізують конвенцію дещо по-різному, і їхня поведінка змінюється, тому перевірте правила завантаження для агента, який використовується у вашій команді.
Практична структура репозиторію з трьома сервісами
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 зазначають правила, які не дають агенту виконувати небезпечні дії. Ніколи не запускайте terraform apply. Запустіть terraform plan і на цьому зупиніться. Також вкажіть уже налаштований 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, у якому зафіксовано причини структури коду присвячено третьому файлу — тому, що пояснює рішення, а не команди.
Хто оновлює файл, коли змінюється код?
Одне правило, яке потрібно додати до кореневого файлу: той, хто змінює код у каталозі, оновлює AGENTS.md цього каталогу в тому самому коміті.
Це працює з механічної, а не культурної причини. Файл для окремого каталогу міститься в тому самому diff, що й код, тому рев’юер pull request бачить їх одночасно. Кореневий файл належить усім, а отже — нікому, і він ніколи не входить до diff, який хтось уже переглядає.
Підкріпіть це правило перевіркою в 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, який застарів?
Сьогодні можна виконати дві перевірки та побачити одну ознаку безпосередньо в межах сесії.
Порівняйте дату кожного файлу з датою коду, який він описує. %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Документ, дата якого на шість місяців старіша за дату коду, не обов’язково неправильний. Це лише показує, який файл слід прочитати першим. Для перевірки, що триває одну секунду, цього достатньо.
Шукайте шляхи, яких більше не існує. Документація застаріває в один конкретний спосіб: вона продовжує описувати видалений код. У цих файлах кожен шлях записано в зворотних апострофах, тому їх легко вилучити та перевірити.
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. Вона також позначає glob-шаблони, як-от src/**/*.ts, і будь-які URL, записані в лапках, оскільки і ті, і ті містять скісну риску, але не є файлами на диску.
Ознака в межах сесії. Агент читає файл, намагається відкрити src/api/client.ts, оскільки файл вказує йому це зробити, а інструмент повертає:
No such file or directoryТому агент робить логічний висновок і створює власну обгортку fetch. У цьому полягає реальна ціна застарілого файлу. Агент не ігнорує вашу документацію. Він дотримується її, переходить до шляху, який видалили три місяці тому, і повторно створює код, який у вас уже є. Навичка на кшталт Ponytail, яка змушує агента вносити найменшу працездатну зміну, зменшує ймовірність такого повторного створення, але не може знайти допоміжний компонент, якщо файл вказує неправильний шлях до нього.
Чи читає Claude Code файли AGENTS.md?
Ні. Це важливо зазначити, оскільки від цього залежить вкладена структура. Станом на August 2026 документація стверджує: «Claude Code читає CLAUDE.md, а не AGENTS.md». Схема все одно працює, але поруч із кожним AGENTS.md потрібно розмістити CLAUDE.md.
Форма імпорту підходить, якщо потрібно додати специфічні для інструмента рядки до спільних. Додайте це до 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.mdln нічого не виводить у разі успіху, тому перевірте вміст каталогу: apps/web/CLAUDE.md -> AGENTS.md. Потім запустіть сесію і виконайте /context. Завантажені файли з’являться в розділі Memory files. У Windows для створення symlink потрібні права Administrator або Developer Mode, тому замість цього використовуйте імпорт @AGENTS.md.
Є ще один важливий нюанс. Після /compact кореневий файл повторно читається з диска, але вкладені файли в підкаталогах не завантажуються повторно. Вони знову завантажуються наступного разу, коли агент читає файл у відповідному каталозі. Якщо правило для окремого каталогу перестає застосовуватися під час тривалої сесії, зазвичай причина саме в цьому. Щоб завантажити його знову, достатньо змінити будь-який файл у каталозі.
Налаштування, які вказують іншим агентам на AGENTS.md
Codex підтримує AGENTS.md безпосередньо. На кожному рівні він спочатку перевіряє AGENTS.override.md. Це дає змогу задати локальне перевизначення для одного каталогу без редагування спільного файла. Злиття припиняється, коли загальний розмір досягає 32 KiB — значення за замовчуванням для project_doc_max_bytes. Це ще одна причина зберігати кореневий файл невеликим.
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 налаштування claudeMdExcludes у Claude Code пропускає файли предків за шляхом або glob-шаблоном. Це корисно, коли каталог іншої команди розташований вище за ваш.
Чим це відрізняється від пам’яті агента або skill?
Ці механізми виглядають подібними, але дають збій із зовсім різних причин. Тому важливо точно визначити, який саме механізм вам потрібен.
AGENTS.md створюєте ви, додаєте до git і переглядаєте в pull request. Його вміст однаковий для всіх, хто клонує репозиторій. Пам’ять агента створює агент, зберігає її за межами репозиторію, і вона доступна лише на одній машині. Документація Claude Code проводить таку саму межу: CLAUDE.md містить «Інструкції та правила», які пишете ви, а автоматична пам’ять містить «Висновки та шаблони», які записує Claude; каталог пам’яті не спільний для різних машин. Перевірка проста. Якщо факт має бути чинним для колеги, який щойно клонував репозиторій, його не можна зберігати в пам’яті. У розділі Як пам’ять агента зберігається між сеансами розглянуто цю частину питання.
Skill — це третій механізм. Контекст із AGENTS.md завантажується під час кожного сеансу, а skill завантажується, коли він потрібен. У документації Claude Code наведено практичне правило: «Якщо запис містить багатоетапну процедуру або стосується лише однієї частини кодової бази, перенесіть його до skill або правила з обмеженою областю дії». Друга частина цього речення — саме те, для чого призначений вкладений AGENTS.md. Перша частина — те, для чого призначені skill агента, а коли ту саму процедуру потрібно використовувати в кількох репозиторіях, краще поширити skill між репозиторіями, ніж вставляти однакові абзаци в десять різних файлів AGENTS.md.
В upstream зазначено: «на момент написання основний репозиторій OpenAI має 88 файлів AGENTS.md». Це число повністю підтверджує наведений аргумент. Великому репозиторію не потрібен більший файл. Йому потрібно більше невеликих файлів, кожен із яких розташований поруч із кодом, який описує, і належить тому, хто востаннє змінював цей код.
FAQ
Чи замінює вкладений AGENTS.md кореневий файл, чи доповнює його?
Він доповнює його. В upstream сказано, що «найближчий файл має пріоритет». Це описує поведінку в разі конфлікту, а не те, які файли завантажуються. Codex «об’єднує файли від кореня вниз, розділяючи їх порожніми рядками», а Claude Code об’єднує всі знайдені файли, піднімаючись від робочого каталогу вгору, а не замінює їх. Найближчий файл має пріоритет лише тоді, коли два файли містять різні вказівки щодо одного питання. Запишіть спільні правила один раз у кореневому файлі й не дублюйте їх у кожному каталозі.
Яким має бути розмір кореневого AGENTS.md?
Він має бути достатньо малим, щоб ви не заперечували проти його додавання на початок кожного запиту в цьому репозиторії, оскільки саме це відбувається. Документація Claude Code радить обмежувати кожен файл 200 рядками та попереджає, що довші файли «знижують дотримання правил». Codex припиняє об’єднувати файли з інструкціями, коли їхній загальний розмір за замовчуванням досягає 32 KiB. Якщо кореневий файл документує чотири сервіси, більшість його вмісту не потрібна для окремого завдання. Перенесіть докладні відомості до файлів у відповідних каталогах, а в кореневому залиште карту.
Як не допустити застарівання цих файлів?
Додайте до кореневого файлу правило: той, хто змінює код у каталозі, оновлює AGENTS.md цього каталогу в тому самому коміті. Розміщення файлу поруч із кодом допомагає дотримуватися цього правила, оскільки зміна потрапляє до того самого pull request diff, який уже переглядає людина. Додайте в CI попередження, яке зіставляє кожен змінений шлях із найближчим AGENTS.md вище за ієрархією, і час від часу порівнюйте git log -1 --format=%cs для кожного файлу з результатом тієї самої команди, виконаної для каталогу, який він документує.
Чи читає Claude Code файли AGENTS.md?
Ні. Станом на August 2026 у документації зазначено: «Claude Code читає CLAUDE.md, а не AGENTS.md». Створіть CLAUDE.md у тому самому каталозі, а в першому рядку вкажіть @AGENTS.md. Це завантажить спільний файл і дасть змогу додати нижче інструкції, специфічні для Claude. Символічне посилання, створене за допомогою ln -s AGENTS.md CLAUDE.md, працює, якщо додаткових інструкцій немає, але у Windows для цього потрібні права Administrator або Developer Mode. Виконайте /context у сеансі й переконайтеся, що файл відображається в розділі Memory files.
Куди додати правило, яке потрібне лише іноді?
Не в AGENTS.md. Цей файл завантажується в кожному сеансі, тому кожен його рядок конкурує за увагу із запитом, який ви фактично ввели. Процедура з кількома кроками, потрібна лише час від часу, належить до skill, який завантажується на вимогу. Правило, що застосовується до одного каталогу, належить до AGENTS.md у цьому каталозі. Факт, який агент може безпосередньо прочитати з коду, наприклад дерево каталогів або список залежностей, не потрібно розміщувати ніде.