К этому моменту у вас установлен Claude Code и есть папка с заготовкой игры. Дальше вся работа сводится к одному циклу: вы описываете задачу — получаете код — проверяете его в браузере — уточняете. Качество результата почти целиком определяется первым шагом. Не «умом модели», а тем, сколько нужного контекста вы положили в промпт и дали ли способ проверить результат.
Эта глава — про то, как формулировать задачи и как перестать объяснять одно и то же каждый раз.
Почему «сделай игру» не работает
Claude Code читает файлы вашего проекта и может сам разобраться в структуре кода. Чего он не может — угадать то, чего в коде нет:
- что сборка поедет в ZIP, где
index.htmlобязан лежать в корне; - что в именах файлов нельзя использовать пробелы и кириллицу;
- что модерация Яндекса завернёт билд, если в консоли есть JS-ошибки;
- что вы принципиально не хотите сборщик и внешние зависимости.
Всё это — ограничения платформы и ваши решения. Если их не сказать, модель выберет самый распространённый вариант из того, что видела: соберёт проект на Vite, подтянет библиотеку с CDN и назовёт папку «спрайты игрока». Формально код будет рабочим. На Яндекс Играх он не поедет.
Отсюда простое правило: промпт — это не пожелание, а техническое задание с приёмкой.
Анатомия рабочего промпта
У промпта, который стабильно даёт годный код, есть четыре части.
| Часть | Что отвечает | Пример |
|---|---|---|
| Контекст | Где это в проекте | «в src/platform.js, функция initSdk» |
| Задача | Что сделать | «добавь показ полноэкранной рекламы» |
| Ограничения | Чего нельзя / как именно | «без новых зависимостей, всё через существующий ysdk» |
| Критерий готовности | Как понять, что готово | «после правки открой игру локально и покажи, что в консоли нет ошибок» |
Сравните две формулировки одной и той же задачи.
Плохо:
добавь рекламу в игру
Хорошо:
В
src/platform.jsдобавь функциюshowInterstitial(). Она вызываетysdk.adv.showFullscreenAdvс объектом{ callbacks: { onOpen, onClose, onError } }. ВonOpenостанови игровой цикл и заглуши звук, вonClose(wasShown)— восстанови и то и другое независимо от значенияwasShown, потому чтоonCloseсрабатывает и когда реклама не показалась. ВызывайshowInterstitial()изonLevelComplete()вsrc/game.js, не по таймеру. Не трогай остальной кодplatform.js.
Вторая формулировка длиннее втрое и экономит три круга правок. Заодно она снимает конкретную ловушку: реклама, повешенная на setInterval, — прямо описанный в документации Яндекса антипаттерн, а незавершённая пауза при wasShown === false даёт намертво зависшую игру.
Критерий готовности — самая недооценённая часть
Claude Code останавливается, когда работа «выглядит законченной». Если проверить результат может только человек, то этим человеком становитесь вы — и каждую ошибку ловите глазами. Как только у агента появляется проверка, которую он может запустить сам, цикл замыкается: он пишет код, запускает проверку, читает результат и правит дальше.
Для веб-игры проверкой может быть:
- запуск игры локально и чтение консоли браузера (если у вашей сборки Claude Code есть доступ к браузеру — он прочитает ошибки сам);
- скриншот результата и сравнение с макетом, который вы вставили в чат;
- маленький скрипт-валидатор архива: проверить, что
index.htmlв корне ZIP, что распакованный размер не больше 100 МБ и что в путях нет кириллицы и пробелов.
Совет
Скрипт проверки архива стоит написать один раз в самом начале проекта и потом просто добавлять в промпт фразу «прогони node scripts/check-build.js и покажи вывод». Это дешевле, чем узнать о проблеме через 4 дня отказа модерации.
Что ещё можно положить в промпт
- Ссылка на файл через
@:объясни логику в @src/game.js— файл читается сразу, без поисков. - Скриншот: перетащите картинку в окно Claude Code или вставьте из буфера. Для UI-задач это в разы точнее описания словами.
- Текст ошибки целиком, а не «не работает». Со стектрейсом и командой, которой вы её воспроизвели.
- Ссылка на документацию. У Яндекса каждая страница документации отдаётся ещё и в виде сырого Markdown — достаточно дописать
.mdк адресу. Так что вместо пересказа по памяти можно прямо написать: «прочитайhttps://yandex.ru/dev/games/doc/ru/sdk/sdk-adv.mdи сделай по ней» (проверено в сентябре 2026 года).
Последний приём особенно полезен именно на Яндекс Играх: SDK менялся, а старые статьи и старый код никуда не делись.
CLAUDE.md: память проекта
Всё, что вы объясняете во второй раз, должно переехать в файл. Этот файл называется CLAUDE.md, и Claude Code читает его в начале каждой сессии.
Где он лежит
| Область | Расположение | Для чего |
|---|---|---|
| Пользовательская | ~/.claude/CLAUDE.md | ваши личные привычки во всех проектах |
| Проектная | ./CLAUDE.md или ./.claude/CLAUDE.md | правила проекта, коммитятся в git |
| Локальная | ./CLAUDE.local.md | личное для этого проекта, добавьте в .gitignore |
Файлы не заменяют друг друга, а склеиваются: сначала более общие, затем более частные. Кроме того, CLAUDE.md из родительских каталогов тоже подхватываются при старте, а файлы во вложенных папках подгружаются, когда Claude начинает читать файлы оттуда.
Как его завести и проверить
/init— Claude сам осмотрит проект и напишет стартовыйCLAUDE.md. Дальше дополняете руками тем, что из кода не выводится./memory— список файлов памяти и открытие любого из них в редакторе./context— показывает, какие файлы памяти реально загрузились в текущую сессию. Если правило не работает, начинать надо отсюда.
Важные свойства, о которые все спотыкаются
CLAUDE.md — это контекст, а не конфигурация. Он влияет на поведение, но не гарантирует его. Если что-то обязано выполняться всегда и без исключений — это не строчка в CLAUDE.md, а hook.
Второе: длина. Официальная рекомендация — держаться в пределах примерно 200 строк на файл. Раздутый CLAUDE.md работает хуже пустого: важные правила тонут в шуме, и модель начинает игнорировать половину. Для каждой строки полезно спросить: «если я это удалю, Claude начнёт ошибаться?» Если нет — удаляйте.
| Стоит включать | Не стоит |
|---|---|
| Команды, которые нельзя угадать | То, что видно из кода |
| Правила, отличающиеся от общепринятых | Стандартные конвенции языка |
| Запрещённые паттерны и подводные камни | Пересказ документации API |
| Как запускать и как проверять | Описание файлов по одному |
| Архитектурные решения проекта | Быстро устаревающие данные |
Важно
Если Claude Code упорно игнорирует конкретное правило — почти всегда файл слишком длинный, а не правило слишком слабое. Пометка «ВАЖНО» помогает только пока такая пометка одна-две на файл.
Пример CLAUDE.md для игры под Яндекс Игры
Ниже рабочая заготовка. Подставьте свои команды и структуру, лишнее выкиньте.
# Игра для Яндекс Игр — правила проекта
## Что это
HTML5-игра на чистом JavaScript. Сборщика нет: файлы из `dist/` кладутся
в ZIP как есть. В корне архива — `index.html`.
## Команды
- Локальный запуск с SDK: `npx @yandex-games/sdk-dev-proxy -p ./dist`
- Проверка архива перед загрузкой: `node scripts/check-build.js`
## Ограничения
- ES-модули, без сборщика и без рантайм-зависимостей.
- Никаких внешних хостов: шрифты, звуки, библиотеки — только внутри архива.
Любой внешний хост требует согласования на вкладке CSP в консоли разработчика.
- Имена файлов и папок — только латиница, цифры и дефис. Без пробелов
и кириллицы. Распакованный размер архива — не больше 100 МБ.
## Yandex Games SDK — обязательные правила
- Подключение только так: `<script src="/sdk.js"></script>`.
НИКОГДА не писать `https://yandex.ru/games/sdk/v2` — это старый лоадер,
он не проходит требование 1.19.1.
- `ysdk.getPlayer()` принимает только `{ signed }`. Опции `scopes` нет.
- Лидерборды — только `ysdk.leaderboards.getDescription` / `setScore` /
`getPlayerEntry` / `getEntries`. `ysdk.getLeaderboards()` устарел.
- `flush` — второй аргумент `setData(data, flush)`. Метода `player.flush()`
не существует.
- Обращения к `ysdk.features` — через опциональную цепочку:
`ysdk.features.LoadingAPI?.ready()`, `ysdk.features.GameplayAPI?.start()`.
## Порядок инициализации (не менять)
1. Подключить `/sdk.js`
2. `const ysdk = await YaGames.init()`
3. Подписаться на `game_api_pause` / `game_api_resume`
4. Загрузить ресурсы игры
5. `ysdk.features.LoadingAPI?.ready()` — когда всё готово к взаимодействию
6. `GameplayAPI?.start()` / `?.stop()` вокруг геймплея
## Лимиты (проверено в сентябре 2026)
| Метод | Запросов | Объём |
|---|---|---|
| `ysdk.getPlayer()` | 20 / 5 мин | — |
| `player.getData` / `setData` | 100 / 5 мин | 200 КБ на игрока |
| `getStats` / `setStats` / `incrementStats` | 60 / 1 мин | 10 КБ на игрока |
| `leaderboards.setScore` | 1 / 1 сек | — |
Часто меняющиеся числа (очки, валюта, опыт) — через `setStats`
и `incrementStats`, не через `setData`.
## Частые причины отказа модерации — проверять перед сборкой
- Game Ready не вызван или вызван не в тот момент (1.19.2)
- Язык не определяется через `ysdk.environment.i18n.lang` (2.14)
- Звук не глушится во время рекламы (4.7) и при потере фокуса вкладки (1.3)
- Контекстное меню браузера по правому клику или долгому тапу в игре
- Прогресс не сохраняется между сессиями (1.9)
- Ошибки JS в консоли при запуске или во время игры (1.14)
## Стиль
- Игровые константы — в `src/config.js`, магические числа в коде запрещены.
- Работа с SDK — только через `src/platform.js`. Игровой код не обращается
к `ysdk` напрямую: игра обязана запускаться и без SDK.Обратите внимание на блок «обязательные правила SDK». Он существует ровно по одной причине: устаревших примеров в интернете гораздо больше, чем актуальных, и языковая модель по умолчанию тяготеет к самому частому варианту. Явный запрет в CLAUDE.md — самый дешёвый способ это перебить.
Частая ошибка
Если в сгенерированном коде появилось <script src="https://yandex.ru/games/sdk/v2"></script>, ysdk.getLeaderboards() или вызов player.flush() — это не «работающий вариант», это следы старой документации. Первые два прямо ведут к проблемам с требованиями платформы, третий просто упадёт с ошибкой.
Итеративный цикл
Один заход выглядит так.
| Шаг | Что делаете | Инструмент |
|---|---|---|
| 1. Описать | Промпт с контекстом, ограничениями и критерием | @файл, скриншот, ссылка на доки |
| 2. Получить | Claude правит код | плановый режим для многофайловых правок |
| 3. Проверить | Запуск локально, консоль браузера | npx @yandex-games/sdk-dev-proxy |
| 4. Уточнить | Конкретная правка или откат | Esc, /rewind, /clear |
Несколько замечаний по шагам.
Плановый режим. Если правка затрагивает несколько файлов или вы сами не уверены в подходе — нажмите Shift+Tab, пока в строке состояния не появится ⏸ plan mode on. Claude прочитает код и предложит план, ничего не меняя на диске. План можно поправить и только потом одобрить. Для мелочи вроде «поменяй цвет кнопки» плановый режим — лишние накладные расходы.
Проверка в браузере. Локальный запуск через npx @yandex-games/sdk-dev-proxy -p ./путь-к-игре поднимает прокси, который подставляет настоящий SDK. Скачивать sdk.js себе не нужно и не следует. Смотреть надо не только на картинку, но и в консоль: пустая консоль — это буквально пункт требований, а не вопрос вкуса.
Откат вместо спора. Если два раза подряд правка не помогла, третья попытка обычно тоже не поможет: контекст уже забит неудачными подходами. Esc останавливает работу на середине, двойной Esc или /rewind открывает меню отката к предыдущему состоянию кода и диалога, /clear полностью сбрасывает контекст. Чистая сессия с хорошим промптом почти всегда выигрывает у длинной сессии с накопленными исправлениями.
Типичные ошибки в промптах
Задача размером с главу. «Сделай меню, сохранения, лидерборд и рекламу» — гарантированно получите четыре наполовину сделанные вещи. Один промпт — одна проверяемая единица работы.
Нет указания места. «Почини баг с сохранением» заставляет агента прочитать полпроекта и забить контекст. «Прогресс не восстанавливается после перезагрузки, смотри loadProgress() в src/storage.js» — сразу в цель.
«Не работает» вместо ошибки. Вставляйте текст ошибки, шаги воспроизведения и то, что должно было произойти.
Отсутствие критерия приёмки. Самая частая причина «правдоподобного, но нерабочего» кода. Если вы не можете проверить результат — не выкатывайте его.
Свалка в одной сессии. Начали с рекламы, свернули на баланс уровней, вернулись к рекламе. Контекст полон нерелевантного. /clear между несвязанными задачами.
Третье повторение одного и того же правила. Если вы во второй раз пишете «не подключай библиотеки с CDN» — это не промпт, это строчка в CLAUDE.md. Промпт живёт одну сессию, файл — весь проект.
Слепая вера в код про SDK. Всё, что касается Яндекс SDK, стоит проверять по актуальной документации, а не по правдоподобности. Это единственная область в проекте, где красивый и уверенный код может быть устаревшим на несколько лет.
Что дальше
Дальше — практика: подключение SDK к пустой странице, инициализация и вызов Game Ready в правильный момент жизненного цикла. Именно там правила из вашего CLAUDE.md впервые окупятся, а промпты из этой главы превратятся в первые строчки настоящего кода игры.