Як скоротити гігантський CLAUDE.md на 91% і виміряти, що зламалося
Розбийте CLAUDE.md на 194K символів на скіли, довідкові файли й правила з прив'язкою до шляхів, переконайтеся, що нічого не загубилося, і виміряйте, як часто скіли насправді спрацьовують.
Уявіть, що кожна сесія в репозиторії починається із завантаження CLAUDE.md на 194 492 символи. Це приблизно 48 600 токенів ще до того, як ви щось надрукували, і так на кожному повідомленні, а сам файл майже вп'ятеро більший за поріг, після якого Claude Code починає попереджати про розмір файлу пам'яті. А тепер уявіть, що сміття там немає. Це два роки здобутої важкою працею експлуатаційної пам'яті: команда міграції, яка мовчки видаляє індекс, індекс місць, що безкінечно повторює спробу з тим самим місцем, функція кольору, синтаксис виводу якої не змогли прочитати два інструменти перевірки контрасту. Видалити все це не варіант.
Робочий шлях скоротив файл до 17 283 символів, тобто на 91%, і загубилося лише чотири слова — усі із заголовків, видалених навмисно. Далі йшла частина, до якої мало хто доходить: перевірити, чи реструктуризація справді спрацювала. Нижче весь метод, разом із помилкою.
Застереження, перш ніж пробувати. Реструктуризація переписує CLAUDE.md на місці й створює файли в .claude/, тож перед початком зробіть коміт або stash — тоді git checkout усе відкотить. Тестовий стенд запускає справжні headless-сесії Claude Code, по одній на промпт, витрачаючи квоту API й іноді по кілька хвилин на кожну. Спершу спробуйте два-три промпти, а не двадцять. І оскільки всі кодові бази різні, читайте кожну команду й скрипт, перш ніж запускати їх у себе.
Чому очевидні рішення не працюють
Видалити застаріле звучить розумно, але зрозуміти, що застаріло, неможливо, не перечитавши код, який описує кожна нотатка. «Схоже, це вже неактуально» — здогадка, і хибна здогадка видаляє ту саму нотатку, яка врятувала б майбутню сесію налагодження.
Переказ — небезпечний варіант, і йому нижче присвячено окремий розділ.
Розбиття через @import теж не допомагає. Імпорти розгортаються на місці, тож файл стає охайнішим, а ціна за контекстом лишається тією самою.
Справжня проблема не в розмірі. Вона в тому, що все завантажується для кожної задачі, включно з 90%, які не стосуються поточної. Баґу в CSS ні до чого правила порядку вебхуків Stripe.
Три шари
Думайте рівнями: компактне ядро, яке завантажується завжди, скіли, що підтягуються, коли модель вирішує, що їхній опис пасує до задачі, і довідкові файли, які відкриваються лише за потреби. Четвертому механізму приділяють замало уваги. Файли правил у .claude/rules/ можуть містити frontmatter paths:, і тоді вони завантажуються, щойно ви торкаєтеся відповідних файлів. Це зіставлення за glob-шаблоном, і ніхто нічого не вирішує.
Підсумок: CLAUDE.md на 17KB плюс 12 скілів і 28 довідкових файлів.
Що лишити завантаженим завжди
Скіл завантажується, коли модель вирішує, що його опис підходить. Це судження дуже добре, але все ж судження. Тому питання «це важливо?» — неправильний тест, адже у файлі важливим було все. Запитайте інакше: якщо це правило не завантажиться саме тоді, коли воно потрібне, наскільки це буде погано?
Пастка зі стилями коштує вам трохи часу. Збій правила безпеки означає, що ви викотите той самий баґ, заради запобігання якому воно існує. Тому всі правила безпеки лишилися постійними, усі 26, плюс 21 архітектурний інваріант (база даних на кожного орендаря, журнал лише на додавання, частковий унікальний індекс, що розв'язує конкуренцію за місця) і команди, які потрібні постійно й коштують мало. Комісії, бронювання, сповіщення, мобільні застосунки, рендеринг сторінок, практики тестування й список відомих прогалин — усе це переїхало назовні.
Витягуйте правила, а не переписуйте
Утиснути 47 правил приблизно у 200 рядків — велика спокуса переписати кожне в чітке однорядкове формулювання. Не треба. Рядок із власного посібника репозиторію, написаний після гіркого досвіду, каже про це точно: застаріле твердження, яке відредагували без перевірки, не виправлене, а відмите, тож або перечитайте код, який описує рядок, або не чіпайте його.
Переказ 47 неперевірених правил дає 47 упевнених тверджень, які ніхто не перевіряв, і виглядають вони як щойно переглянуті, що гірше, ніж виглядати старими.
Вихід у тому, що ваші правила, найімовірніше, уже починаються із самого правила в першому реченні. Візьміть це речення дослівно, а обґрунтування перенесіть у довідковий файл. Нічого не переписується. Правило живе в CLAUDE.md, а «чому» лежить на відстані одного переходу. Постійний запис виглядає так:
- **The card never touches this server.** A SetupIntent hands the browser a
client secret and Stripe's own SDK collects the number, which is why no
endpoint here takes one.
Одне речення лишається завантаженим, а решта 400 слів обґрунтування йдуть у hard-rules/references/security.md.
Два записи починалися не з інструкції, а зі знахідки — наприклад, як велика літера переводила анонімного краулера в ліміт запитів для учасників студії. Кожен із них також закінчувався реченням, що починалося з "The general rule" («Загальне правило»), і цей рядок перенесли як є.
Доведіть, що нічого не зникло
Порядковий diff нічого не дає: перенесений текст переформатовується, і все виглядає зміненим. Зіставлення речень трохи краще, але жирне виділення й заголовки зсувають початок і кінець речень. Підрахунок слів як мультимножини оминає обидві проблеми: кожне слово зі старого корпусу має трапитися в новому не рідше, ніж раніше.
Фінальний прогін показав, що з 31 697 входжень слів зникли 4: Traps, bitten, Invariants і simplify, усі з двох видалених заголовків розділів. Ось так виглядає «готово».
Ще переконайтеся, що перевірка падає, коли має падати. Видалення однієї теки скіла й повторний прогін дали 2522 втрати, зокрема слово fee сорок разів. Перевірка, яку ви жодного разу не бачили проваленою, — не перевірка.
Помилка
Скрипт збирання дописував перенесені записи у два наявні файли скілів, і під час ітерацій його запустили двічі. У підсумку вийшло 36 блоків записів там, де мало бути 28, — тихе дублювання, той самий збій, про який попереджає кожен посібник. Його впіймали лише тому, що кожен запис перераховували по всіх файлах і перевіряли, що він трапляється рівно один раз. Додайте таку перевірку. Зробіть скрипт ідемпотентним або хай він перезаписує файли, а не дописує в них.
Вимірюйте, а не вірте цитованим цифрам
Одна популярна цифра каже, що скіли спрацьовують приблизно у 79% випадків проти 100% у правила, яке лежить просто в CLAUDE.md. Як попередження це корисно, але це вимірювання однієї людини на її власній конфігурації, а не константа. Виміряйте свою:
- Напишіть 14 промптів, які міг би набрати реальний користувач, що охоплюють усі скіли й сформульовані як симптоми, а не теми. "The Booked screen crashes with RangeError" («екран Booked падає з RangeError») підходить. "Tell me about the mobile app" («розкажи про мобільний застосунок») сама підказує відповідь.
- Запускайте кожен у свіжій headless-сесії через
claude -p. Сесія, яка проводила реструктуризацію, уже тримає в контексті всі скіли, тож розпитувати її, що б вона завантажила, марно. - Зберігайте
session_idкожного прогону через--output-format json, щоб паралельні перевірки не переплуталися. - Відкрийте транскрипт цієї сесії й позначте, які скіли були завантажені.
- Заблокуйте
EditіWrite, щоб вимірювання не могло змінити репозиторій, який вимірює.
Успіхом вважайте дві події: виклик інструмента Skill або ручне відкриття моделлю файлу скіла. Якщо вона дісталася потрібних знань, прочитавши файл, це теж зараховується.
Результат — 13 із 14, тобто 93%, а не 79%. І за кожного влучання скіл спрацьовував найпершим викликом інструмента, до відкриття будь-якого файлу.
Промах коштує грошей, а не правильності
Єдиний промах усе одно дав правильну відповідь. Просто знання довелося відновлювати з нуля: 56 викликів інструментів проти медіанних 16 за влучань. Модель перечитала чотири вихідні файли й пройшлася grep по API, щоб вивести те, що скіл дав би за одне читання. Постійний шар спрацював і як страховка: жорсткого правила про календарні дати вистачило, щоб однаково спрямувати її до потрібного довідника.
Це змінює погляд на ризик. Промах не означає, що правило не застосовано. Він означає сесію приблизно в 3,5 раза дорожчу — значно менш страшний збій.
Промах виявився помилкою в тексті
Обидва промпти про мобільний застосунок цілилися в той самий скіл, але спрацював лише той, у якому було слово "Expo". Опис скіла рекламував інструменти: фіксацію версії SDK, Metro під pnpm і керування симулятором. А ще в ньому були пастки на рівні екранів: кнопка Book для заняття, на яке учасник уже записаний, поле дати, що падає. Промпт про падіння екрана Booked не збігся з жодним із рекламованих слів.
Тому описуйте симптоми, а не інструменти. Запитайте себе, що користувач побачить насправді. Слабкий опис перелічує налаштування pnpm, glob-шаблони тестів Node, вивід tsc і будову Docker-образу. Сильний спрацьовує, коли збирання ламається з причин поза самим кодом, наприклад MODULE_NOT_FOUND, відсутній query engine, роздутий образ або виправлення, що працює лише з другої спроби.
Після того як усі 11 описів переписали так і перевірили сім нових промптів у формулюванні симптомів, результат склав 7 із 7, і щоразу на першому виклику інструмента. Промпт, який раніше схибив, тепер влучив і витратив 26 викликів замість 56.
Правила з прив'язкою до шляхів як друга сітка
Для всього, що відповідає якійсь теці, .claude/rules/*.md повністю прибирає потребу в судженні:
---
paths:
- "apps/mobile/**"
- "apps/mobile-yoga/**"
---
You are in one of the two Expo member apps.
**Read `.claude/skills/mobile-apps/SKILL.md` before changing anything here.**m
Тримайте їх як вказівники, а не копії, щоб знання жило рівно в одному місці.
Двобічний канарковий тест показує, чи прив'язка справді працює, бо glob, який нічому не відповідає, ззовні поводиться точнісінько як робочий. Створіть правило, прив'язане до однієї теки, з текстом, який велить Claude вивести вигаданий рядок-маркер. Відкрийте файл у цій теці — маркер має з'явитися. Відкрийте файл деінде — маркера бути не повинно.
Останній крок більшість пропускає. Без нього не відрізнити «працює» від «завантажується завжди», а друге непомітно з'їдає всю економію. Тут обидві перевірки поводилися як слід: 1 і 0.
Одне застереження: пишіть glob-шаблони під реальну структуру. Перша здогадка була apps/api/src/fees/, але комісії, абонементи й пакети занять насправді жили в apps/api/src/billing/. Без перевірки ці правила не збігалися б ні з чим — мовчки й назавжди.
Чого це коштує
Корпус зріс на 14%, із 194 492 до 220 885 символів. Ці зайві 26 393 символи — frontmatter, індексні таблиці й вказівники, нових знань у них немає; вони потрібні, щоб правильний файл знайшов вас. Правки тепер зачіпають більше файлів: одна зміна перетворилася на три. Таблиця маршрутизації в CLAUDE.md зменшує ризик застарівання, але не усуває його. І ви міняєте файл, який завжди трохи роздутий, на той, що зазвичай компактний, а іноді обходиться дорого. Це обмін, який варто повторювати, якщо чесно визнавати, що він не безкоштовний.
Готова версія
Метод запаковано в плагін для Claude Code із двома скілами: один виконує реструктуризацію з вбудованими правилами безпеки, другий вимірює, чи ваші скіли справді спрацьовують. Встановлення:
/plugin marketplace add your-org/claude-md-progressive-disclosure
/plugin install progressive-claude-md
Потім скажіть Claude, що ваш CLAUDE.md завеликий, і попросіть його реструктурувати, а згодом попросіть виміряти, чи спрацьовують скіли.
Хай би що ви винесли з цього тексту, виміряйте власний відсоток влучань, перш ніж щось будувати для виправлення. Тут вихідний рівень був 93% ще до будь-яких змін, а єдиним справжнім дефектом виявилося погано написане речення, а не архітектура.