@zurab/mdmanager
v0.3.0
Published
MDManager — Nx-плагин и CLI для сборки распределённых *.ai.md в единый markdown/PDF/HTML/DOCX-паспорт с группировкой, фильтрами и валидацией frontmatter через JSON Schema
Readme
@zurab/mdmanager
MDManager — инструмент, который собирает разрозненные markdown-файлы в дерево связанных документов, а не в один длинный файл.
Вместо того чтобы складывать всё в один монолитный README.md, вы пишете много маленьких *.md-файлов с понятными заголовками. MDManager собирает их в компактный навигационный документ, где каждый раздел — это короткое название и ссылка на отдельный markdown с деталями. Открыли оглавление — увидели, о чём документация. Захотели глубже — кликнули по ссылке.
Текущая версия: 0.3.0. Поддерживается формат markdown (другие форматы — за рамками первой версии).
Зачем это нужно
Боль первая: монолитный markdown — ад для чтения
Любая документация любого продукта рано или поздно превращается в один из двух anti-patterns:
- Один длинный markdown на 3000–10 000 строк, который никто не читает целиком, который страшно ревьюить и в котором новые правки гарантированно ломаются о merge-conflicts на чужих абзацах.
- Куча отдельных файлов в папке без оглавления, без связей, без принципа сборки. Каждый автор пишет «как Бог на душу положит», и никакой целостной документации не получается.
Боль вторая: AI-агенту нужна навигация, а не «всё сразу»
Когда документацию читает AI-агент (Claude Code, Cursor, Copilot), он не может «съесть» 10 000 строк за один запрос — это и неэффективно по токенам, и бесполезно: 95% контента не нужно для текущей задачи. Агенту нужен верхнеуровневый обзор со ссылками, чтобы он сам решил, в какие разделы нырять глубже.
Что даёт MDManager
MDManager превращает набор маленьких *.md-файлов в связанное дерево:
- На верхнем уровне — короткий навигационный документ: заголовки разделов, описания в одну строку, ссылки на детали.
- На уровне ниже — отдельный markdown по каждой теме, версионируемый в git, ревьюимый отдельным PR-ом.
- Между ними — автоматически расставленные относительные ссылки, которые продолжают работать после публикации на любом markdown-рендерере (GitHub, GitLab, статический сайт, Obsidian).
AI-агент читает верхнеуровневый файл (короткий, помещается в контекст), видит структуру и идёт за деталями только в нужные разделы. Человек открывает тот же файл и навигирует по ссылкам, а не скроллит километровый markdown.
Как это работает: постфикс-based сборка
MDManager не привязан ни к какому конкретному имени или расширению. Пользователь задаёт свой постфикс — это уникальный суффикс имени файла, по которому библиотека находит документы для сборки. Постфикс может быть любым:
.ai.md— документация продукта для AI-агентов.adr.md— Architecture Decision Records.product.md— продуктовые описания.runbook.md— оперативные инструкции дежурным.changelog.md— журнал изменений- любой другой суффикс, удобный для вашего проекта
В одном репозитории могут параллельно жить несколько разных постфиксов для разных типов документации. Один конфиг .mdmanager.json отвечает за один постфикс.
Что библиотека делает с найденными файлами
- Сканирует дерево от заданного
searchDirрекурсивно или нет. - Находит все файлы с заданным постфиксом.
- Парсит YAML-frontmatter каждого файла (категория, weight, теги, флаги).
- Группирует по категории, сортирует по weight + имени.
- Собирает один итоговый markdown или несколько (через
outputs[]с фильтрами по тегам). - Применяет compact-режим: файлы с
compact: trueво frontmatter превращаются в строку «Заголовок → ссылка на оригинальный файл», вместо вставки всего тела. - Опционально копирует все источники в
mirrorSourcesTo— папку, пригодную для прямой публикации на статический хостинг.
Результат — markdown-документ или набор документов с автоматически расставленными ссылками на отдельные файлы. Никакого длинного простыни-текста: каждый раздел — это компактная карточка с переходом «вглубь».
Ключевые возможности
| Возможность | Что даёт |
| ----------- | -------- |
| Постфикс-based сбор | Пользователь сам определяет, какие файлы собирать (любой суффикс). Несколько постфиксов = несколько типов документации в одном репо. |
| Compact-режим | Файл с compact: true превращается в карточку «Заголовок + ссылка на оригинал» вместо вставки тела. Документ остаётся обозримым. |
| More-links | Автоматически добавляет блок «Подробнее» со ссылкой на отдельный файл (или на more.md рядом с источником). |
| Группировка по категориям | YAML-поле category определяет секцию, groupWeights — порядок секций. |
| Сортировка по весу | YAML-поле weight управляет порядком файлов внутри секции. |
| Теги и фильтры | Frontmatter-поле tags, селекторы select-by-tag / select-by-category / and / or / select-by-field. |
| Separated outputs | Один и тот же набор источников → несколько результирующих markdown через outputs[] с разными фильтрами. Например: «полный паспорт» + «только public-документация» + «только runbook'и». |
| Шаблон с placeholder'ом | template-файл с [$GENERATED] оборачивает сгенерированный контент в произвольную обвязку (header, подпись, лицензия). |
| Bundle ссылок | copyReferencesTo — копирует ссылаемые файлы в поддиректорию и переписывает ссылки в результирующем markdown'е. |
| Self-contained mirror | mirrorIncludeMainOutput — итоговый документ + все источники + все ссылки попадают в одну папку, готовую к публикации на хостинг 1-в-1. |
| JSON Schema валидация frontmatter | Привязка схем к категориям/тегам/файлам через schemaBindings. Опечатки во frontmatter ловятся валидатором, не на ревью. |
| Custom runners (preprocessor) | Code-блоки в источниках могут вызывать пользовательские скрипты, которые подставляют живые данные в сгенерированный документ (см. ниже). |
| Bundled Claude skill | AI-агент устанавливает skill одной командой и сразу понимает контракт продукта без чтения всей документации. |
Установка / запуск
Все примеры ниже используют npx -p @zurab/mdmanager mdmanager … — пакет скачивается из npm-реестра при первом запуске. Локальная установка не требуется.
# Проверка установки и версии.
npx -p @zurab/mdmanager mdmanager --versionQuickstart
# 1. Создать паспорт продукта (скелет директории + .mdmanager.json).
npx -p @zurab/mdmanager mdmanager init --passport my-product
# 2. Добавить раздел документации (создаст файл с правильным постфиксом).
npx -p @zurab/mdmanager mdmanager spec add my-product overview --title "Обзор"
# 3. Собрать связанный markdown-документ.
npx -p @zurab/mdmanager mdmanager build docs/product-passports/products/my-product/.mdmanager.jsonПосле сборки вы получаете один компактный markdown с оглавлением и ссылками на отдельные *.md-файлы. Каждый раздел — отдельная карточка, каждая ссылка ведёт в свой файл с деталями.
Минимальный конфиг
{
"postfix": ".my-product.md",
"output": "docs/my-product/index.md",
"searchDir": "docs/my-product",
"recursive": true,
"enableCompactMode": true
}postfix— ваш суффикс имён файлов. Может быть любым.searchDir— где искать.output— куда писать собранный документ.enableCompactMode— превращать файлы сcompact: trueв карточки-ссылки.
В исходных файлах (*.my-product.md) — frontmatter:
---
title: "Архитектура"
category: spec
weight: 1
compact: true
compactTitle: "Архитектура продукта"
---
# Архитектура
Подробное описание...Файл с compact: true появится в итоговом документе как короткая карточка-ссылка. Файл без compact — вставится целиком.
Несколько выходов из одного источника (separated outputs)
Один и тот же набор *.md-файлов можно собирать в разные документы для разных аудиторий через outputs[] с фильтрами по тегам:
{
"postfix": ".my-product.md",
"output": "docs/my-product/index.md",
"searchDir": "docs/my-product",
"outputs": [
{
"path": "docs/my-product/public.md",
"filter": { "type": "select-by-tag", "tags": ["public"] }
},
{
"path": "docs/my-product/runbook.md",
"filter": { "type": "select-by-tag", "tags": ["runbook"] }
},
{
"path": "docs/my-product/architecture.md",
"filter": {
"type": "and",
"value": [
{ "type": "select-by-category", "category": "spec" },
{ "type": "select-by-tag", "tags": ["architecture"] }
]
}
}
]
}npx -p @zurab/mdmanager mdmanager build docs/my-product/.mdmanager.jsonРезультат — четыре связанных markdown-документа из одного дерева источников: общий, публичный, runbook, архитектурный.
Self-contained папка для публикации на хостинг
Чтобы получившийся документ можно было одной командой загрузить на статический хостинг (GitHub Pages, S3, Netlify), включите mirrorIncludeMainOutput:
{
"postfix": ".my-product.md",
"output": "site/index.md",
"searchDir": ".",
"recursive": true,
"enableCompactMode": true,
"mirrorSourcesTo": "site",
"mirrorIncludeMainOutput": true
}npx -p @zurab/mdmanager mdmanager build path/to/.mdmanager.jsonПосле сборки папка site/ содержит:
index.md— главный документ с переписанными ссылками- все источники в 1:1 структуре относительно
searchDir - никаких внешних ссылок «вверх» — папка самодостаточна
# Локальная проверка перед публикацией:
cd site && python3 -m http.server 8000Custom runners — один из вариантов применения
Помимо обычной сборки markdown, MDManager даёт механизм пользовательских обработчиков code-блоков. Внутри *.md-файлов вы можете писать code-блоки с произвольным prefix'ом, которые при сборке заменяются на результат выполнения вашего скрипта.
Это один из вариантов использования — не основная фича. Возможные сценарии:
- Подстановка живых данных в документацию — блок
apirunnerдёргает ваш API и подставляет актуальный список endpoint'ов. - Self-executable acceptance criteria — блок
jestrunnerзапускает jest-тест и подставляет PASS/FAIL прямо в документ. - Валидация конфигов — блок
lintrunnerпроверяет yaml/json в documentation и подставляет результат. - Snapshot-тестирование документации — блок
snaprunnerсравнивает текущий output с зафиксированным. - Любой другой случай, где документ должен содержать актуальный результат выполнения кода.
Контракт runner-скрипта
Любой исполняемый файл (Node, Bash, Python). Получает на stdin JSON:
{
"blockBody": "...",
"blockLanguage": "myrunner",
"sourcePath": "/path/to/source.md",
"outputPath": "/path/to/output.md",
"frontmatter": { "title": "..." },
"prefix": "myrunner"
}Возвращает на stdout JSON:
{ "ok": true, "mode": "replace", "payload": "<markdown to replace block with>" }или
{ "ok": false, "error": { "code": "X", "message": "..." } }Регистрация runner'а
В .mdmanager.json:
{
"preprocessor": [
{
"type": "codeblock",
"prefix": "myrunner",
"pathToRun": "scripts/runners/my-runner.sh",
"schemaInput": { "type": "object", "required": ["fr"] },
"timeoutMs": 30000
}
]
}В исходном файле:
```myrunner
{ "fr": "FR-X", "command": "..." }
```При сборке блок заменится на то, что вернёт ваш скрипт.
Bundled runners
Из коробки идут готовые runners для популярных задач (устанавливаются вместе со skill через mdmanager install-skill):
| Prefix | Назначение |
| ------ | ---------- |
| jestrunner | Запуск Jest-теста с подстановкой PASS/FAIL |
| vitestrunner | То же для Vitest |
| bashrunner | Произвольный shell-скрипт или команда |
| pytestrunner | Pytest |
| playwrightrunner | Playwright-сценарий |
| cypressrunner | Cypress component test |
Управление активностью runner'ов через токены
Runner-блок может иметь суффикс <prefix>@<token>. Токен фильтруется по activeRunnerTokens в конфиге:
{ "activeRunnerTokens": ["current"] }\`\`\`myrunner@current
{ ... }
\`\`\` ← исполнится (current — активный)
\`\`\`myrunner@beta
{ ... }
\`\`\` ← пропустится
\`\`\`myrunner@deprecated
{ ... }
\`\`\` ← пропустится (deprecated — зарезервирован, никогда не активен)Это позволяет помечать runner-блоки как «устаревшие» без удаления — историческая информация остаётся в документации, но при прогоне не запускается. Удобно при рефакторингах.
Запуск runner'ов
# Запустить все активные runner-блоки одного источника:
npx -p @zurab/mdmanager mdmanager preprocess run --source path/to/file.md --json
# Проверить runner-конфиг без запуска скриптов (валидация схем, проверка пути, runtime):
npx -p @zurab/mdmanager mdmanager preprocess validate --config .mdmanager.json --json
# Drift-detection: сравнить текущий результат с lock-файлом предыдущего прогона:
npx -p @zurab/mdmanager mdmanager preprocess check --source file.md --json
# Strict-режим: упасть, если есть skipped-блоки (для CI после рефакторингов):
npx -p @zurab/mdmanager mdmanager preprocess check --source file.md --strict-tokens --jsonCLI-команды
Базовые
# Собрать документ:
npx -p @zurab/mdmanager mdmanager build path/to/.mdmanager.json
# Валидация конфига и frontmatter:
npx -p @zurab/mdmanager mdmanager validate path/to/.mdmanager.json
# Создать новый паспорт (скелет директории + конфиг):
npx -p @zurab/mdmanager mdmanager passport create my-product --title "Мой продукт"
# Список существующих паспортов:
npx -p @zurab/mdmanager mdmanager passport list --json
# Добавить новый раздел:
npx -p @zurab/mdmanager mdmanager spec add my-product overview --title "Обзор"
# Инициализация в текущей директории:
npx -p @zurab/mdmanager mdmanager init --passport my-product --non-interactive
# Диагностика окружения:
npx -p @zurab/mdmanager mdmanager doctor --jsonУстановка bundled Claude skill
Skill — набор инструкций для AI-агента (Claude Code, Cursor, Codex и других), который содержит контракт продукта. Установка — в любую вашу директорию без хардкода subpath:
# Установить:
npx -p @zurab/mdmanager mdmanager install-skill --install-path ./.cursor/skills/mdmanager
# Повторный запуск той же версии — idempotent (no-op):
# stdout: "Skill актуален (0.3.0): ./.cursor/skills/mdmanager"
# Удалить:
npx -p @zurab/mdmanager mdmanager install-skill --uninstall --install-path ./.cursor/skills/mdmanagerDebug-команды
# Распарсенный YAML-frontmatter одного файла:
npx -p @zurab/mdmanager mdmanager dump-meta path/to/file.my-product.md
# Привязанная JSON Schema для одного файла:
npx -p @zurab/mdmanager mdmanager dump-schema-binding path/to/file.my-product.mdPreprocessor (custom runners)
# Запустить runner-блоки на одном источнике (с записью mirror+lock):
npx -p @zurab/mdmanager mdmanager preprocess run --source path/to/spec.md --json
# Запуск во временной директории, без записи на диск:
npx -p @zurab/mdmanager mdmanager preprocess dry-run --config .mdmanager.json --json
# Drift-check: текущий результат vs зафиксированный lock:
npx -p @zurab/mdmanager mdmanager preprocess check --source path/to/spec.md --json
# Валидация runner-конфига без запуска скриптов:
npx -p @zurab/mdmanager mdmanager preprocess validate --config .mdmanager.json --jsonNx-интеграция
Для проектов на Nx (peer-dependency @nx/devkit ^22) все возможности доступны как Nx-цели. После pnpm i @zurab/mdmanager:
# Сборка одного паспорта:
pnpm nx run my-passport:build-passport
# Сборка всех паспортов в монорепо:
pnpm nx run-many --target=build-passport
# Установка skill в произвольный путь:
pnpm nx run my-passport:install-skill --installPath ./tools/skills/mdmanager
# Generators:
pnpm nx g @zurab/mdmanager:passport my-product --title "Мой продукт"
pnpm nx g @zurab/mdmanager:spec --passport my-product --slug overview --title "Обзор"
pnpm nx g @zurab/mdmanager:install-skill --installPath ./tools/skills/mdmanagerПолный справочник полей конфига
JSON Schema конфига публикуется внутри пакета. После установки:
cat node_modules/@zurab/mdmanager/src/config/schema.jsonОсновные поля (минимально документированы выше):
postfix— суффикс имён файлов для сборки.output— путь итогового markdown.searchDir,recursive,includeHiddenFiles— что и где искать.categories,groupWeights,groupingBy— группировка.enableCompactMode,enableMoreLinks,moreFilename— управление compact-карточками и more-links.template,generateToc,separator,minify— оформление итогового документа.outputs[]— несколько результирующих файлов с фильтрами.copyReferencesTo— bundle ссылок.mirrorSourcesTo,mirrorIncludeMainOutput— self-contained mirror для хостинга.schemas,schemaBindings,defaultSchema,strictValidation— JSON Schema валидация frontmatter.preprocessor[]— регистрация custom runners.activeRunnerTokens— фильтрация runner-блоков по токену.input— режим явного списка файлов (взаимоисключающий сpostfix).
Зависимости
Runtime (внутри пакета): commander, yaml, ajv + ajv-formats, fast-glob, tslib, @inquirer/prompts.
Peer: @nx/devkit ^22 (только если используются Nx executors/generators).
Системные (опционально, только для соответствующих runners): node ≥ 18.17, bash, python3, npx vitest — каждое нужно только если вы регистрируете соответствующий runner. Для базовой markdown-сборки достаточно node.
Документация (спеки)
Все спецификации — в docs/product-passports/products/mdmanager/docs/specs/1-spec/:
1-overview— обзор продукта2-feature-parity— контракт сборки markdown3-schema-validation— JSON Schema валидация frontmatter4-cli-commands— команды CLI5-nx-executors— Nx executors6-nx-generators— Nx generators7-skill-bundling— упаковка Claude skill (FR-610..630 заменены FR-1010..1017 спеки 10)8-npx-distribution— npx-формы запуска и backward-compat9-preprocessor-mirror— preprocessor pipeline + mirror-режим10-self-contained-mirror— self-contained mirror + flexible install-skill + runner tokens
