Как я реализовал LLM-вики в Obsidian

Как я реализовал LLM-вики в Obsidian

В прошлой статье я объяснил, почему отказался от RAG в Obsidian. Здесь — практическая часть. Как повторить такую же схему у себя: какой skill поставить, какие папки создать, как запускать ingest, как задавать вопросы и как не превратить вики в кашу после третьего источника.

Я использую Astro-Han/karpathy-llm-wiki. Это skill для Claude Code, Cursor, Codex и других инструментов, которые понимают стандарт Agent Skills. Он реализует идею LLM-вики: источники складываются в raw/, агент компилирует из них markdown-страницы в wiki/, отвечает по ним с цитатами и периодически проверяет вики через lint.

Ниже я буду использовать вымышленный пример — Atlas Wiki. Допустим, это личная вики по исследованию городских пространств. Название не важно. Важно, что тема узкая и долгоживущая.

Установить skill

Установка библиотеки выглядит так:

npx add-skill Astro-Han/karpathy-llm-wiki

В Claude Code, Cursor и OpenCode это основной путь. Для Codex CLI в README проекта указан ручной вариант: скопировать skill в .agents/skills/karpathy-llm-wiki/. Для других агентов принцип тот же: в каталог skills должны попасть SKILL.md и папка references/.

После установки у агента появляется три операции:

  • Ingest — забрать источник, сохранить его в raw/ и скомпилировать знания в wiki/.
  • Query — прочитать wiki/index.md, открыть релевантные страницы и ответить с ссылками.
  • Lint — проверить здоровье вики: индекс, ссылки, raw-ссылки, orphan-страницы и потенциальные противоречия.

Это не приложение и не плагин для Obsidian. Это инструкция для coding-agent'а. Вся работа происходит через обычные файлы в твоём волте.

Создать папку проекта

Я не делаю одну глобальную LLM-вики на весь Obsidian. Это плохая идея: слишком много тем, слишком много мусора, слишком дорогой контекст. Вместо этого я создаю отдельную вики под конкретную область.

Например:

Wiki/Atlas/

Первую структуру можно не создавать руками. По спецификации skill сам создаёт raw/, wiki/, wiki/index.md и wiki/log.md при первом ingest'е, если их ещё нет. Но я предпочитаю сразу понимать, что должно получиться:

Wiki/Atlas/
├── raw/
│   ├── articles/
│   ├── books/
│   ├── notes/
│   └── interviews/
└── wiki/
    ├── index.md
    ├── log.md
    ├── concepts/
    ├── places/
    └── people/

raw/ — неизменяемые источники. Туда кладутся статьи, PDF, заметки, транскрипты, экспортированные треды, куски документации. После ingest'а источник лучше не править и не переименовывать. Если нужна новая версия — добавь новый файл.

wiki/ — скомпилированные статьи. Их поддерживает агент: создаёт новые страницы, обновляет старые, добавляет связи и пишет index.

wiki/index.md — карта вики. Агент начинает query с неё.

wiki/log.md — журнал операций. Туда пишутся ingest/query archive/lint события.

Добавить локальные правила

Сам skill универсальный. Но универсальности мало. Для нормальной работы агенту нужно объяснить, что именно считать хорошей страницей в твоей вики.

Для этого я добавляю локальную инструкцию в корень папки:

Wiki/Atlas/CLAUDE.md

Пример минимального содержания:

# Atlas Wiki

This is a topic-specific LLM wiki about urban spaces, city observation, architecture, walking routes, and visual research.

## Scope

Use this wiki only for sources related to urban spaces, photography walks, city patterns, architecture, public transport, signage, and local history.

Ignore unrelated personal notes, work notes, and generic productivity material.

## Wiki Structure

- `wiki/concepts/` — reusable concepts, methods, patterns, and recurring observations.
- `wiki/places/` — city districts, streets, buildings, and locations.
- `wiki/people/` — photographers, architects, authors, and researchers.

## Writing Rules

- Write wiki pages in Russian.
- Use standard Markdown.
- Use relative Markdown links inside `wiki/`.
- Prefer durable concepts over source-by-source summaries.
- Keep sources traceable through the `Raw` field.
- If sources contradict each other, mark the conflict explicitly.

## Query Rules

- Always start from `wiki/index.md`.
- Prefer wiki pages over model memory.
- Answer in Russian.
- Cite wiki pages with Markdown links.

Да, это выглядит как бюрократия. Но без локальной инструкции агент будет угадывать структуру. А LLM, которая угадывает структуру базы знаний, — это быстрый путь к энтропии.

Первый ingest

Можно дать агенту URL, путь к файлу или просто вставленный текст. Skill сам должен сохранить источник в raw/, а потом скомпилировать его в wiki/.

Пример с URL:

Ingest this article into Atlas Wiki:
https://example.com/how-cities-use-signage

Пример с локальным файлом:

Ingest file `Wiki/Atlas/raw/articles/2026-04-30-city-signage.md` into Atlas Wiki.

При ingest'е skill делает две разные операции, и это важно:

  1. Fetch в raw/ — сохраняет источник как markdown-файл.
  2. Compile в wiki/ — создаёт или обновляет скомпилированные страницы.

Шаблон raw-файла в skill выглядит примерно так:

# Source Title

> Source: URL or origin description
> Collected: 2026-04-30
> Published: 2026-04-25

Original content below.

Смысл raw/ — сохранить источник достаточно близко к оригиналу. Не переписывать мнение автора. Не превращать статью в summary. Просто убрать мусор форматирования и оставить текст, из которого потом можно восстановить происхождение знания.

Как выглядит скомпилированная статья

После ingest'а агент создаёт или обновляет страницы в wiki/. Важно: файл называется не по источнику, а по концепту.

Например, статья how-cities-use-signage.md может породить страницу:

wiki/concepts/wayfinding-signage.md

Страница строится по шаблону skill:

# Wayfinding Signage

> Sources: Example Magazine, 2026-04-25
> Raw: [How Cities Use Signage](../../raw/articles/2026-04-30-how-cities-use-signage.md)

## Overview

Wayfinding signage is the layer of visual navigation that helps people understand where they are, where they can go, and how to move through a city without asking for help.

## Key Principles

...

## See Also

- [Public Space Legibility](public-space-legibility.md)
- [Transit Maps](../places/transit-maps.md)

Вот здесь и происходит отличие от RAG. Векторная база хранила бы чанки исходной статьи. LLM-вики хранит уже обработанное знание: концепт, связи, источники, конфликты, ссылки на соседние страницы.

Один источник может обновить несколько страниц. Например, статья про городскую навигацию может затронуть wayfinding-signage, public-space-legibility, street-furniture и страницу конкретного района. Это нормально. Вики должна копить связи, а не складывать каждый источник в отдельный ящик.

Проверить index.md и log.md

После ingest'а я всегда смотрю два файла.

wiki/index.md должен получить новую или обновлённую строку:

# Knowledge Base Index

## Concepts

Concepts and recurring patterns in urban research.

| Article | Summary | Updated |
|---------|---------|---------|
| [Wayfinding Signage](concepts/wayfinding-signage.md) | Visual navigation systems that help people move through the city. | 2026-04-30 |

wiki/log.md должен получить запись операции:

## [2026-04-30] ingest | How Cities Use Signage
- Updated: wiki/concepts/wayfinding-signage.md
- Updated: wiki/concepts/public-space-legibility.md

Если этих двух следов нет, ingest сделан плохо. Без индекса агенту нечего читать при query. Без лога ты через неделю не поймёшь, откуда взялись изменения.

Задавать вопросы к вики

Query должен быть явно направлен в конкретную вики. Не “что я знаю про навигацию”, а:

What do I know about wayfinding signage in Atlas Wiki?

или по-русски:

Что я знаю про городскую навигацию в Atlas Wiki?

Агент в этот момент делает так:

  1. Читает wiki/index.md.
  2. Находит релевантные страницы.
  3. Открывает эти страницы.
  4. Синтезирует ответ.
  5. Даёт ссылки на wiki-страницы.
  6. Не меняет файлы без явного запроса.

Последний пункт критичен. Query не должен переписывать базу знаний. Это чтение. Если ответ получился полезным, его можно отдельно сохранить:

Save this answer as an archived query in Atlas Wiki.

Тогда skill создаст отдельную страницу-архив, обновит index.md и добавит запись в log.md.

Запускать lint

Когда страниц становится больше двадцати-тридцати, вики начинает немного расползаться. Это нормально. Для этого есть lint:

Lint Atlas Wiki.

По спецификации skill auto-fix применяется только к детерминированным вещам:

  • файл есть в wiki/, но его нет в index.md;
  • запись в индексе ведёт в несуществующий файл;
  • markdown-ссылка сломана, но правильный файл можно найти однозначно;
  • Raw-ссылка указывает не туда;
  • в See Also есть очевидно битые ссылки.

А вот спорные вещи skill должен только докладывать:

  • противоречия между страницами;
  • устаревшие claims;
  • missing conflict annotations;
  • orphan-страницы;
  • концепты, которые часто упоминаются, но не имеют отдельной страницы.

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

Что лучше не автоматизировать

Самая большая ошибка — повесить file watcher на raw/ и делать ingest автоматически при каждом новом файле. Звучит удобно, но это плохая идея.

Ingest — это не конвертация формата. Это редакторское решение. Агент выбирает, какие концепты создать, какие страницы обновить, какие связи поставить и где отметить конфликт источников. Если это происходит фоном, база начинает дрейфовать. Ты замечаешь проблему только через месяц, когда половина страниц уже написана в странной логике.

Мой рабочий режим такой:

  1. Я выбираю один источник.
  2. Запускаю ingest.
  3. Смотрю diff.
  4. Проверяю index.md и log.md.
  5. Только потом считаю источник обработанным.

Да, это медленнее. Зато база остаётся управляемой.

Минимальный рецепт

Если собрать всё в короткую инструкцию, получается так:

1. Поставить skill:
   npx add-skill Astro-Han/karpathy-llm-wiki

2. Создать папку:
   Wiki/Atlas/

3. Добавить локальную инструкцию:
   Wiki/Atlas/CLAUDE.md

4. Запустить первый ingest:
   Ingest this article into Atlas Wiki: <URL>

5. Проверить:
   wiki/index.md
   wiki/log.md
   wiki/<topic>/<article>.md

6. Задавать вопросы:
   What do I know about X in Atlas Wiki?

7. Периодически чистить:
   Lint Atlas Wiki.

Это и есть вся система. Никакой векторной базы, отдельного сервера, embeddings pipeline и синхронизации индекса между машинами. Только markdown, agent skill и дисциплина вокруг ingest'а.

Для личной базы знаний это оказалось гораздо практичнее RAG. Не потому что RAG плох сам по себе, а потому что в моём случае задача другая. Мне не нужно быстро доставать случайные куски из огромного корпуса. Мне нужно, чтобы знания по узкой теме накапливались, связывались и оставались читаемыми без агента.