Чому coding agents ігнорують ваші інструкції
Інструкція каже зупинитися, але coding agent продовжує. Розберіться з чотирма причинами та проведіть діагностику до повторного переписування правила.
Чому coding agents ігнорують ваші інструкції
Coding agents ігнорують ваші інструкції з чотирьох причин, і жодна з них не полягає в тому, що ви були недостатньо ввічливі. Правило ніколи не потрапило до context window. Правило було надто нечітким, щоб зіставити з ним певну дію. Щось інше в контексті суперечило цьому правилу — зазвичай код, який агент щойно прочитав. Або правило все ще завантажене, але розташоване далеко від поточного запиту, тому агент працює з тим, що міститься поруч.
Для кожної причини потрібне окреме виправлення, тому спочатку їх потрібно розрізнити. Великі літери та слово IMPORTANT не допоможуть встановити причину. Нижче механіку розглянуто на прикладі Claude Code, оскільки станом на August 2026 його поведінку під час завантаження та compaction докладно задокументовано. Інші інструменти мають інші деталі, але загалом працюють так само.
Спочатку визначимо два терміни. Context window — це блок тексту, який модель бачить у певному запиті: system prompt, ваші файли інструкцій, розмову та кожен файл, який прочитав агент. Harness — це програма навколо моделі, яка зчитує файли з диска та формує цей блок. Майже кожна скарга в цій статті насправді стосується harness, а не моделі.
Файл інструкцій — це повідомлення, а не налаштування
Файл інструкцій не є конфігурацією. Під час виконання нічого не читає 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 виводить розташування файлів і відкриває їх для редагування, зокрема файли, яких ще не існує.
Для точнішої перевірки журналюйте завантаження. Подія hook 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"
}
]
}
]
}
}hook отримує дані у форматі JSON через стандартне введення, тому cat додає весь запис. Переглядайте журнал за допомогою tail -f /tmp/instructions-loaded.log під час роботи. Статус завершення цієї події ігнорується, тому hook може лише спостерігати й не може блокувати виконання. Якщо вкладений файл не з’являється в цьому журналі під час сесії, у якій він мав завантажитися, припиніть змінювати формулювання. Проблема полягає в розташуванні.
Як тривала сесія впливає на ваші правила
Тут діють два окремі ефекти, і кожен потребує іншого підходу.
Віддаленість. Правило, задане на ході 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, у контексті з одного боку є одне абстрактне речення, а з іншого — три конкретні, нещодавні приклади, що відповідають завданню. Копіювати локальний шаблон зазвичай правильно. У цьому випадку це помилка лише тому, що ви знаєте те, чого не знає контекст: ці файли містять застарілий код.
Тому явно вкажіть це в правилі. Правила, які називають власні контраргументи з коду, витримують перевірку реальним репозиторієм. Правила, що містять лише необґрунтовану перевагу, — ні.
Новий доступ до бази даних має проходити черезapp/repositories/. У файлах підapp/legacy/досі виконуються прямі виклики ORM. Це застарілий код, а не шаблон для наслідування. Не копіюйте його.
Саме друге речення виконує основну роботу. Воно заздалегідь повідомляє агенту, що він побачить і як це слід інтерпретувати. Такий самий підхід застосовується до будь-якого правила, якому репозиторій явно суперечить: стилю комітів, якого не дотримується історія, структури тестів, яку ігнорує половина набору тестів, або правила імпортів, що діє лише в новому коді. Якщо код суперечить файлу, вкажіть цю суперечність у самому файлі.
Розпливчасте правило не можна перевірити, тому його неможливо виконати
«Пишіть чистий код». «Не ускладнюйте». «Дотримуйтеся простоти». «Обережно виконуйте міграції». Жодне з цих правил не можна перевірити на відповідність конкретній дії — ні агенту, ні вам. Агент, якому задано правило, що його не можна перевірити за власним результатом, лише вгадує, а ви оцінюєте цю здогадку на власний розсуд.
Застосовуйте до кожного рядка у файлі таку перевірку. Напишіть shell-команду, яка завершуватиметься з ненульовим кодом, якщо правило порушено. Якщо ви не можете написати таку команду, правило не є перевірюваним. Порівняйте ці пари:
- Не перевірюване: «Робіть функції короткими». Перевірюване: «Функція довша за 60 рядків повинна мати над собою коментар із поясненням причини».
- Не перевірюване: «Тестуйте зміни». Перевірюване: «Запустіть
npm testі вставте кількість помилок перед тим, як позначити завдання виконаним». - Не перевірюване: «Підтримуйте впорядкованість файлів». Перевірюване: «Обробники HTTP зберігаються у
src/api/handlers/. У цьому каталозі не повинно бути нічого іншого». - Не перевірюване: «Форматуйте код належним чином». Перевірюване: «У файлах
.tsвикористовуйте відступ у 2 пробіли».
«Не ускладнюйте» — це правило, від якого люди відмовляються найчастіше, оскільки виправлення полягає не в коротшому реченні, а в довшому: чітко опишіть, що саме означає мінімальна робоча зміна. Так агент отримає критерії, з якими він зможе самостійно порівняти власний diff.
Розмір файлу — це та сама проблема, але під іншим виглядом. Рекомендації Claude Code орієнтують на файли інструкцій обсягом до 200 рядків і прямо зазначають, що довші файли знижують дотримання правил. Файл на 700 рядків не містить надійніших інструкцій. Це 700 тверджень із більшою кількістю можливих суперечностей, і вони враховуються у вашому контекстному вікні під час кожного запиту, що безпосередньо відображається у використанні токенів. Структурування файлу так, щоб кожне правило було розміщене під заголовком, який читач може швидко переглянути, описано в матеріалі про написання файлу інструкцій, за яким агент може діяти.
Як діагностувати проблему за десять хвилин
Виконайте ці дії по черзі. Якщо одразу перейти до останнього кроку, можна отримати довгий файл із правилами, написаними великими літерами, який усе одно не працюватиме.
- Переконайтеся, що правило завантажене. Виконайте
/contextі перегляньте список Memory files. Якщо файлу немає, виправте шлях і зупиніться. Інші кроки цього списку поки що не застосовуються. - Відтворіть проблему в новій сесії. Запустіть нову сесію та поставте найменше завдання, яке має активувати правило. Якщо правило працює тут, але не працює в довгій сесії, проблема, ймовірно, пов’язана з віддаленням від початкового контексту або його стисканням. Якщо воно не працює і тут, проблема в самому правилі.
- Усуньте конкурувальні інструкції. Попросіть виконати ту саму зміну в каталозі, наявний код якого вже відповідає правилу. Якщо відповідність відновиться, навколишній код переважив вашу інструкцію.
- Знайдіть конфлікт. Два файли з різними вказівками щодо однакової поведінки є документованою причиною збою: модель може довільно вибрати один із них і не повідомити про це.
- Зробіть правило придатним для перевірки та повторіть тест. Перепишіть правило, додавши конкретний шлях і умову. Якщо відповідність значно покращиться, причиною було формулювання.
Крок 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/або коментар на початку самого файлу. Тоді правило завантажується під час того самого читання, що й код, якого воно стосується. Прийміть компроміс: усе, що завантажується таким способом, зникає під час наступного скорочення контексту й повертається під час наступного відповідного читання. - Перенесіть контроль у hook. Текстова інструкція лише просить. Hook ухвалює рішення. Hooks виконуються як код у визначені події життєвого циклу та застосовуються незалежно від висновку моделі.
- Передайте правило детермінованому інструменту й видаліть текстову інструкцію. Форматування, порядок імпортів, довжина рядка, заборонені імпорти, формат повідомлення коміту.
ruff format,prettier --write,eslint, hookpre-commit. Formatter щоразу дає правильний результат і не витрачає токенів. Речення найчастіше дає правильний результат, але витрачає токени під час кожного запиту.
Крок 3 повністю. Припустімо, що агент ніколи не має редагувати файли міграцій. Додайте це до .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 у ваших налаштуваннях виконує ту саму роботу без скрипту, який потрібно супроводжувати, а режими дозволів визначають, що запускається без попереднього запиту до вас. Якщо інструкція справді має бути на рівні системного prompt, а не в повідомленні користувача, --append-system-prompt розміщує її там. Однак її потрібно передавати під час кожного запуску, тому такий підхід краще підходить для скриптів, ніж для інтерактивної роботи.
Що не можна виправити інструкцією
Чітко визначте, яка частина проблеми залежить від вас. Розташування, формулювання, конфлікти між файлами та розмір файла належать до проблем автора і мають виправлятися автором. Решта залежить від поведінки моделі, і точніше формулювання цього не усуне.
Погодження не означає виконання. Агент підтвердить правило, правильно повторить його, а через два виклики інструментів порушить. Таке підтвердження нічого не коштує і нічого не прогнозує. Не сприймайте його як виправлення і не вважайте його тестом.
Деякі звички зберігаються. Додавання коментарів, додавання захисної обробки помилок, написання підсумку наприкінці, виконання очевидної наступної команди. За наявності правила, яке це забороняє, такі дії виконуватимуться рідше, але не зникнуть повністю. Ви можете виміряти власну частоту: виконайте те саме завдання десять разів у нових сесіях і порахуйте порушення. Якщо це число має дорівнювати нулю, правило потрібно прибрати з prompt.
Ваша сесія стає прикладом. Якщо агент порушив правило на кроці 12, а ви це пропустили, порушення залишається в контексті як приклад і є набагато новішим за саме правило. Виправляйте порушення одразу після виявлення. Невиправлене порушення навчає решту сесії.
Файл інструкцій не є межею безпеки. Він формує поведінку, але не забезпечує її дотримання. Усе, де помилка має високу ціну, зокрема облікові дані або руйнівні команди, потрібно контролювати через дозволи або hook. Не допускайте доступу агента до секретів застосовує той самий принцип до даних: не просіть агента не читати файл, а зробіть так, щоб файл не був доступний для читання.
Коротко: доведіть, що файл завантажено, зробіть правило перевірюваним, розмістіть його поруч із тим, чого воно стосується, а якщо частота порушень усе ще має значення, приберіть це правило з prose. Правило, яке агент не може проігнорувати, ніколи не було лише проханням до агента.
FAQ
Чому Claude Code ігнорує мій CLAUDE.md?
Спочатку перевірте, чи файл завантажено, перш ніж вважати, що його проігноровано. Виконайте /context і перегляньте список Memory files; якщо файл не зазначено в ньому, його немає в поточному контексті. Файли інструкцій передаються як повідомлення користувача після системного промпту й розглядаються як контекст, а не як конфігурація з обов’язковим виконанням. Тому суворої гарантії дотримання немає. У більшості реальних випадків причина одна з чотирьох: файл розташований у підкаталозі, з якого агент не читав дані; два файли містять суперечливі правила, і модель довільно обрала одне; правило надто нечітке, щоб зіставити його з конкретною дією; або навколишній код демонструє протилежне до того, що вимагає правило.
Чи впливає редагування файлу інструкцій під час сеансу?
Не для копії, яка вже є в поточному контексті. Файли вище робочого каталогу повністю завантажуються під час запуску, тому модель має текст зі станом на момент запуску. Щоб завантажити зміни, почніть новий сеанс або попросіть агента прочитати файл за допомогою його штатних файлових інструментів. У такому разі поточна версія потрапить у контекст як нове повідомлення. Після compaction файл у корені проєкту повторно читається з диска, тому нова версія також з’являється в цей момент.
Який файл має пріоритет, якщо кореневий CLAUDE.md і вкладений файл містять суперечливі правила?
Надійного пріоритету немає. Виявлені файли об’єднуються в контекст, а не перевизначають один одного. Вони впорядковуються від кореня файлової системи до робочого каталогу, тому найближчий файл просто читається останнім. Механізму пріоритетів для розв’язання суперечностей немає. У документації Claude Code зазначено, що суперечливі правила можуть розв’язуватися довільно. Створюйте вкладені файли як доповнення й указуйте в них шлях, якого вони стосуються. Усуньте суперечність, а не намагайтеся надати одному правилу вищий пріоритет.
Чи зберігаються мої інструкції після /compact?
Це залежить від способу їх завантаження. Файл у корені проєкту CLAUDE.md, правила без області застосування та автоматична пам’ять повторно додаються з диска після compaction. Правила з frontmatter paths: і вкладені файли CLAUDE.md у підкаталогах втрачаються, доки відповідний файл не буде прочитано знову. Усе, що ви лише ввели в чат, зберігається тільки в тому разі, якщо засіб узагальнення залишив це в контексті. Якщо правило має діяти протягом усього сеансу, розмістіть його у файлі в корені проєкту без frontmatter paths:.
Коли правило слід реалізувати як hook, а не як текстову інструкцію?
Коли перевірка є детермінованою, а вартість пропуску вища за вартість написання невеликого скрипту. До таких випадків належать обмеження шляхів до файлів, обов’язкові команди перед commit і заборонені виклики інструментів. Hook PreToolUse, який завершується зі статусом 2, безпосередньо блокує виклик інструмента й передає текст stderr моделі як причину. Тому правило діє незалежно від того, чи залишилося воно в контексті. Усе, що може визначити formatter або linter, має перевірятися цим інструментом, а з файлу інструкцій таке правило слід повністю видалити.