# Память проекта по-взрослому

Курс: Claude Code: уровень профи — https://zero2claude.ru/learn/claude-code-pro
Канонический URL: https://zero2claude.ru/learn/claude-code-pro/5-1-pamyat-proekta

Длинный CLAUDE.md загружается целиком в каждую сессию. Импорт @path делит его на файлы, правило в .claude/rules с полем paths загружается только тогда, когда Claude читает подходящий файл. А /context all и хук InstructionsLoaded показывают, что на самом деле загрузилось.

Ты уже умеешь писать CLAUDE.md. Но у большого проекта он быстро разрастается: команды, договорённости, правила для API, для тестов, для вёрстки. И **каждая строка** загружается в каждую сессию — даже когда ты правишь README.

Два инструмента помогают навести порядок: импорт и правило.

## Импорт: @path

Строка с `@` и путём подгружает другой файл вместе с CLAUDE.md:

```markdown
# Проект linkcheck

@AGENTS.md

- Команды npm: @package.json
- Архитектура: @docs/architecture.md
```

Импорт упорядочивает память, но **контекст не экономит**: импортированный файл загружается всегда, вместе с тем, кто его импортирует.

Две мелочи, на которых спотыкаются:

- путь тянется до первого пробела — не ставь точку сразу после него;
- путь считается от файла, в котором стоит импорт, а не от папки, где ты запустил Claude.

Импорт файла вне рабочей папки, например `@~/notes.md`, при первом использовании в проекте попросит твоего одобрения. Откажешь — он так и останется выключенным.

## AGENTS.md и CLAUDE.md

Если в проекте уже есть `AGENTS.md` для других агентов, учти: **когда существует CLAUDE.md, Claude читает его вместо AGENTS.md**. Чтобы не дублировать правила, поставь первой строкой CLAUDE.md импорт `@AGENTS.md`.

## Правило: .claude/rules

Правило — это Markdown-файл в папке `.claude/rules/`. Без заголовка `paths` оно загружается при старте, как обычный CLAUDE.md. С заголовком — только когда Claude работает с подходящим файлом:

```markdown
---
paths:
  - "test/**/*.js"
---

# Тесты

- Используй node:test и node:assert/strict, других библиотек не подключай.
```

Шаблоны считаются **от корня проекта**. `*` не выходит за пределы одной папки, `**/` проходит через любое число папок, а фигурные скобки вроде `src/**/*.{ts,tsx}` тоже работают.

Главная тонкость: правило с `paths` срабатывает, когда Claude читает совпадающий файл **своим инструментом Read**. Если он посмотрел файл командой `cat` в оболочке, правило не подгрузится. Поэтому при проверке так и проси: «прочитай test/config.test.js инструментом Read».

## Что и когда загружается

| Файл инструкций | Когда загружается |
|---|---|
| CLAUDE.md в корне и правило без `paths` | при старте сессии |
| файл из импорта `@path` | вместе с файлом, который его импортирует |
| правило с `paths` | когда Claude читает подходящий файл инструментом Read |
| автопамять — заметки, которые Claude ведёт сам | при старте: первые 200 строк или 25 КБ индекса MEMORY.md |

Для личных инструкций к этому проекту есть `CLAUDE.local.md`. Его создают руками и не коммитят — как раз об этом урок про общий набор для команды.

## Почему Claude не слушается

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

Первый способ — `/context all`. Простой `/context` может свернуть список, а `all` раскрывает его. В разделе **Memory files** видны файлы, загруженные при старте. Правила с `paths` там появятся только после чтения подходящего файла.

Второй способ — хук `InstructionsLoaded`. Он срабатывает при каждой загрузке CLAUDE.md, правила или импорта. Положи его в отдельный файл, например `.practice/loaded-hook.json`:

```json
{
  "hooks": {
    "InstructionsLoaded": [
      { "hooks": [ { "type": "command", "command": "jq -r '[.load_reason, .file_path] | @tsv' >> \"$CLAUDE_PROJECT_DIR/.practice/loaded.txt\"" } ] }
    ]
  }
}
```

И запусти сессию с ним: `claude --settings .practice/loaded-hook.json`. В логе у каждой строки есть причина:

- `session_start` — загружен при старте, как CLAUDE.md;
- `include` — подтянут импортом;
- `path_glob_match` — правило сработало по шаблону.

Если строки `path_glob_match` для твоего правила нет, сравни шаблон с настоящими файлами. Помогает git:

```bash
git ls-files ':(glob)src/api/**/*.js'
```

Пустой вывод — шаблон не совпадает ни с одним файлом. Классика: правило для `source/**` в проекте, где код лежит в `src/`.

## Правка посреди сессии

Claude Code читает CLAUDE.md проекта **один раз, при старте**. Поправил файл — правка дойдёт до сессии после `/clear`, `/compact` или перезапуска.

А чтобы найти инструкции, которые противоречат друг другу или ссылаются на удалённые файлы, запусти `/doctor prompt-audit`. Он предложит правки и ничего не изменит, пока ты не попросишь.

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