Формулировка, которая наконец сработала, живёт до конца сессии. Завтра я напишу её заново, чуть иначе и чуть хуже, а через месяц вспомню, что когда-то нашёл правильные слова, и не вспомню какие.
Это самая скучная проблема из всего цикла и самая дорогая по накопительному эффекту. Ниже — как я её решил на двенадцати проектах и где переусердствовал.
Три места
У знания о том, как работать с этим проектом, есть ровно три адреса.
Сообщение. Живёт одну сессию. Сюда идёт всё, что относится к конкретной задаче: цель, объём, критерий готовности.
Файл контекста. AGENTS.md, CLAUDE.md. Читается в начале каждой сессии. Сюда идёт то, что верно всегда, независимо от задачи.
Скилл. Каталог с SKILL.md, который подключается по условию. Сюда идёт процедура, применимая иногда: публикация статьи, создание ресурса админки, разбор карты репозитория.
Ошибка первых месяцев — держать всё в первом адресе. Ошибка следующих месяцев — переносить всё во второй.
Признак переезда
Формулировка переезжает из сообщения в файл, когда я пишу её третий раз.
Не второй. Второй раз бывает случайностью: две похожие задачи подряд ничего не доказывают. Третий — уже закономерность, и с этого момента дешевле записать.
Пример из блога. Первые три задачи по бэкенду я начинал строкой «команды artisan запускай внутри контейнера webserver, вот так». На четвёртой строка переехала в CLAUDE.md, и с тех пор я её не пишу:
docker compose --env-file .local/.env -f .local/docker-compose.yml \
exec -T webserver php artisan testОбратный признак тоже есть, и он важнее. Если формулировка сработала один раз и я не могу представить второй — она остаётся в сообщении. Соблазн записать всё, что удачно получилось, приводит к файлу на триста строк, из которого работают тридцать.
Что попадает в файл контекста
Три категории, проверенные на дюжине репозиториев.
Команды. Как запустить, как прогнать тесты, как собрать фронт, как применить миграции. Это первое, что спрашивают, и первое, что придумывают неправильно. В моих Laravel-проектах вся разница с типичным проектом — в том, что команды идут через контейнер, и без записи об этом первым делом пробуют php artisan на хосте.
Конвенции. То, чем проект отличается от типичного проекта на этом стеке. У блога это раскладка ресурсов админки по папкам, обязательная передача списка рубрик в публичные шаблоны, вывод пользовательского HTML только через очиститель. Ни одну из трёх нельзя вывести из кода за разумное время, а нарушение каждой стоит правки после ревью.
Чего здесь нет. Самый недооценённый раздел. Он бьёт по механизму достройки: там, где данных нет, они восстанавливаются из типичного проекта. Строка «ролевой модели нет, есть один флаг администратора» экономит больше, чем страница описания архитектуры.
Что в файл контекста не идёт: описание архитектуры на две страницы, перечисление всех моделей, пересказ фреймворка. Это либо устареет за месяц, либо и так видно в коде.
Что становится скиллом
Скилл — это записанная процедура со своими шагами и своим условием срабатывания. Не «как устроен проект», а «как здесь делается вот эта работа».
У блога таких пятнадцать. Самые рабочие:
repo-discovery карта проекта до правок: flow, связи, побочные эффекты
visual-qa проверка интерфейса после изменений
publish-workflow draft → preview → publish, RSS, sitemap, сброс кэша
seed-content правка контента в сидерах, на проде полный сброс базы
filament-resource создание ресурса админки по конвенциям проектаРазница с файлом контекста видна на паре seed-content и строки в AGENTS.md. В файле контекста записано, что источник контента — сидеры. В скилле — порядок действий: где искать источник правды, почему на проде база каждый раз пересоздаётся целиком, что делать с идемпотентностью, куда идут тексты и картинки. Первое нужно всегда, второе — раз в неделю.
Условие срабатывания живёт в описании скилла и пишется как «используй, когда…», а не как название темы. Про это будет отдельная статья цикла «Скиллы»; здесь важно, что скилл без внятного условия не подключается и, значит, не существует.
Почему складывать всё в файл вредно
Файл контекста читается целиком и всегда. Это его сила и его ограничение.
Триста строк конвенций на старте сессии — это триста строк, которые конкурируют за внимание с самой задачей. Хуже того, на пятидесятом действии подряд из них помнится не всё, и первыми выпадают те, что не относятся к текущей работе. Строка про правила именования миграций мешает удерживать строку про экранирование в шаблонах ровно тогда, когда задача про шаблоны.
Мой рабочий размер — до сотни строк на AGENTS.md и десяток на CLAUDE.md, который служит указателем. Всё, что не помещается, либо становится скиллом, либо выбрасывается как неработающее.
Второй вред от разрастания — гниение. Строка, которая перестала быть правдой, хуже отсутствующей: ей верят. В блоге месяца три висело утверждение про скоуп публикации, которое не соответствовало коду, и обнаружилось это случайно, на разведке со ссылками на строки.
Как это выглядит на двенадцати проектах
Раскладка везде одинаковая, и в этом весь смысл.
CLAUDE.md короткий указатель: стек, команды, ссылка на AGENTS.md
AGENTS.md подробное руководство: автономность, конвенции, маршрутизация
.ai/skills/ процедуры, каждая — каталог со SKILL.md
.ai/agents/ исполнители под зоны кодаОдинаковость даёт неочевидную выгоду: возврат к проекту через полгода не требует вспоминать, где что лежит. Открываю AGENTS.md, вижу знакомую структуру, дальше по ссылкам.
Стоимость тоже есть. Два проекта пришлось подгонять под общий формат, и в одном из них раскладка была объективно удобнее — но своя. Я её сломал ради единообразия и до сих пор не уверен, что был прав.
Что осталось
Правило трёх повторов работает и почти не требует дисциплины: третье написание одной и той же строки само вызывает раздражение, которое и есть сигнал.
Чего не решил — обратного движения. Строки в файлы попадают, а обратно не уходят. Я ни разу не удалял конвенцию из AGENTS.md по причине «она больше не нужна», только по причине «она врёт». Подозреваю, что треть моих файлов контекста — это следы проблем, которых давно нет.