«Скучная часть работы с базой знаний — не чтение и не размышление, а бухгалтерия». Так Андрей Карпаты объясняет, почему люди бросают свои вики: издержки на поддержку растут быстрее, чем польза. Гист llm-wiki.md, опубликованный 4 апреля 2026 года, — это не библиотека, не бенчмарк и не модель, а описание паттерна на полторы тысячи слов, которое предлагается скопировать своему агенту и дальше инстанцировать вместе с ним. 22 сентября мы это сделали в одном из своих продакшен-проектов — AI Budget Assistant — и за один день вынесли из главного файла проекта 24 616 слов. Ниже: что это за паттерн, во что он у нас превратился и, главное, что в нашей реализации пока не работает.
Что предложил Карпаты
Обычный опыт работы с языковой моделью и документами выглядит как RAG (Retrieval-Augmented Generation) — это когда ИИ сначала находит нужную информацию в ваших документах, а потом отвечает, опираясь на неё, а не на догадки. Полное определение →: вы загружаете коллекцию файлов, модель на каждый вопрос достаёт релевантные фрагменты и генерирует ответ. Это работает, но знание каждый раз открывается заново. Задайте вопрос, ответ на который требует синтеза пяти документов, — и модель будет заново искать и склеивать фрагменты. Ничего не накапливается. Так устроены и NotebookLM, и загрузка файлов в чат, и большинство RAG-систем.
Идея гиста в другом. Между вами и исходниками появляется LLM wiki — база знаний из markdown-файлов, которую поддерживает языковая модель: она читает новые источники и сама встраивает их в уже существующие страницы вместе с перекрёстными ссылками, вместо того чтобы искать всё заново на каждый вопрос. Паттерн описал Андрей Карпаты. Полное определение → — структурированная, перелинкованная коллекция markdown-файлов, которую модель строит и поддерживает инкрементально. Новый источник не просто индексируется на будущее: модель читает его, извлекает существенное и встраивает в уже существующую вики — правит страницы сущностей, пересматривает сводки по темам, отмечает, где новые данные противоречат старым утверждениям. Знание компилируется один раз и дальше поддерживается в актуальном состоянии, а не выводится заново на каждый запрос.
В этом всё отличие: вики — артефакт, который накапливается. Перекрёстные ссылки уже проставлены. Противоречия уже отмечены. Синтез уже учитывает всё прочитанное. Сами вы её почти не пишете — пишет модель; ваша работа — источники, направление и правильные вопросы. Карпаты описывает свою расстановку так: агент в одном окне, Obsidian в другом, правки видны в реальном времени. Obsidian как IDE, модель как программист, вики как кодовая база.
Три слоя и три операции
| Слой | У Карпаты | У нас |
|---|---|---|
| Сырые источники | Неизменяемая коллекция статей, PDF и изображений | Такого слоя нет — источник истины сам код, а вики его конспектирует |
| Вики | Каталог markdown-файлов, которым владеет модель | Хабы доменов в корне, страницы фич во вложенной папке |
| Схема | Файл конвенций и процессов, например CLAUDE.md или AGENTS.md | CLAUDE.md: правила репозитория и указатель на индекс, без описаний фич |
| Индекс | Каталог всех страниц с однострочным описанием | Хаб на домен, страница на фичу и одно правило о том, как читать страницу |
| Журнал | Хронологическая запись: ингесты, запросы, проходы линта | Те же три секции, одна строка на запись — журнал это цель поиска, а не вторая вики |
Операций тоже три. Ingest — приходит новый источник, модель его читает, обсуждает с вами выводы, пишет страницу-сводку, обновляет индекс и все затронутые страницы, дописывает строку в журнал; один источник может задеть десять-пятнадцать страниц. Query — вы задаёте вопрос, модель находит нужные страницы, читает их и отвечает со ссылками на источник; и самое важное — хороший ответ возвращается в вики новой страницей, чтобы ваши исследования накапливались наравне с источниками. Lint — периодическая проверка здоровья: противоречия между страницами, устаревшие утверждения, страницы-сироты без входящих ссылок, важные понятия без собственной страницы, недостающие перекрёстные ссылки, пробелы в данных.
Отдельно стоят два служебных файла. Индекс ориентирован на содержание: каталог всего, что есть в вики, со ссылкой и однострочным описанием на каждую страницу. Журнал ориентирован на время: append-only запись того, что и когда произошло. Карпаты отмечает, что при сотне источников и сотнях страниц одного индекса хватает и инфраструктура на эмбеддингах не нужна вовсе.
Чем это отличается от RAG и от обычной документации
От RAG — тем, где происходит синтез. В RAG он происходит в момент ответа и умирает вместе с ответом. В вики он происходит в момент приёма источника и остаётся на диске. Стоимость вопроса падает не потому, что поиск стал лучше, а потому, что отвечать уже почти не на что: половина работы сделана заранее.
От обычной документации — тем, кто платит за обслуживание. Документация деградирует не из-за лени, а потому, что бухгалтерия перекрёстных ссылок стоит дорого, а её ценность размазана по будущему. Модель не устаёт, не забывает обновить ссылку и может тронуть пятнадцать файлов за один проход. Стоимость поддержки падает почти до нуля — и это единственная причина, по которой вики вообще может выжить.
Но есть условие, которое в гисте сказано мягко, а у нас оказалось жёстким: должен быть цикл, а не единоразовый акт. Мы это выяснили самым дорогим способом.
Почему мы за это взялись: 104 тысячи токенов до первой строчки кода
AI Budget Assistant — монорепозиторий: API — это интерфейс, через который две системы обмениваются данными автоматически, без выгрузок в Excel и копирования руками. Полное определение → на NestJS, мобильное приложение на Expo, админ-панель на Next.js, три чат-бота и два общих пакета. Его CLAUDE.md — файл, который агент загружает целиком в каждую сессию, — дорос до 77 100 слов. Это примерно 104 тысячи Токен — это фрагмент текста, обычно часть слова: ИИ-модели измеряют в токенах и длину запроса, и стоимость, поэтому счёт приходит за токены, а не за вопросы. Полное определение →, 187 верхнеуровневых пунктов, и самый большой из них — 4 629 слов.
Файл был точным. Ритуал завершения задачи дописывал в него всё, что выяснялось по ходу работы, и это честно работало. Неправильной была форма: агент платил 104 тысячи токенов до того, как начинал работу, а чтобы найти один факт, приходилось грепать файл, в котором нет навигации. Пункт на 4 629 слов — это уже не документация, это четыре разные темы под одним заголовком.
Вики, которая врала четыре месяца
Самое интересное: каталог docs/wiki в этом репозитории уже существовал. Пятнадцать страниц, написанных в мае, в хорошей форме. Проблема была одна — после мая в них ни разу ничего не заносили.
К сентябрю вики утверждала: 11 AI-функций — их было 18; 8 языков — девять; 30 модулей API — сорок восемь. Файл трендов здоровья содержал ровно одну точку данных, от 14 мая.
Это не безобидно. Устаревшая вики хуже отсутствующей: агент читает её и уверенно сообщает неверное число, а человек, получивший это число, не имеет повода его перепроверять. Отсутствующая страница хотя бы отправляет читать код.
Первый же читающий проход после запуска нашёл десять устаревших утверждений на двух страницах. Худшим было описание синхронизации: страница объявляла общую очередь путём синхронизации мобильного приложения, тогда как у двух ключевых функций этой очереди ноль мест вызова во всём репозитории. Три из тех же ошибок жили и в CLAUDE.md — их поправили там же.
Наше решение: CLAUDE.md становится схемой
Мы записали дизайн отдельным документом перед работой — четыре решения, и каждое из них закрывало конкретный способ умереть.
Первое: CLAUDE.md перестаёт быть хранилищем содержимого и становится схемой — тем самым третьим слоем из гиста. В нём остаются правила уровня репозитория, конвенции, инварианты, не принадлежащие ни одной отдельной фиче, переменные окружения, процедура деплоя и указатель на индекс. Всё фактическое про конкретную фичу уезжает на страницу вики. Один источник истины — потому что вики рядом с живым, пополняемым CLAUDE.md это ровно то, как умерла предыдущая вики.
Второе: миграция инкрементальная, никогда не одним проходом. Задача, которая трогает фичу, переносит её описание из CLAUDE.md на страницу как часть этой же задачи. Перенести 77 тысяч слов за один присест — механическая работа с высоким шансом растерять нюансы, а нюансы здесь и есть вся ценность.
Третье: два уровня — хабы доменов и страницы фич. Пятнадцать существующих страниц становятся хабами: что это за домен, где точки входа, ссылки на страницы фич под ним. Гранулярность совпала с тем, как приходит работа: одна задача — обычно одна фича, значит у задачи всегда есть очевидная целевая страница. Это мелочь, но именно она превращает ингест из решения в рефлекс.
Четвёртое: хабы лежат в корне каталога вики (имена файлов сохранены — на них уже ссылаются из других мест), а страницы фич — во вложенной папке.
Шаблон страницы и секция, ради которой её открывают
Шесть секций, одна форма на всю вики. Что это — два-три предложения: какую проблему решает и для кого. Точки входа — файлы с путями, откуда начинать читать. Ключевые понятия — механизм, а не туториал. Инварианты — что не должно сломаться, сформулированное как правило, с причиной. Известные пробелы — что намеренно не сделано и почему, чтобы не передумывать заново. История — ссылки на issue: почему это устроено именно так.
Инварианты — та секция, ради которой страницу открывают, и именно её в старой вики не было. «Не возвращать вызов обновления времени синхронизации на каждый маршрут», «резолвить серверный первичный ключ прежде, чем использовать идентификатор как внешний ключ» — эти фразы были в CLAUDE.md, но похоронены внутри четырёхтысячесловных пунктов и достижимы только грепом.
Два правила про честность формы. Секцию, которая действительно пуста, лучше опустить, чем написать в ней «нет»: отсутствующая секция честно читается как «ещё не разбирались», а слово «нет» читается как утверждение. И страница не имеет права называть число: счётчики протухают молча, поэтому когда аудит находит на странице число, правильная правка — удалить его, а не обновить. Эта статья — датированный артефакт, и числа в ней есть; у страницы вики такой привилегии нет.
Три ритуала
| Операция | Наш ритуал | Что после него остаётся |
|---|---|---|
| Ingest | Закрытие задачи: issue, страница фичи, строка в журнале | Обновлённая страница и одна строка в секции ингестов |
| Query | Сначала вики, потом код; ответ со ссылкой на путь страницы | Находка, дописанная на страницу, и строка в секции запросов — даже если код не менялся |
| Машинный линт | Два python-скрипта еженедельно в CI, без вызова модели | Комментарий к одному долгоживущему issue: мёртвые ссылки, сироты, отставшие страницы |
| Читающий линт | Аудит в сессии: две-три страницы как следует, а не беглый просмотр всех | Исправленные утверждения и строка в секции проходов линта |
Про Query стоит сказать отдельно, потому что в первой версии нашего дизайна этого пункта не было — и без него паттерн собран наполовину. Ingest накапливает знание из изменений. Если к нему не добавить Query, вики никогда не начнёт накапливать знание из вопросов: сессия, потратившая час на доказательство того, почему что-то ведёт себя именно так, и не изменившая ни строчки кода, не оставляет следа вообще. Диагноз, заканчивающийся словами «всё работает правильно», — худший случай: у фикса остаётся хотя бы коммит и issue, у чистого диагноза не остаётся ничего, и именно его следующая сессия будет исследовать заново.
Отдельное правило того же ритуала: отвечать со ссылкой на страницу, по пути. Ответ без ссылки неотличим от выдуманного на месте, и человек, который его читает, не может ни проверить источник, ни улучшить его. И если страница разошлась с кодом — это находка сама по себе: страницу правят в том же ответе, а не обходят молча.
Почему в нашем CI нет ни одного вызова модели
Линт разделён на две части по принципу «что где вообще может выполняться».
Машинно-проверяемое работает еженедельно в CI. Первый скрипт проверяет, что каждая ссылка между страницами резолвится в существующий файл, что каждый процитированный путь есть на диске и что ни одна страница фичи не осталась сиротой без ссылки из индекса. Второй сравнивает дату последнего коммита страницы с датами коммитов файлов, которые она цитирует, и сообщает о страницах, чей код ушёл вперёд на три и более коммита. Первый возвращает ненулевой код, второй — всегда нулевой: это отчёт, а не шлагбаум. Никто не должен быть заблокирован на мердже из-за того, что страница отстала на неделю. Оба сходятся комментарием к одному долгоживущему issue, а не новым issue каждую неделю — иначе репозиторий зарастёт почти одинаковыми отчётами, которые перестанут читать.
Ни один шаг этого workflow не вызывает модель, и это не аскетизм. Claude Code в проекте работает по подписке, а значит API-ключа, который можно положить в секреты репозитория, просто нет — и job, которому ключ нужен, никогда бы не запустился. Поэтому читающая половина линта — противоречия между страницами, недостающие перекрёстные ссылки, пробелы в данных — оформлена как скилл, который запускают внутри сессии, где модель уже оплачена. Отчёт о протухании служит ей порядком приоритета: страница с двадцатью коммитами позади — то место, куда смотреть в первую очередь; страница с тремя, скорее всего, требует только взгляда.
И ещё одно правило, выведенное из прошлого провала: читать две-три страницы как следует, а не пробегать глазами все. Беглый просмотр с выводом «выглядит нормально» — ровно тот механизм, которым предыдущая вики оставалась неверной четыре месяца.
Где мы намеренно разошлись с гистом
Три отличия, и все три — следствие того, что наш нижний слой не такой, как у персональной вики.
У нас нет слоя raw sources. У Карпаты нижний слой — неизменяемая коллекция статей, PDF и изображений. У нас источник истины — сам код, а вики его конспектирует. Это меняет природу ошибки. У персональной вики источник статичен, и страница расходится с ним, только если её плохо написали. У нашей источник меняется каждый день, поэтому страница может стать неверной, не будучи изменённой ни разу. Отсюда отчёт о протухании, которого в гисте нет вообще: нам нужен сигнал «под страницей сдвинулась земля».
Мы запретили числа на страницах. В личной вики число — факт из источника. У нас число — почти всегда счётчик чего-то в репозитории, и протухает он первым. Это прямое следствие «11 AI-функций при 18»: если страница не называет число, она не может назвать его неверно.
Мы не строим поиск. Гист предлагает qmd — локальный поисковик по markdown с гибридным BM25 и векторным поиском. Пока индекса достаточно: вики читается по путям, ровно так же, как агент читает код. Никаких эмбеддингов и векторных хранилищ — и это решение мы пересмотрим, когда индекс перестанет помещаться в один взгляд, а не раньше.
Что дал первый день
Одна задача-адопция и два обычных таска с ингестом — и CLAUDE.md прошёл путь 77 100 → 63 916 → 59 394 → 52 484 слова. Двенадцать самых тяжёлых пунктов вынесены. Самый крупный из них, на 4 629 слов, оказался четырьмя темами под одним заголовком и превратился в четыре отдельные страницы — что само по себе диагноз тому, как знание жило раньше.
Плюс страницы, родившиеся не из миграции, а из обычных задач: расхождение идентификаторов категорий между телефоном и сервером, из-за которого фильтр находил пустоту, и таймер обновления виджета, протекавший между файлами мобильного тестового набора и записывавший падение на тот набор, который бежал в этот момент. Обе страницы существуют только потому, что ритуал завершения задачи теперь ведёт в вики, а не в CLAUDE.md.
Что в этой схеме пока не работает
Самый честный раздел, и он длиннее, чем хотелось бы.
| Пробел | Почему это важно | Что будем делать |
|---|---|---|
| Секция запросов в журнале пуста | Вики накапливается только из изменений и никогда из вопросов | Встроить фиксацию ответа в ритуал, а не оставлять её решением |
| 52 484 слова всё ещё в CLAUDE.md | Правило «переносит тот, кто трогает» не перенесёт фичу, которую никто не трогает | Либо честно назвать остаток тем, что живёт в схеме, либо закрыть миграцию осознанно |
| Линт проверяет только пути от корня репозитория | Пути, процитированные относительно приложения, не проверяются вообще | Расширять только тогда, когда это можно сделать без угадывания базового каталога |
| Отчёт о протухании считает коммиты, а не суть | Три косметических коммита выглядят как три, сломавших механизм | Считать его порядком приоритета для человека, а не вердиктом |
| Хабы не перечитаны с мая | Верхний уровень навигации — тот самый артефакт, который однажды соврал | Следующая цель названа в журнале: страница API, 46 коммитов схемы позади |
| В файле трендов одна точка от 14 мая | Без тренда не видно, живёт вики или умирает | Складывать еженедельный результат в файл, а не только в комментарий к issue |
| Экономия не измерена | Любая названная сегодня цифра экономии была бы выдуманной | Замерить средний объём прочитанного за сессию до и после на сопоставимых задачах |
Секция ответов на вопросы в журнале до сих пор пуста. Ingest сработал шесть раз, читающий аудит — один, Query — ноль. Пока это так, у нас не вики в смысле гиста, а хорошо организованная документация проекта, которая накапливается только из изменений. Причина понятна: ингест встроен в обязательный ритуал завершения задачи, а фиксация ответа на вопрос — отдельное решение, которое надо принять ровно в тот момент, когда вопрос уже отвечен и хочется идти дальше. Ритуал побеждает намерение — значит, нужен ритуал, а не напоминание.
Миграция остановится не потому, что закончилась. В CLAUDE.md осталось 52 484 слова, и самые тяжёлые пункты уже вынесены. Дальше каждый следующий перенос даёт всё меньше выигрыша при той же цене, а правило «переносит тот, кто трогает» означает, что фичи, которых никто не трогает, не переедут никогда. Возможно, это и правильно — но тогда остаток надо честно назвать «тем, что живёт в схеме», а не «очередью миграции», иначе мы будем годами считать незавершённым то, что решили не делать.
Оба скрипта видят меньше, чем кажется. Проверка путей срабатывает только на путях от корня репозитория, а страницы законно цитируют пути относительно своего приложения — такие цитаты не проверяются вообще. Это сознательный компромисс: чекер, который угадывает базовый путь, выдаёт находки, которым перестают верить, а это хуже узкого чекера, который всегда прав. Но цена компромисса — часть ссылок вне контроля. Отчёт о протухании тем временем остаётся прокси по коммитам: он не знает, изменилась ли суть, и три косметических коммита выглядят для него так же, как три, сломавших описанный механизм.
Хабы почти не перечитаны. Их пятнадцать, они написаны в мае, читающий аудит дошёл пока до двух. Следующая цель уже названа в журнале — страница API, у схемы базы данных которой 46 коммитов с момента последней правки страницы. Пока хабы не прочитаны против кода, верхний уровень навигации остаётся ровно тем артефактом, который однажды уже соврал.
Файл трендов здоровья задуман как временной ряд и содержит одну точку с 14 мая. Пока еженедельный отчёт уходит комментарием в issue, тренд физически негде накапливать. А показывает, живёт вики или умирает, именно тренд, а не разовый снимок: одна неделя с пятью находками ничего не значит, пять недель подряд с растущим числом находок значат всё.
И главное: мы не знаем, сколько это экономит. Про стоимость агента у нас есть отдельная модель, и она показывает, что вес контекста — одна из крупных статей расхода. Но 104 тысячи токенов в начале сессии — это про то, что было, а не про то, что стало: сколько агент читает теперь, мы не замеряли ни разу. Честный ответ на вопрос «что это дало в деньгах» сегодня — не знаем, и это предмет измерения, а не догадки. Замер несложный: средний объём прочитанного за сессию до и после, на сопоставимых задачах. Мы его ещё не сделали, и до тех пор любая цифра экономии в этой статье была бы выдуманной.
Как повторить у себя за вечер
Скопируйте гист своему агенту и попросите инстанцировать паттерн под ваш репозиторий — документ ровно для этого и написан, он намеренно абстрактен и заканчивается фразой о том, что его единственная задача — передать идею, а детали агент придумает сам.
Дальше четыре вещи, каждая из которых у нас оказалась обязательной.
Объявите схему в том файле, который агент читает всегда. Без указателя на индекс в самых первых строках свежая сессия никогда не узнает, что вики существует, и продолжит дописывать в старый файл. Мы записали это в журнал отдельной строкой в день запуска, потому что это единственная часть схемы, которую нельзя отложить.
Зафиксируйте один шаблон страницы и положите в него секцию инвариантов. Всё остальное в шаблоне можно поменять позже; инварианты — то, ради чего страницу вообще открывают перед правкой кода.
Привяжите ингест к ритуалу, который и так обязателен. У нас это закрытие задачи: issue, страница, строка в журнал. Ритуал, который надо вспомнить, не выполняется.
Поставьте дешёвый линт раньше, чем накопятся страницы. Пара сотен строк на Python, никакой модели, еженедельный запуск. Он не найдёт противоречий, но найдёт мёртвые ссылки и сироты — а это ровно те дефекты, которые в одиночку никто не замечает, пока их не станет тридцать.
И одно предупреждение. Момент, когда вики начинает врать, выглядит точно как момент, когда всё хорошо: страницы на месте, ссылки живые, агент отвечает уверенно. Единственное различие — читал ли кто-нибудь эти страницы против кода за последние четыре месяца.
Итог
Паттерн Карпаты решает не проблему поиска, а проблему накопления: знание компилируется один раз и поддерживается, вместо того чтобы выводиться заново на каждый вопрос. В репозитории это превращается в простую перестановку — главный файл агента становится схемой, знание уезжает на страницы, а три операции становятся тремя ритуалами.
У нас за первый день это дало минус 24 616 слов в файле, который загружается в каждую сессию, и семнадцать страниц фич вместо пунктов списка. Не дало пока ничего из того, что связано со второй операцией: ни одного ответа на вопрос, возвращённого в вики. И не дало ни одной измеренной цифры экономии — потому что мы её не мерили.
Если из статьи стоит забрать одну мысль, то эту: артефакт почти никогда не бывает виноват. Предыдущая вики была написана хорошо и врала четыре месяца, потому что у неё не было цикла. Паттерн ценен не структурой файлов, а тем, что делает поддержку достаточно дешёвой, чтобы цикл вообще состоялся.
Частые вопросы
- Что такое LLM wiki простыми словами?
- Это набор перелинкованных markdown-файлов, который модель строит и поддерживает вместо вас. Новый источник не просто индексируется на будущее: модель читает его и встраивает в уже существующие страницы, поправляя сводки и перекрёстные ссылки. Знание компилируется один раз и поддерживается в актуальном состоянии, а не выводится заново на каждый вопрос.
- Чем LLM wiki отличается от RAG?
- Местом, где происходит синтез. В RAG он происходит в момент ответа и умирает вместе с ответом — на следующий вопрос модель заново ищет и склеивает фрагменты. В вики синтез происходит в момент приёма источника и остаётся на диске вместе с перекрёстными ссылками и отмеченными противоречиями. RAG оптимизирует поиск, вики оптимизирует накопление.
- Нужна ли для этого векторная база или эмбеддинги?
- На старте — нет. Карпаты отмечает, что при сотне источников и нескольких сотнях страниц хватает файла индекса: модель читает индекс, выбирает нужные страницы и уходит в них. У нас вики читается по путям, ровно так же, как агент читает код, — без эмбеддингов и векторного хранилища. Гист предлагает добавить локальный поиск по markdown только тогда, когда вики перерастёт возможности индекса.
- Почему устаревшая вики хуже, чем её отсутствие?
- Потому что агент читает её и уверенно сообщает неверное число, а человек, получивший это число, не имеет повода его перепроверять. Отсутствующая страница хотя бы отправляет читать код. Наша собственная вики после четырёх месяцев без обновлений утверждала 11 AI-функций при 18, 8 языков при девяти и 30 модулей API при сорока восьми — и все эти числа шли дальше как факты.
- С чего начать в своём репозитории?
- С четырёх вещей, каждая из которых у нас оказалась обязательной. Объявите схему в файле, который агент читает всегда, — без указателя на индекс свежая сессия не узнает, что вики существует. Зафиксируйте один шаблон страницы с секцией инвариантов. Привяжите ингест к ритуалу, который и так обязателен, например к закрытию задачи. И поставьте дешёвый линт без модели раньше, чем накопятся страницы.