Продвинутый

CLAUDE.md для Claude Code по наблюдениям Кэрпати

Алексей Кузнецов
Алексей Кузнецов
Системный администратор6 ноября 2026 г.13 мин чтения

Один файл CLAUDE.md, который улучшает поведение Claude Code на основе наблюдений Андрея Кэрпати о типичных ошибках LLM при кодировании.

CLAUDE.md для Claude Code по наблюдениям Кэрпати

Один файл CLAUDE.md, который улучшает поведение Claude Code на основе наблюдений Андрея Кэрпати о типичных ошибках LLM при кодировании.

Что такое CLAUDE.md и зачем он нужен Claude Code

Что такое CLAUDE.md и зачем он нужен Claude Code

CLAUDE.md — это файл с инструкциями для Claude Code, который лежит в корне вашего проекта и читается моделью в начале каждой сессии. Он не заменяет системный промпт, а дополняет его проектным контекстом: стиль кода, архитектурные решения, правила тестирования и соглашения по именованию.

Андрей Кэрпати в своих наблюдениях за работой LLM с кодом отмечал, что модели часто склонны к поверхностным решениям: пишут функцию, которая работает изолированно, но не учитывает существующие абстракции в репозитории, или предлагают библиотеку, которая дублирует уже подключённую зависимость. CLAUDE.md фиксирует ожидания команды в одном месте, чтобы модель не гадала, а опиралась на соглашения.

В результате вы получаете предсказуемость: Claude Code предлагает код, который вписывается в ваш репозиторий, а не выглядит как чужеродное вставление. CLAUDE.md для проекта — это как инструкция по сборке мебели: без неё можно собрать что-то, но скорее всего с лишними деталями и кривыми полками.

Отличие от системного промпта

Системный промпт задаёт общие правила поведения модели — как она думает, какие ограничения соблюдает, как форматирует ответ. CLAUDE.md работает на другом уровне: он описывает конкретный проект, о котором системный промпт ничего не знает.

Во-первых, системный промпт одинаков для всех проектов. CLAUDE.md уникален для каждого репозитория.

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

С практической точки зрения разница выглядит так. Системный промпт может сказать модели: «Пиши чистый код на Python». CLAUDE.md уточняет: «Используйте type hints, именуйте переменные в snake_case, бизнес-логика выносится в app/services, а не в роутеры».

Пример содержимого CLAUDE.md:

markdown
# CLAUDE.md

## Стиль кода
- Используйте type hints во всех публичных функциях.
- Именуйте переменные в стиле `snake_case`, константы — `UPPER_SNAKE_CASE`.
- Импорты сортируйте с помощью `isort`, форматируйте код через `ruff`.

## Архитектура
- Бизнес-логика живёт в `app/services`, не в роутерах FastAPI.
- Внешние API оборачиваются в адаптеры в `app/clients`.

## Тестирование
- Каждый новый эндпоинт покрывается тестом в `tests/api/`.
- Запускайте `pytest` перед коммитом.

Комментарий в коде объясняет, почему строка такая, а не пересказывает её. То же самое относится к CLAUDE.md: файл не дублирует системный промпт, он добавляет контекст, которого у модели нет по умолчанию.

Где файл должен лежать

Файл должен лежать в корне репозитория, рядом с .gitignore и README.md. Claude Code ищет его там при старте сессии. Если положить глубже — в docs/ или instructions/ — модель его не подхватит автоматически.

Структура типичного проекта:

text
.
├── CLAUDE.md
├── README.md
├── .gitignore
├── pyproject.toml
├── src/
└── tests/

Если проект монолитный и состоит из нескольких компонентов, можно положить несколько CLAUDE.md — по одному на компонент. Claude Code подхватит ближайший к текущей рабочей директории. Для начала достаточно одного файла в корне.

CLAUDE.md не панацея. Он не исправит ошибки в логике и не заменит код-ревью. Но он снижает вероятность того, что модель предложит решение, которое работает в вакууме, но ломается в вашем репозитории.

Наблюдения Кэрпати о ловушках LLM при кодировании

Наблюдения Кэрпати о ловушках LLM при кодировании

Андрей Кэрпати в своих наблюдениях за работой больших языковых моделей при написании кода выделил несколько повторяющихся проблем. Они проявляются независимо от размера модели и особенно заметны при использовании Claude Code. Две из них критичны для настройки CLAUDE.md: чрезмерная уверенность модели и игнорирование контекста репозитория.

Чрезмерная уверенность модели

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

Это напоминает стажёра, который уверенно заявляет, что собрал сервер, но забыл подключить кабель питания. Всё стоит на месте, индикаторы горят, а система не стартует. Модель ведёт себя так же — она не сомневается, потому что у неё нет механизма сомнения.

Пример из практики. Модель предлагает добавить в Dockerfile строку:

dockerfile
RUN apt-get update && apt-get install -y python3-pip && pip install some-package

Сборка пройдёт, но если в образе уже есть Python 3.11, а пакет требует 3.9, приложение упадёт при запуске. Модель не предупредит о конфликте, потому что она не запускала код — она только сгенерировала текст, который выглядит правдоподобно.

В CLAUDE.md я прописываю правило: модель должна явно помечать неопределённость. Если она не уверена в версии зависимости или в существовании API — она должна сказать об этом, а не выдумывать.

Пример инструкции для CLAUDE.md:

# CLAUDE.md

## Правила генерации кода

- Не предлагай код, если не уверен в точности API или версии зависимости.
- Если версия не указана в репозитории, укажи это явно и предложи проверить в package.json / requirements.txt / go.mod.
- Не выдумывай флаги командной строки. Если не уверен — предложи проверить `command --help`.

Это снижает количество ложных срабатываний и экономит время на отладке кода, который никогда не должен был быть написан.

Игнорирование контекста репозитория

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

Это как нанять подрядчика на ремонт, который не смотрит на проект дома и ставит розетки там, где удобно ему, а не там, где нужны хозяевам. Розетки работают, но в стене появилось лишнее отверстие, а проводка не соответствует общему плану.

Пример. В репозитории уже есть утилита для чтения конфигурации:

go
package config

func Load(path string) (*Config, error) {
    data, err := os.ReadFile(path)
    if err != nil {
        return nil, err
    }
    var cfg Config
    if err := yaml.Unmarshal(data, &cfg); err != nil {
        return nil, err
    }
    return &cfg, nil
}

Модель, не зная об этом, предлагает в другом файле написать свою версию:

go
func readConfig(path string) (Config, error) {
    // собственная реализация, дублирующая config.Load
}

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

Пример инструкции:

# CLAUDE.md

## Работа с репозиторием

- Перед внесением изменений изучи существующий код в каталоге.
- Если функция с похожей логикой уже существует — переиспользуй её, а не пиши новую.
- Следуй стилю именования и структуре каталогов, принятым в репозитории.
- Не дублируй код из пакетов, которые уже подключены в go.mod / Cargo.toml / requirements.txt.

Это делает изменения предсказуемыми. Когда код пишется в рамках одного стиля, его проще читать, рефакторить и поддерживать.

В следующем разделе разберём, как перевести эти наблюдения в конкретные правила для CLAUDE.md.

Как настроить CLAUDE.md для своих проектов

Как настроить CLAUDE.md для своих проектов

CLAUDE.md — это не инструкция для пользователя, а системный промпт для Claude Code. Модель читает его перед началом работы и старается следовать описанным правилам. Наблюдения Андрея Кэрпати о типичных ошибках LLM при кодировании показывают, что модель чаще всего ошибается там, где нет чёткого контекста: выдумывает несуществующие API, игнорирует типы, пишет код без обработки ошибок и не до конца понимает структуру репозитория. Хороший CLAUDE.md закрывает эти пробелы ещё до того, как модель начнёт генерировать.

Ниже — пример минимального файла и правила, которые я сам прописываю в своих проектах.

Пример минимального файла

Скопируйте этот шаблон в корень репозитория и подправьте под свой стек. Я обычно начинаю с минимального набора и добавляю правила по мере работы — не стоит пытаться описать всё сразу.

markdown
# CLAUDE.md

## Проект
- Стек: Python 3.11, FastAPI, PostgreSQL, Docker Compose
- Сборка и запуск: `docker compose up --build`
- Тесты: `pytest tests/`

## Стиль кода
- Пиши на Python 3.11, используй type hints во всех функциях
- Следуй PEP 8, длина строки — 88 символов
- Именование: snake_case для функций и переменных, PascalCase для классов

## Архитектура
- Бизнес-логика в `app/services/`, маршруты в `app/api/`, модели в `app/models/`
- Не смешивай слои: API-роутер не должен напрямую работать с БД

## Обработка ошибок
- Всегда оборачивай внешние вызовы в try/except с логированием
- Не возвращай сырые исключения клиенту, преобразуй в HTTPException с понятным detail

## Git
- Коммиты в формате conventional commits: feat, fix, docs, refactor
- Перед коммитом запусти `ruff check` и `pytest`

Этого достаточно для начала. Модель поймёт, какой стек используется, где лежит код и чего от неё ждать. Если в проекте есть особенности — например, кастомный мидлварь или нестандартная структура тестов — добавь отдельный пункт, иначе Claude Code будет гадать.

Какие правила стоит прописать

Я делю правила на четыре группы. Каждая закрывает конкретный класс ошибок, которые Кэрпати отмечал в работе LLM.

Контекст проекта

Укажи явно, что это за проект, какая у него цель и какие технологии используются. Без этого модель может предложить решение для другого стека или выдумать библиотеку, которой нет в зависимостях.

Пример:

markdown
## Контекст
Это внутренний API для обработки платежей. Стек: Go 1.22, Gin, PostgreSQL.
Не предлагай решения на Node.js или Python, если не оговорено отдельно.

Соглашения по коду

Опиши стиль, именование и структуру папок. LLM склонна к хаотичному именованию и смешению подходов, если не дать ей шаблон.

Пример:

markdown
## Стиль кода
- TypeScript, строгий режим, без `any`
- Компоненты React в `src/components/`, хуки в `src/hooks/`
- Именование файлов: kebab-case, компоненты — PascalCase

Обработка ошибок и краевые случаи

Одна из типичных ошибок LLM — написать «счастливый путь» и забыть про обработку ошибок. Пропиши это явно.

Пример:

markdown
## Надёжность
- Все сетевые запросы — с таймаутом и повторными попытками
- Не игнорируй ошибки от базы данных, всегда логируй с stack trace
- Валидируй входные данные на границе системы, а не внутри бизнес-логики

Работа с репозиторием

Укажи, как запускать тесты, линтер и сборку. Это защищает от ситуации, когда модель предлагает код, который не проходит даже базовую проверку.

Пример:

markdown
## Разработка
- Запуск тестов: `make test`
- Проверка типов: `make typecheck`
- Линтер: `golangci-lint run ./...`

Если в проекте есть Makefile или скрипты в package.json, сошли на них ссылку, а не дублируй команды. Модель и так читает репозиторий, ей достаточно знать, где смотреть.

С практической точки зрения, начните с минимального файла и добавляйте правила по мере работы. Если заметили, что Claude Code повторяет одну и ту же ошибку — добавьте правило против неё в CLAUDE.md. Это работает быстрее, чем объяснять модель в каждом новом чате.

Ограничения и когда подход не работает

Ограничения и когда подход не работает

CLAUDE.md — это не волшебная кнопка, а дополнение к системному промпту. Модель читает его в начале сессии, но это не гарантирует, что она будет следовать каждому правилу в каждой ситуации. Инструкции работают как рекомендации, а не как жесткие ограничения компилятора.

Во-первых, у модели есть контекстное окно. Если CLAUDE.md раздут до нескольких тысяч токенов, важные правила могут вытесниться длинными логами, выводом команд или историей переписки. С практической точки зрения, файл должен быть коротким — до 200–300 строк, иначе модель начнёт игнорировать хвост.

Во-вторых, инструкции в файле не отменяют обучающую выборку. Если в CLAUDE.md написано «всегда добавляйте type hints», а модель видит в репозитории сотни функций без аннотаций, она может решить, что локальная конвенция важнее вашего файла. Пример:

python
# Модель сгенерирует так, несмотря на CLAUDE.md
def process_data(data):
    result = []
    for item in data:
        result.append(item.transform())
    return result

В-третьих, модель не может выполнить команду за вас. Она может посоветовать запустить тесты, но не запустит их сама и не увидит результат, пока вы не скопируете вывод обратно в чат. Инструкция «перед коммитом прогоняй pytest» остаётся пожеланием.

Наконец, конфликт инструкций. Если вы пишете в чате «сделай быстро, без тестов», а в CLAUDE.md прописано «тесты обязательны», модель часто выберет текущий запрос пользователя. Статический файл не перебивает прямой приказ в диалоге.

Когда инструкции не помогают

Даже краткий и грамотно написанный CLAUDE.md бессилен перед рядом паттернов поведения LLM.

Первый паттерн — выдуманные API. Модель может уверенно импортировать несуществующий метод из библиотеки, потому что такое сочетание имен часто встречается в обучающих данных. Никакое правило «используй только документированные функции» не остановит галлюцинацию, если модель не имеет доступа к актуальной документации в контексте.

Второй паттерн — игнорирование границ файлов. Вы просите отрефакторить одну функцию, а модель переписывает три смежных модуля, ломая импорты. CLAUDE.md с пунктом «не трогай лишнее» не помогает, потому что модель не видит последствий своих изменений до тех пор, пока вы не запустите тесты.

Третий паттерн — ложная уверенность. Модель может утверждать, что код рабочий, хотя не запустила его ни разу. Инструкция «проверяй код перед отправкой» не имеет смысла, если у модели нет инструментов для верификации.

Альтернативы CLAUDE.md

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

Первая альтернатива — репозиторий как источник истины. Вместо того чтобы объяснять модели стиль кода, подключите линтер и форматтер:

yaml
# .pre-commit-config.yaml
repos:
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.5.0
    hooks:
      - id: ruff
        args: [--fix]
      - id: ruff-format

Теперь модель может предложить код с нарушениями, но pre-commit не пустит коммит дальше. Это работает даже если CLAUDE.md проигнорирован.

Вторая альтернатива — Makefile с целями проверки. Описываете один раз, запускаете всегда:

makefile
.PHONY: check test lint
check: lint test

lint:
	ruff check .
	ruff format --check .

test:
	pytest -q

Третья альтернатива — инструкции прямо в чате. Для разовой задачи проще написать «рефакторь эту функцию, добавь типизацию и комментарии к сложным участкам», чем править глобальный файл. Такие инструкции живут только в рамках сессии, но зато не конфликтуют с другими проектами.

Четвёртая — агентный подход с явными этапами: план → реализация → тесты → ревью. CLAUDE.md может описывать эти этапы, но реальная польза появляется, когда вы сами контролируете переход от одного к другому, а не полагаетесь на модель.

Итог простой: CLAUDE.md полезен для общих предпочтений, но не заменяет CI, линтеры и человеческую проверку. Если правило важно, оно должно быть в коде, а не только в маркдауне.

Часто задаваемые вопросы

Нужно ли отдельный CLAUDE.md для каждого репозитория?

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

Что писать в CLAUDE.md, если проект только начинается?

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

Следует ли Claude Code правилам из CLAUDE.md безоговорочно?

Нет, это скорее сильная подсказка, а не жесткое ограничение. Модель может проигнорировать правило, если задача сформулирована нечётко, или предложить альтернативное решение. Поэтому вместо фразы «пишите чистый код» укажите «используйте type hints и именуйте переменные в стиле snake_case».

Как часто нужно обновлять CLAUDE.md?

Обновляйте, когда меняется архитектура, добавляются новые зависимости или появляются повторяющиеся ошибки модели. С практической точки зрения, если Claude Code начал предлагать код, который не вписывается в репозиторий, значит инструкции устарели. Рассматривайте файл как живой документ, который правится вместе с рефакторингом.

Можно ли использовать CLAUDE.md вместе с README.md и AGENTS.md?

Можно, но они решают разные задачи. README.md читают люди, AGENTS.md — другие агенты и инструменты, а CLAUDE.md — конкретно Claude Code в начале сессии. Не дублируйте одно и то же в трёх файлах, иначе модель запутается в противоречиях.

Поделиться:TelegramX / TwitterVK