RE:NODE

AI-контекст в репозитории: CLAUDE.md, AGENTS.md и сервер

Автор Команда RE:NODE
15 мин чтения


AI-ассистент для кода, открытый в репозитории, знает код и больше ничего. Он не знает, на каком порту слушает сервер, что после перезапуска сохраняется только одна директория, что нет ни root, ни systemd, и что push переразворачивает сервер за считаные секунды. Поэтому он гадает, а его догадки - это значения по умолчанию из учебников: порт 3000, localhost, Dockerfile, которого никто не просил, пароль, вставленный прямо в конфиг. Решение - обычный Markdown-файл в репозитории, который ассистент читает перед началом работы: CLAUDE.md для Claude Code, AGENTS.md для Codex, Cursor и растущего списка других инструментов. На серверах приложений RE:NODE, связанных с GitHub, панель может написать этот файл за вас: включите переключатель Keep AI context in the repository на вкладке GitHub, и она откроет pull request, добавляющий .renode/server.md и короткий помеченный блок в CLAUDE.md и AGENTS.md. Вы читаете его, принимаете, и с этого момента ассистент знает, как работает сервер, и никому не нужно вставлять это вручную.

В этой статье две части: что такое файл контекста и как написать хороший на любом хостинге, а также что именно панель записывает, что оставляет за скобками и как в это попадает предполётная проверка.

Что такое файл AI-контекста#

Файл контекста - это инструкции для агента, которые лежат рядом с кодом. Когда агентный инструмент начинает сессию в репозитории, он ищет в корне (а иногда и в подкаталогах) файл с известным именем, читает его и считает постоянными инструкциями на всю сессию. Это не конфигурация в строгом смысле - ничто его не разбирает - это текст и списки, которые модель читает так же, как ваш запрос, только писать их нужно один раз.

В него попадает то, что новому коллеге понадобилось бы в первый день и о чём иначе пришлось бы спрашивать:

  • как установить, собрать, протестировать и запустить проект, точными командами;
  • где что лежит и какие директории генерируются и их нельзя править;
  • соглашения, которые не очевидны из кода: имена, обработка ошибок, какая библиотека главнее, если подходят две;
  • среда, в которой код реально работает, и её ограничения;
  • то, чего нельзя допускать никогда: секреты в коммитах, правки вендорного кода, force push.

Последние два пункта - то место, где большинство файлов контекста скудны и откуда идёт основной вред. Ассистент, не знающий среды развёртывания, пишет код для ноутбука. Код для ноутбука слушает 127.0.0.1, пишет загрузки в /tmp и считает, что может сделать apt install для всего, что ему понадобится. Все три предположения тихо ломаются на контейнерном хостинге. Общие виды сбоев у агентов, работающих с серверами, мы разобрали в статье AI coding agents for server and DevOps work; файл контекста - самая дешёвая защита от ошибок класса "не та среда".

Какой инструмент какой файл читает#

Единого стандарта пока нет, а с именами файлов путаница. Полезная сводка на конец 2026 года:

ФайлКто читает
CLAUDE.mdClaude Code
AGENTS.mdOpenAI Codex, Cursor, агент GitHub Copilot и другие
.cursor/rules/Cursor (собственные файлы правил)
.github/copilot-instructions.mdGitHub Copilot

AGENTS.md - самое близкое к общему формату: обычный Markdown-файл без обязательной структуры, который согласились читать несколько вендоров. CLAUDE.md - собственное имя Claude Code для той же идеи; он также читает файлы CLAUDE.md в подкаталогах, когда работает в них, и личный файл в вашей домашней директории. Поддержка в инструментах меняется быстро, поэтому если важен конкретный из них, проверьте в его документации, какие имена он сейчас подхватывает.

Два практических следствия. Во-первых, если команда использует больше одного ассистента, одни и те же базовые инструкции нужны в нескольких файлах. Держать их одинаковыми вручную не получается; обычное решение - оставить общую часть короткой и направить оба файла на один более длинный документ. Во-вторых, чат-ассистент вроде ChatGPT в браузере сам вообще не читает ваш репозиторий. Он знает только то, что вы ему дали, - поэтому для такого случая в панели есть ссылка для передачи, о ней в конце.

Что в него писать, а что нет#

Лучшие файлы контекста короткие и конкретные. Модель читает каждую строку файла в каждой сессии, а длинный файл с общими советами размывает те немногие строки, которые важны. Полезная проверка для каждой строки: ошибся бы ассистент, никогда не видевший этот файл? Если нет, удалите её. "Пишите чистый код" эту проверку не проходит. "Сервер слушает порт из SERVER_PORT, а не 3000" - проходит.

В небольшом сервисе на Node это может выглядеть так:

CLAUDE.md
# Orders API## Commands- Install: npm ci- Test: npm test (needs a local Postgres, see docker-compose.yml)- Start: npm start (runs node dist/server.js; build first with npm run build)## Layout- src/ is the code; dist/ is generated - never edit it.- migrations/ is append-only. Add a new file; never change a merged one.## Rules- Read configuration from environment variables only. See .env.example.- Never commit .env or any key, token or password.- Use the existing logger in src/log.ts, not console.log.

Чему в нём не место:

  • Секреты. Файл контекста попадает в коммит, а значит всё, что в нём есть, остаётся в истории навсегда. Называйте переменную, но никогда не пишите её значение. О том, где должны лежать значения, рассказано в статье Environment variables and secrets.
  • То, что меняется при каждом деплое. Текущий коммит, время последнего деплоя, номер сборки. Они мгновенно устаревают и превращают каждый diff в шум.
  • То, что код и так говорит. Список маршрутов, схема базы данных. Ассистент может прочитать их сам; копирование в текст лишь создаёт вторую версию, которая разойдётся с первой.
  • Длинные руководства. Вместо этого сошлитесь на документ в репозитории, и пусть ассистент откроет его, когда понадобится.

Чаще всего люди пропускают сам сервер. Они пишут команды и соглашения и на этом останавливаются, потому что сервер кажется чьей-то чужой заботой. А это как раз та часть, которую может заполнить панель, потому что только она знает её точно.

Переключатель AI-контекста на вкладке GitHub#

На сервере приложения, связанном с репозиторием GitHub, на вкладке GitHub есть переключатель: Keep AI context in the repository (opens a pull request). Пока вы его не включили, он выключен, и действует он только для этой одной связи. Для репозитория, владелец которого его не нажал, ничего не открывается никогда.

Когда он включён, GitHub App панели - тот же самый, что отвечает за деплой из GitHub - делает следующее:

  1. Создаёт ветку renode/ai-context от головы ветки, из которой деплоится ваш сервер.
  2. Коммитит в эту ветку .renode/server.md и помеченные блоки в CLAUDE.md и AGENTS.md через API GitHub. Ничего не клонируется.
  3. Открывает pull request из renode/ai-context в вашу ветку деплоя.
  4. Вы просматриваете его и принимаете либо закрываете.

Панель никогда не делает push в ветку, из которой деплоится ваш сервер. Каждый коммит идёт в отдельную ветку renode/ai-context, а решение о слиянии остаётся за вами. Push в ветки renode/ к тому же игнорируется хуком деплоя при push, поэтому обновление контекста никогда не перезапускает сервер.

Строка статуса под переключателем показывает, что происходит: выключено, идёт работа, ожидание разрешения, pull request открыт к вашей ветке, всё актуально, последний pull request закрыт без слияния или ошибка. Любой отказ от GitHub - лимит запросов, защищённая ветка, архивный репозиторий, нехватка прав - появляется как одна из этих строк, а не как страница сбоя. Общие шаги по связыванию репозитория описаны в руководстве по деплою.

Что панель записывает в репозиторий#

Содержимое двух видов, с разным владельцем.

Блок в CLAUDE.md и AGENTS.md

В CLAUDE.md и AGENTS.md панели принадлежит только текст между двумя HTML-комментариями, <!-- renode:start --> и <!-- renode:end -->. Если файла нет, он создаётся и содержит только этот блок. Если файл есть, но без маркеров, блок добавляется в конец. Если маркеры есть, заменяется только то, что между ними. Всё, что вы написали вне них, сохраняется байт в байт, так что ваши команды и соглашения могут стоять выше или ниже части панели, и их никто не тронет. HTML-комментарии не отображаются на GitHub, поэтому при чтении файла там маркеры не видны.

Блок намеренно короткий: несколько правил, нарушение которых ломает деплой, и ссылка на полный файл. Для сервера Node.js с деплоем при push он выглядит примерно так:

CLAUDE.md (the panel's block)
<!-- renode:start -->## Renode serverThis repository is deployed to a Renode server (Node.js) from the mainbranch. Read .renode/server.md before changing how it builds, starts orconnects to anything.- Listen on 0.0.0.0 on the port in the SERVER_PORT environment variable.  No other port is reachable from outside.- Only /home/container persists. No root, no apt, no systemd, no Docker.- The panel starts it in a fixed order. Keep the entry file and start  script it expects.- Never commit secrets. They go in a .env uploaded through the Files tab,  or in Startup variables, and are read from the environment.- A push to main redeploys and restarts the server within seconds.- Fix the code, not the startup command or the Docker image.<!-- renode:end -->

Точный текст зависит от сервера: название среды выполнения, ветка, число шагов загрузки и включён ли деплой при push. Если он выключен, строка про push вместо этого велит ассистенту перезапустить сервер из панели после push.

Файл сервера

.renode/server.md целиком принадлежит панели, говорит об этом в комментарии вверху и перезаписывается при каждом изменении настроек сервера. Свои заметки пишите в CLAUDE.md или AGENTS.md, вне маркеров, а не здесь. В нём такие разделы:

РазделЧто содержит
Runtimeтип сервера и его образ Docker
Networkпорт, а также адрес и домены (для приватных репозиториев)
Codeпуть в контейнере, репозиторий, ветка, переключатели деплоя
How this server bootsпронумерованные шаги, которые панель выполняет при запуске
Variablesкаждая переменная окружения, её имя и является ли она секретной
Databasesподключённые базы данных (подробности только в приватных репозиториях)
Limitsпамять, CPU и диск
Pre-flight checkчто панель нашла не так в репозитории
Rulesполный список, который кратко пересказывает короткий блок

Порядок загрузки - самая полезная часть, и именно её никто не пишет вручную. Ассистент, которого спросили "почему не запускается приложение", может прочитать, что сервер устанавливает зависимости, а затем выполняет определённую команду запуска, и рассуждать от этого, а не выдумывать Procfile. Раздел с ограничениями важен по той же причине: знание о том, что процесс убивается на потолке памяти без сообщения об ошибке - консоль просто останавливается, - превращает загадочный сбой в очевидный диагноз. Подробно об этом написано в статье Node memory limits explained.

Чего файл не содержит намеренно: развёрнутого коммита и его времени. Они превратили бы каждый push в обновление pull request, а такой шум вам совсем не нужен.

Публичные и приватные репозитории#

Панель при каждой записи спрашивает у GitHub, приватный ли репозиторий, и считает публичным всё, что не является явным "private". Файлы для них получаются разные.

ДетальПриватный репозиторийПубличный репозиторий
Правила, шаги загрузки, ограничениядада
Адрес сервера и портдатолько переменная порта
Домены, нода, ID сервераданет
Имена переменныхдада
Значения переменныхнесекретныенет
Хост, имя и пользователь базы данныхдатолько количество

Секретные значения не записываются ни в один из видов. Переменная, помеченная как секретная, отображается заглушкой, где сказано, что она задана на сервере и не показывается, а пароли баз данных не включаются никогда: в файле написано, что пароль находится на вкладке Databases и его место в .env. Обе версии также проходят через тот же редактор, что и другие AI-функции панели: он вычищает всё, что похоже на ключ или токен, и известные ему секреты самого сервера. Мы называем это сеткой, а не обещанием: она ловит то, для чего построена, а pull request всё равно стоит прочитать перед слиянием, как и любой другой.

Как находки предполётной проверки попадают в контекст#

Вкладка GitHub также запускает предполётную проверку: она читает репозиторий - один список дерева и несколько небольших файлов, без клонирования - и перечисляет то, что сломается при запуске сервера, начиная с худшего, и к каждому пункту даёт исправление, которое можно вставить. Она ищет отсутствующий скрипт запуска или входной файл, привязку к порту 3000 или к localhost вместо порта сервера на 0.0.0.0, фреймворк, который никогда не собирается (скажем, нет .next), версию среды, закреплённую в .nvmrc или go.mod, зависимости Python и входной файл, главный пакет Go, задачи запуска Bun и Deno, файл index на веб-хостинге и закоммиченный .env, о котором сообщается по имени и который никогда не открывается.

Когда переключатель AI-контекста включён, эти находки попадают в .renode/server.md в раздел Pre-flight check, который начинается словами "What the panel found when it read this repository. Fix every FAIL first." Каждая находка - одна строка, помеченная своим уровнем заглавными буквами, затем подробности и исправление:

.renode/server.md (excerpt)
## Pre-flight checkWhat the panel found when it read this repository. Fix every FAIL first.- [FAIL] No start script and no entry file - The server runs npm run start,  and package.json has no start script. ... Fix: Add "start": "node <your  main file>" to the scripts in package.json.

Именно эта часть меняет поведение ассистента. Без неё вы открываете Claude Code или Cursor, пишете "деплой сломан, почини", и ассистент начинает с догадок. С ней ассистент открывает репозиторий, читает файл контекста и находит список конкретных неисправностей с уже написанными исправлениями. Обычно первым делом он идёт по этому списку сверху вниз. Диагностику сделала панель, правку делает ассистент, а вы проверяете diff.

Это ещё и замыкает цикл. Вы исправляете FAIL, делаете push, и следующее обновление снова читает репозиторий. Находка исчезла, содержимое файла изменилось, и в открытый pull request добавляется новый коммит без неё. У чистого репозитория раздела Pre-flight check в итоге нет вовсе.

Как поддерживать актуальность#

Контекст обновляется, а не пересоздаётся по прихоти. Фоновая задача запускается каждые десять минут и замечает, что изменились переменные, порты, базы данных или домены; сохранение настроек на вкладке GitHub тоже ставит обновление в очередь, не чаще одного раза в десять минут на связь. Каждый раз содержимое хешируется, и если хеш совпадает с прошлым, ничего не записывается. Сервер, который не меняется, не порождает коммитов.

Что происходит с pull request, зависит от его состояния:

  • Открыт: в renode/ai-context добавляется новый коммит с изменениями.
  • Принят: новый pull request открывается, только если содержимое отличается от того, что в вашей ветке.
  • Закрыт без слияния: статус сообщает об этом, и новый открывается, только когда содержимое снова изменится.

Update now пропускает ожидание и запускает обновление немедленно - это полезно после одобрения прав приложения или сразу после изменения настроек, которое вы хотите видеть в файле сегодня.

Связь следует за настройками деплоя сервера. Смена ветки деплоя закрывает pull request и открывает новый к новой ветке. Переход на другой репозиторий выключает функцию, потому что согласие на pull request в одном репозитории не означает согласия на них в другом. Отвязка тоже выключает её. Если вы сами выключите переключатель, открытый pull request будет закрыт с комментарием, а ветка renode/ai-context удалена. То, что вы уже приняли, это не затрагивает: файлы остаются в вашем репозитории, пока вы сами их не удалите.

Устранение неполадок#

В статусе написано, что идёт ожидание разрешения. GitHub App не получило в вашей установке права на запись Contents и Pull requests. Перейдите по ссылке на вкладке к настройкам установки, примите новые права и нажмите Update now. Пока вы этого не сделаете, панель ничего не записывает.

Сообщается, что не удалось обновить репозиторий. Прочитайте строку статуса и причину рядом с ней. Частые случаи: репозиторий архивный (GitHub отклоняет любую запись), вы упёрлись в лимит запросов GitHub (подождите и нажмите Update now) или правило защиты ветки охватывает renode/*. Защита вашей главной ветки значения не имеет - панель туда никогда не пишет, - но правило с подстановкой, которому соответствует и renode/ai-context, её заблокирует.

В моём CLAUDE.md есть начальный маркер, но нет конечного. Панель не берётся угадывать, где заканчивается её блок, и ничего не записывает. Обычно так бывает после ручной правки или неудачного слияния. Удалите лишний маркер или добавьте недостающий и нажмите Update now.

Ассистент по-прежнему привязывается к порту 3000. Проверьте, что pull request принят в ту ветку, которая у вас сейчас открыта. Файлы работают, только когда они лежат в рабочей копии, которую открывает ассистент. Затем проверьте, что инструмент читает именно тот файл, о котором вы думаете: Claude Code читает CLAUDE.md, Codex и Cursor читают AGENTS.md. Некоторые инструменты читают контекст только в начале сессии, поэтому начните новую.

Я вообще не хочу, чтобы панель трогала CLAUDE.md. Закройте pull request или выключите переключатель. Если вам нужна информация без pull request, панель "Work on this server with AI" на вкладке Console даёт ссылку с тем же контекстом сервера, которую можно передать ассистенту напрямую.

FAQ#

Делает ли панель когда-нибудь push в мою главную ветку?

Нет. Любая запись идёт в renode/ai-context и попадает в вашу ветку только через pull request, который принимаете вы. Код, перемещающий ветки, отказывается работать с любой веткой вне renode/, а push в эти ветки никогда не запускает деплой.

Перезапустит ли мой сервер слияние pull request?

Если деплой при push включён, слияние добавляет новый коммит в вашу ветку деплоя, так что да, сервер переразвернётся и перезапустится, как при любом другом push. Сами файлы контекста никак не влияют на то, как работает код.

Можно ли править сгенерированные файлы?

CLAUDE.md и AGENTS.md вне маркеров правьте свободно; панель этот текст не трогает. Не правьте .renode/server.md и текст между маркерами - следующее обновление его перезапишет. Лучше измените настройки сервера, и файл последует за ними.

Работает ли это с ChatGPT?

Не через репозиторий. ChatGPT в браузере сам не читает файлы из вашего GitHub. Для чат-ассистента используйте кнопку Connect AI на вкладке Console: она создаёт ссылку для передачи с контекстом сервера, которую вы вставляете в разговор. Claude Code, Cursor, Copilot и Codex - это инструменты, которые подхватывают файлы репозитория сами.

Есть ли пароль от моей базы данных в файле?

Нет, ни в публичных, ни в приватных репозиториях. Приватный репозиторий получает имя базы, хост, порт и пользователя с пометкой, что пароль находится на вкладке Databases и его место в .env. Публичный получает только количество подключённых баз.

Что если мой репозиторий не связан с сервером?

Тогда панели нечего описывать, и переключатель не предлагается. Вы по-прежнему можете написать CLAUDE.md и AGENTS.md вручную, следуя советам выше, - к разделу о сервере стоит отнестись внимательнее всего.

Это было полезно?