Чому coding agents ігнорують ваші інструкції
Дізнайтеся, чому agent пропускає правило stop: воно не потрапило в context window, нечітке, суперечить коду або загубилося після compaction.
Чому coding agents ігнорують ваші інструкції
Coding agents ігнорують ваші інструкції з 4 причин, і жодна з них не полягає в тому, що ви були недостатньо наполегливими. Правило ніколи не потрапило до context window. Правило було надто нечітким, щоб зіставити з ним певну дію. Щось інше в context суперечило цьому правилу — зазвичай код, який agent щойно прочитав. Або правило все ще завантажене, але розташоване далеко позаду в поточному turn, тому agent працює з тим, що міститься ближче.
Для кожної причини є окреме виправлення, тому спочатку потрібно розрізнити їх. Великі літери та слово IMPORTANT не допоможуть встановити причину. Нижче описано механіку на прикладі Claude Code, оскільки станом на August 2026 його поведінку під час завантаження та compaction детально задокументовано. Інші інструменти відрізняються в деталях, але загалом працюють так само.
Спочатку визначимо 2 терміни. Context window — це блок тексту, який model бачить у певному turn: system prompt, ваші instruction files, conversation і кожен файл, який прочитав agent. Harness — це програма навколо model, тобто компонент, який читає файли з диска та формує цей блок. Майже кожна скарга в цій статті насправді стосується harness, а не model.
Файл інструкцій — це повідомлення, а не налаштування
Файл інструкцій не є конфігурацією. Середовище виконання не зчитує CLAUDE.md і не забезпечує його дотримання. Harness зчитує файл із диска та вставляє його текст у розмову. У Claude Code цей вміст надходить як повідомлення користувача після системного промпту. Отже, модель бачить ваші правила так само, як і будь-який інший введений вами текст.
Це має неприємний наслідок. Ваші правила конкурують з усіма іншими фрагментами тексту у вікні на рівних умовах. Правило є твердженням. Файл, який агент щойно відкрив, є доказом. Коли вони суперечать одне одному, доказ часто перемагає, і жодної помилки не виникає, оскільки з погляду моделі нічого не пішло не так.
В офіційній документації це сказано прямо: файли інструкцій розглядаються як контекст, а не як конфігурація, виконання якої забезпечується. Щоб заблокувати дію незалежно від рішення моделі, потрібен hook, а не речення. Запам’ятайте цей принцип. Більшість виправлень наприкінці цього допису є застосуванням цього принципу до конкретного випадку.
Які файли інструкцій завантажуються і коли
Claude Code піднімається вгору деревом каталогів від каталогу, у якому його запустили. Усі CLAUDE.md і CLAUDE.local.md від кореня файлової системи до робочого каталогу повністю завантажуються під час запуску. Їх об’єднано в цьому порядку, тому файл, розташований найближче до каталогу запуску, читається останнім. У межах одного каталогу файл .local додається після основного файла.
Файли в підкаталогах нижче робочого каталогу працюють інакше. Вони не завантажуються під час запуску. Вони завантажуються, коли агент читає файл у відповідному каталозі. Те саме стосується правил з обмеженням за шляхом у .claude/rules/, які містять поле frontmatter paths:: вони потрапляють у контекст, коли читається відповідний файл, а не під час кожного запиту.
Саме ця відмінність пояснює значну частину повідомлень про збої. Ви додаєте правило у packages/api/CLAUDE.md, ставите запитання про API, а агент відповідає, жодного разу не відкривши файл у packages/api/. Правило не було проігнороване. Воно взагалі не було присутнє в контексті. Якщо у вашому репозиторії вказівки розподілено між файлами інструкцій для кожного пакета в monorepo, це потрібно перевіряти насамперед і щоразу.
Є ще одна проблема із завантаженням. Це найпоширеніший варіант ситуації, коли «агент проігнорував мої інструкції»: Claude Code читає CLAUDE.md, а не AGENTS.md. Якщо в репозиторії стандартизовано AGENTS.md і немає CLAUDE.md, Claude Code взагалі не має чого завантажувати. Підтримуваний спосіб сумісності — це CLAUDE.md, перший рядок якого містить @AGENTS.md. Він імпортує файл під час запуску, а нижче можна додати специфічні для Claude примітки. Символічне посилання також працює, якщо більше нічого додавати не потрібно. Визначення того, що саме має міститися в цьому файлі, — окреме питання, розглянуте в розділі про розділення інструкцій для агента та документації для людей.
Підтвердьте завантаження файлу, перш ніж переписувати його
Не змінюйте формулювання, доки не переконаєтеся, що агент бачить файл. Є дві перевірки. Спочатку виконайте простішу.
Виконайте /context у сесії. Команда виводить поточне вікно з розподілом за категоріями, а список Memory files містить назви всіх файлів інструкцій, які фактично завантажено. Файл, якого немає в цьому списку, не входить до розмови, тому його вміст не вплине на результат. /memory показує розташування файлів і відкриває їх для редагування, зокрема файлів, яких ще не існує.
Для детальнішої перевірки записуйте завантаження в журнал. Подія-перехоплювач InstructionsLoaded спрацьовує щоразу, коли в контекст додається CLAUDE.md або файл правил, а її matcher показує причину завантаження: session_start, nested_traversal, path_glob_match, include або compact. Додайте це до .claude/settings.json:
{
"hooks": {
"InstructionsLoaded": [
{
"matcher": "nested_traversal",
"hooks": [
{
"type": "command",
"command": "cat >> /tmp/instructions-loaded.log"
}
]
}
]
}
}Перехоплювач отримує дані у форматі JSON через стандартний ввід, тому cat додає весь запис. Переглядайте журнал за допомогою tail -f /tmp/instructions-loaded.log під час роботи. Статус завершення цієї події ігнорується, тому перехоплювач може лише спостерігати й не може блокувати виконання. Якщо вкладений файл не з’являється в цьому журналі під час сесії, у якій ви очікували його завантаження, припиніть переписування. Проблема полягає в розташуванні файлу.
Як тривалий сеанс впливає на ваші правила
Тут діють два окремі ефекти, і для них потрібні різні підходи.
Віддаленість. Правило, сформульоване на 1-му ході, все ще перебуває у вікні на 90-му ході, але тепер конкурує з 90 ходами тексту, який є новішим і більше стосується поточної роботи. Це неможливо усунути конфігурацією, але можна виміряти. Виконайте те саме завдання в новому сеансі. Якщо там правило працює, а глибоко в тривалому сеансі перестає працювати, причина полягає у віддаленості.
Компактизація. Коли вікно заповнюється, harness узагальнює попередню розмову й продовжує роботу з цього резюме. Зберігається те, що summariser визнав важливим, а це не обов’язково збігається з тим, що вважаєте важливим ви. Claude Code описує результат для кожного механізму, і відмінності значні. Project root CLAUDE.md і правила без області дії повторно завантажуються з диска після компактизації. Auto memory повторно завантажується з диска. Правила з frontmatter paths: втрачаються, доки знову не буде прочитано відповідний файл. Вкладені файли CLAUDE.md у підкаталогах втрачаються, доки знову не буде прочитано файл у цьому підкаталозі.
Розташуйте свої інструкції за цією таблицею, і порядок їхньої нестійкості стане очевидним. Правило, яке ви лише ввели в чаті, є найменш надійним у сеансі: воно зберігається лише в тому разі, якщо резюме випадково його містить. Далі йде правило у packages/api/CLAUDE.md, оскільки його було завантажено один раз, потім вилучено під час узагальнення, і воно повернеться лише під час наступного читання в цьому каталозі. Правило у файлі project root є найнадійнішим, оскільки щоразу повторно читається з диска.
Тому інструкція, яка має діяти протягом усього сеансу, повинна міститися у файлі project root без frontmatter paths:. Усе інше є компромісом, який слід обирати свідомо. У матеріалі Керування тим, що залишається у вікні контексту розглянуто /compact за допомогою аргументу focus і /clear між непов’язаними завданнями. Обидва чинники впливають на те, як часто summariser визначає, які саме ваші правила збереглися.
Чому оточувальний код переважає правило
Це помилка, про яку найчастіше повідомляють і найрідше правильно діагностують. У вашому файлі зазначено, що доступ до бази даних має виконуватися через шар репозиторію. Агент створює обробник, який безпосередньо викликає ORM (object relational mapper). Вас проігнорували не через стиль. Вас переважили наявні приклади.
Правило описує перевагу. Код демонструє одну з них. Коли агент відкриває три файли в модулі, який збирається редагувати, і в усіх трьох безпосередньо викликається ORM, контекст містить одне абстрактне речення з одного боку та три конкретні, нещодавні приклади, що відповідають завданню, — з іншого. Зазвичай копіювати локальний шаблон є правильною поведінкою. У цьому випадку це неправильно лише тому, що ви знаєте те, чого не знає контекст: ці файли є legacy-кодом.
Тому явно запишіть це в правилі. Правила, які називають власні суперечливі приклади, витримують перевірку реальним репозиторієм. Правила, що містять лише загальну перевагу, — ні.
Новий доступ до бази даних має виконуватися черезapp/repositories/. У файлах підapp/legacy/досі викликається ORM безпосередньо. Це старий код, а не шаблон. Не копіюйте його.
Основну роботу виконує друге речення. Воно повідомляє агенту, що саме він побачить і як це інтерпретувати, ще до того, як агент це побачить. Такий самий підхід застосовується до будь-якого правила, якому репозиторій явно суперечить: стилю комітів, якого не дотримується історія, структури тестів, яку ігнорує половина набору тестів, або правила імпортів, що діє лише в новому коді. Якщо код суперечить файлу, вкажіть цю суперечність у самому файлі.
Розпливчасте правило не можна перевірити, тому його неможливо виконати
"Пишіть чистий код." "Не ускладнюйте." "Зберігайте простоту." "Будьте обережні з міграціями." Жодне з цих правил не можна перевірити за конкретною дією — ні агентом, ні вами. Агент, якому дали правило, яке він не може перевірити за власним результатом, вгадує, а ви оцінюєте це вгадування на око.
Застосовуйте до кожного рядка у файлі таку перевірку. Напишіть shell-команду, яка завершуватиметься з ненульовим кодом, якщо правило порушено. Якщо ви не можете написати таку команду, правило не є перевірюваним. Порівняйте ці пари:
- Неперевірюване: "Тримайте функції малими." Перевірюване: "Функція довша за 60 рядків має містити над нею коментар із поясненням причини."
- Неперевірюване: "Тестуйте зміни." Перевірюване: "Виконайте
npm testі вставте кількість помилок перед тим, як позначити завдання виконаним." - Неперевірюване: "Підтримуйте впорядкованість файлів." Перевірюване: "HTTP-обробники розташовані в
src/api/handlers/. В інших місцях цього каталогу нічого немає." - Неперевірюване: "Правильно форматуйте код." Перевірюване: "У файлах
.tsвикористовуйте відступ у 2 пробіли."
"Не ускладнюйте" — це правило люди здаються уточнювати найчастіше, оскільки виправлення полягає не в коротшому реченні, а в довшому: чітке визначення того, що саме означає найменша працездатна зміна дає агенту критерії, з якими він може порівняти власний diff.
Розмір створює ту саму проблему під іншим виглядом. Рекомендації Claude Code передбачають менше ніж 200 рядків у файлі інструкцій і прямо зазначають, що довші файли знижують дотримання інструкцій. Файл на 700 рядків не містить чіткіших інструкцій. Це 700 тверджень, які мають більше шансів суперечити одне одному, і вони враховуються у вашому контекстному вікні під час кожного запиту, що безпосередньо відображається у використанні токенів. Структурування файлу так, щоб кожне правило містилося під заголовком, який читач може швидко переглянути, описано в матеріалі як написати файл інструкцій, з яким агент може працювати. Ще краще — вилучіть частини, які описують, а не дають інструкцій: огляд каталогів із розташуванням обробників і моделей — це структура, яку агент може за потреби отримати з розібраної карти репозиторію, замість того щоб зберігати її в контекстному вікні під час кожного запиту.
Як діагностувати проблему за десять хвилин
Виконайте ці дії по черзі. Якщо одразу перейти до останнього кроку, можна отримати довгий файл із правилами, написаними великими літерами, який усе одно не працюватиме.
- Переконайтеся, що правило завантажено. Виконайте
/contextі перегляньте список Memory files. Якщо файла немає, виправте його розташування та зупиніться. Інші дії з цього списку поки що не застосовуються. - Відтворіть проблему в новій сесії. Запустіть нову сесію та поставте найпростішу задачу, яка має активувати правило. Якщо в новій сесії правило працює, але не працює в довгій, проблема, ймовірно, пов’язана з віддаленням або compaction. Якщо правило не працює і в новій сесії, проблема в самому правилі.
- Усуньте конкуренцію. Попросіть внести ту саму зміну в каталозі, наявний код якого вже відповідає правилу. Якщо відповідність відновиться, навколишній код переважав ваше формулювання.
- Знайдіть конфлікт. Два файли з різними вказівками щодо тієї самої поведінки — це задокументована причина збою: модель може довільно вибрати один із них і не повідомить про це.
- Зробіть правило перевірюваним і повторіть тест. Перепишіть правило, додавши конкретний шлях і умову. Значне підвищення відповідності означає, що причиною було формулювання.
Крок 4 — це одна команда. Виконайте пошук у всіх джерелах інструкцій за потрібною темою, а не лише у файлі, який ви редагували:
grep -rni "migration" --include="CLAUDE.md" --include="CLAUDE.local.md" .
grep -rni "migration" .claude/rules/ ~/.claude/CLAUDE.md ~/.claude/rules/ 2>/dev/nullЗбіги у двох файлах, які містять різні вказівки, — це ваша помилка. Видаліть один із них. Не намагайтеся визначити пріоритет за допомогою сильнішого формулювання, оскільки механізму пріоритезації, на який можна було б послатися, немає.
Виправлення в порядку зростання ефективності
Кожен наведений нижче крок має більший вплив, ніж попередній, і потребує більше зусиль для налаштування. Починайте зверху, коли правило можна недорого переформулювати. Переходьте нижче, щойно правило стає настільки важливим, що періодичні пропуски є неприйнятними.
- Сформулюйте правило конкретно. Назвіть шлях, команду або умову. Додайте контраргумент, який агент знайде в репозиторії, як показано вище. Це нічого не коштує та виправляє несподівано велику кількість випадків.
- Розмістіть правило ближче до об’єкта, якого воно стосується. Використайте вкладений
CLAUDE.md, правило з областю дії для шляху у.claude/rules/або коментар на початку самого файлу. Тоді правило завантажується під час того самого читання, що й код, якого воно стосується. Прийміть компроміс: усе, що завантажується таким способом, зникає під час наступної компактизації контексту та повертається під час наступного відповідного читання. - Перенесіть enforcement у hook. Текстове правило лише просить. Hook приймає рішення. Hooks запускаються як код у визначені моменти життєвого циклу та застосовуються незалежно від висновку моделі.
- Передайте правило детермінованому інструменту та видаліть текстове правило. Форматування, порядок імпортів, довжина рядків, заборонені імпорти, формат повідомлення коміту.
ruff format,prettier --write,eslint, hookpre-commit. Formatter завжди працює правильно й не витрачає токенів. Речення працює правильно здебільшого та витрачає токени під час кожного ходу.
Крок 3 повністю. Припустімо, що агенту заборонено редагувати migration files. Додайте це до .claude/settings.json:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/guard-migrations.sh"
}
]
}
]
}
}А це — до .claude/hooks/guard-migrations.sh:
#!/usr/bin/env bash
set -euo pipefail
path=$(jq -r '.tool_input.file_path // empty')
case "$path" in
*/migrations/*)
echo "Files under migrations/ are written by hand. Stop and ask first." >&2
exit 2
;;
esac
exit 0Запустіть chmod +x .claude/hooks/guard-migrations.sh, потім почніть нову сесію та попросіть агента відредагувати файл у migrations/. Редагування буде відхилено, а ваше повідомлення повернеться як причина. Код завершення 2 у PreToolUse блокує виклик інструмента до його запуску, а текст зі stderr передається моделі як повідомлення про блокування. ${CLAUDE_PROJECT_DIR} розгортається в кореневий каталог проєкту, тому hook працює незалежно від каталогу, у якому перебуває агент. Агенту не потрібно погоджуватися з правилом, пам’ятати його або все ще мати це правило в контексті. Редагування не відбувається.
Для простої заборони без логіки permissions.deny у settings виконує ту саму функцію без скрипту, який потрібно підтримувати, а режими дозволів визначають, що запускається без попереднього запиту до вас. Якщо інструкція справді має перебувати на рівні system prompt, а не в user message, --append-system-prompt розміщує її там, хоча її потрібно передавати під час кожного запуску. Це краще підходить для скриптів, ніж для інтерактивної роботи.
Що неможливо забезпечити самими інструкціями
Чітко визначте, яка частина проблеми залежить від вас. Розміщення, формулювання, конфлікти між файлами та розмір файлу є проблемами автора, які має вирішувати автор. Решта залежить від поведінки моделі, і кращі формулювання цього не усунуть.
Згода не означає дотримання. Агент підтвердить правило, правильно повторить його та порушить через два виклики інструментів. Таке підтвердження нічого не коштує й нічого не прогнозує. Не сприймайте його як виправлення та не зараховуйте як тест.
Деякі звички зберігаються. Додавання коментарів, додавання захисної обробки помилок, написання підсумку наприкінці, виконання очевидної наступної команди. Вони знову проявляються навіть за наявності правила, яке їх забороняє, але з меншою, а не нульовою частотою. Ви можете виміряти власну частоту: виконайте те саме завдання 10 разів у нових сеансах і порахуйте порушення. Якщо це число має дорівнювати нулю, правило потрібно прибрати з prompt. Передчасне оголошення завдання завершеним, коли частина роботи ще не виконана, має ту саму природу звички. Виправлення має бути структурним, а не словесним: skill unlazy замінює речення на Depth Tree і gate files, які агент має пройти, перш ніж може оголосити завдання завершеним.
Ваш власний сеанс стає прикладом. Якщо агент порушив правило на 12-му ході, а ви це пропустили, порушення залишається в контексті як приклад і є значно новішим за саме правило. Виправляйте порушення одразу після його виявлення. Невиправлене порушення навчає решту сеансу.
Файл інструкцій не є межею безпеки. Він формує поведінку, але не забезпечує її дотримання. Усе, де помилка має високу ціну, зокрема облікові дані або деструктивні команди, потрібно захищати за допомогою permissions або hook. Тримайте секрети поза межами доступу агента застосовує той самий принцип до даних: не просіть агента не читати файл, зробіть так, щоб файл не можна було прочитати.
Коротко: доведіть, що файл завантажено, зробіть правило перевірюваним, розмістіть його поруч з об’єктом, якого воно стосується, а якщо частота помилок усе ще має значення, приберіть це правило з prose. Правило, яке агент не може проігнорувати, ніколи не було лише проханням до агента.
FAQ
Чому Claude Code ігнорує мій CLAUDE.md?
Спочатку перевірте, чи файл завантажено. Виконайте /context і перегляньте список Memory files; якщо файл не зазначено в ньому, його немає в поточному діалозі. Файли інструкцій передаються як повідомлення користувача після системного промпту й розглядаються як контекст, а не як примусова конфігурація, тому суворе дотримання не гарантується. У більшості реальних випадків причина одна з чотирьох: файл розташований у підкаталозі, з якого агент не читав дані; два файли містять суперечливі вказівки, і модель випадково обрала одну з них; правило надто нечітке, щоб зіставити його з конкретною дією; або навколишній код демонструє протилежне тому, що вимагає правило.
Чи змінює щось редагування файлу інструкцій під час сесії?
Не для копії, яка вже перебуває в поточному діалозі. Файли над вашим робочим каталогом повністю завантажуються під час запуску, тому модель зберігає версію тексту, наявну в момент запуску. Щоб завантажити зміни, почніть нову сесію або попросіть агента прочитати файл за допомогою його стандартних файлових інструментів. У такому разі поточна версія буде додана до діалогу як нове повідомлення. Після compaction файл у корені проєкту повторно читається з диска, тому нова версія також завантажується в цей момент.
Який файл має пріоритет, якщо кореневий CLAUDE.md і вкладений файл містять суперечливі вказівки?
Надійного пріоритету немає. Виявлені файли об’єднуються в контекст, а не перевизначають один одного. Їх упорядковано від кореня файлової системи до робочого каталогу, тому найближчий файл просто читається останнім. Механізму пріоритетів для розв’язання суперечностей немає. У документації Claude Code зазначено, що суперечливі правила можуть розв’язуватися довільно. Створюйте вкладені файли як доповнення й зазначайте шлях, до якого вони застосовуються. Не намагайтеся встановити пріоритет правилам — усувайте суперечність.
Чи зберігаються мої інструкції після /compact?
Це залежить від способу їх завантаження. Файл у корені проєкту CLAUDE.md, правила без області застосування та автоматична пам’ять повторно додаються з диска після compaction. Правила з frontmatter paths: і вкладені файли CLAUDE.md у підкаталогах втрачаються, доки відповідний файл не буде прочитано знову. Те, що ви ввели лише в чаті, зберігається тільки в разі, якщо summariser включив це до результату. Якщо правило має діяти протягом усієї сесії, розмістіть його у файлі в корені проєкту без frontmatter paths:.
Коли правило слід реалізувати як hook, а не описати текстом?
Коли перевірка є детермінованою, а вартість пропуску вища за вартість написання невеликого скрипту. До таких випадків належать обмеження шляхів до файлів, обов’язкові команди перед commit і заборонені виклики інструментів. Hook PreToolUse, який завершується зі статусом 2, повністю блокує виклик інструмента й передає текст stderr моделі як пояснення. Тому правило діє незалежно від того, чи залишається воно в контексті. Усе, що може визначити formatter або linter, має контролюватися відповідним інструментом. Такі правила слід повністю видалити з файлу інструкцій.