Бесплатный интерактивный курс · aicoding.space
Слой адаптеров dz: один навык — десять редакторов
Практический курс о том, как навыки из dz попадают в твой редактор и чем ты за это платишь. Вместе с Костей ты разберёшь, что такое цель (--target), какой контракт общий у всех десяти адаптеров, на какие три измеренных класса они делятся, развернёшь один и тот же навык в два редактора и сравнишь результат, а в конце прочитаешь карту dz parity — включая те клетки, где она честно признаётся, что не измеряла.
Содержание курса
1. Зачем нужен слой адаптеров?
Один навык, десять редакторов — и почему это работа компилятора, а не копипасты.
Ключевая мысль: адаптер — компилятор навыка под конкретный редактор
Костя — тимлид, и у него ровно та же проблема, с которой ты сюда пришёл. Он написал двенадцать навыков в dz. Сам сидит в Claude Code. Фронтендер — в Cursor. Дата-инженер — в Gemini CLI. Ревьюер живёт внутри GitHub Copilot. Вопрос Кости звучал так: «я напишу навык один раз — что увидит каждый из них?»
Сначала два слова, чтобы дальше говорить на одном языке.
- Навык (skill) — это папка с файлом
SKILL.md: YAML-шапка (name,description) плюс тело в Markdown. Тело — инструкция агенту, шапка — метаданные, по которым его находят. - Адаптер (adapter) — это компилятор: на входе один канонический навык, на выходе — файлы ровно в том виде, в каком их читает конкретный редактор.
Вот вся идея курса одной фразой: навык — один источник истины, а у каждого редактора свой формат; адаптер — компилятор из одного во многие. Не десять инструментов, а один компилятор с десятью выходами.
Почему не копировать файлы руками? Потому что копия — это не «то же самое в другом месте». Cursor читает .cursor/rules/ и игнорирует файлы с неправильным расширением. Gemini читает ОДИН файл в корне. Copilot вообще не сканирует каталог навыков. Костя, копируя руками, через неделю не помнил бы, какая копия свежая, — а главное, не знал бы, что именно потерялось по дороге.
Все десять адаптеров лежат на npm рядом друг с другом — например @dzhechkov/adapter-claude и @dzhechkov/adapter-cursor; исходники — в публичном зеркале github.com/djd1m/dz-harness.
2. Что такое цель: dz init --target
Десять имён целей, таблица псевдонимов и ловушка claude против claude-code.
Ключевая мысль: цель --target — имя в реестре dz, а не имя платформы
Костя разворачивает навыки одной командой:
dz init --target claude-code --skills-dir ./skills --project .ИЗМЕРЕНО, вывод дословно: dz init --target claude-code: 1 skill(s), 1 file(s) written, 0 skipped, код возврата 0.
Цель (target) — это имя в реестре dz, по которому выбирается адаптер. Имён ровно десять, и команда их сама перечисляет: agents-md, claude-code, codex, copilot, cursor, gemini, hermes, openclaude, opencode, windsurf.
А теперь ловушка, на которой Костя споткнулся первым. Внутри адаптера платформа называется claude, а имя цели — claude-code. Оба работают, но по-разному: --target claude проходит через таблицу псевдонимов, и dz честно об этом печатает — ИЗМЕРЕНО: dz init: --target "claude" → claude-code (alias). Псевдонимы — это ДАННЫЕ, одна строка таблицы, а не ветвление в коде: claude и cc → claude-code, agents → agents-md, gpt и openai → codex.
Опечатка не молчит. ИЗМЕРЕНО: --target cursur даёт unknown --target "cursur" — did you mean "cursor"? и полный список допустимых имён. Это важнее, чем кажется: цель, набранная с ошибкой, могла бы «успешно» ничего не развернуть.
Установка самого dz и ссылки: @dzhechkov/harness-cli, исходники — github.com/djd1m/dz-harness.
3. Общий контракт: compile, verify и EmitResult
Один интерфейс на десять адаптеров: чистые функции, относительные пути и строгий режим.
Ключевая мысль: compile и verify — чистые функции, возвращающие EmitResult
Костя открыл три адаптера подряд и увидел одно и то же. Не случайность: все десять реализуют один интерфейс Adapter из @dzhechkov/core (src/adapter.ts:68) — три члена и больше ничего:
platform— имя платформы, для которой этот адаптер эмитит;compile(skill, ctx)— возвращаетEmitResult { files, warnings };verify(emitResult)— возвращаетVerifyResult { ok, errors, warnings }.
И compile, и verify — чистые функции. Чистая функция (pure function) — это функция, которая на одном и том же входе всегда даёт один и тот же выход и не делает ничего снаружи: не пишет файлы, не ходит в сеть, не смотрит на часы. Зачем это здесь: адаптер можно проверить целиком без файловой системы, а его вывод воспроизводим — тот же навык всегда компилируется в те же байты.
Запись на диск — забота вызывающей стороны, а не адаптера. Отсюда второе правило, записанное прямо в комментарии контракта: пути в files[] относительны ctx.targetRoot, и адаптер НЕ должен приклеивать корень сам — иначе получится <root>/<root>/… или абсолютный путь, который хост отвергнет.
Третий член контекста — ctx.strict. Смысл: «не применяй потерю молча — откажись». Про него будет отдельная секция, но запомни сейчас: строгий режим превращает предупреждение в отказ.
И измеренная мелочь, которая многое объясняет: у всех десяти пакетов ровно одна зависимость — @dzhechkov/core, и ни один не объявляет bin. Адаптер не самостоятельная утилита; он всегда вызывается через dz init --target.
4. Три класса адаптеров — и как их измерить
Побайтовые, трансформирующие, уплощающие: классификация из исходников, а не из названий.
Ключевая мысль: класс адаптера определяется измерением исходников, а не именем
Костя попробовал угадать класс по названию и ошибся на первом же пакете. Смотри сам: adapter-openclaude звучит как «ещё один вариант Claude» — а по коду это тонкая обёртка над emitSkillTree с корнем .openclaude/skills, то есть чистый побайтовый перенос. Класс адаптера измеряется по исходникам, а не выводится из имени.
Измерение дало ровно три класса:
- Побайтовые адаптеры дерева навыков — пять штук:
claude,codex,opencode,hermes,openclaude. Все пять — тонкие обёртки над одним движкомemitSkillTreeиз core; отличие ровно одно — константа корневого каталога. - Трансформирующие — два:
cursor,windsurf. Файл на навык, но в СВОЁМ формате шапки. - Уплощающие и потерянные — три:
copilot,gemini,agents-md. Структура, которой у цели нет, выбрасывается.
Как измерять самому, по шагам: прочитать description в package.json; открыть src/index.ts; посмотреть, ЧТО импортируется из core (emitSkillTree — побайтовый; renderCursorMdc или renderGeminiMdSection — не побайтовый); посмотреть путь эмита; прочитать текст строки-предупреждения lossy, если она есть. Пять шагов, и класс назван по коду.
Ещё один измеренный факт, который выглядит подсказкой: версии разложились по классам — 0.2.x у побайтовой пятёрки, 0.1.x у остальных. Честная оговорка: это вывод из номеров версий, а не из журнала изменений — считай это гипотезой, а не доказательством общей ревизии API.
Все десять на npm: adapter-claude, adapter-codex, adapter-opencode, adapter-hermes, adapter-openclaude, adapter-cursor, adapter-windsurf, adapter-copilot, adapter-gemini, adapter-agents-md.
5. Побайтовая пятёрка: один движок, пять корней
emitSkillTree и доказательство, что SKILL.md доезжает без единого изменённого байта.
Ключевая мысль: побайтовый перенос: SKILL.md доезжает без единого изменённого байта
Костя ожидал пять разных реализаций. Их пять — но код в них почти одинаковый, и это по замыслу.
Все пять зовут один движок emitSkillTree из core. Разница между адаптерами — одна константа, корневой каталог:
claude→.claude/skillscodex→.agents/skillsopencode→.opencode/skillshermes→.hermes/skillsopenclaude→.openclaude/skills
Побайтовый перенос (lossless) означает буквально это: содержимое SKILL.md — текст документа дословно, поэтому эмиссия ничего не теряет. Меняется только место файла, не его байты.
ИЗМЕРЕНО прямо для этого курса. Канонический навык hello-adapters развёрнут командой dz init --target claude-code; затем:
$ diff canon/hello-adapters/SKILL.md proj-claude/.claude/skills/hello-adapters/SKILL.md
$ echo $?
0
$ sha256sum canon/.../SKILL.md proj-claude/.../SKILL.md
3c8f59dd00e6d737552eb01e28e04c7567af1617dfa15112e4fe6fce561f7c82 (оба файла)Пустой diff и один и тот же sha256 — это и есть побайтовость, предъявленная, а не обещанная.
Что отсюда следует практически: круговой рейс. Скомпилировал навык в цель, разобрал обратно — получил исходник. Активы (scripts/, references/) переносятся тоже, а не остаются дома. И движок защищается на входе: небезопасный идентификатор навыка или путь актива с .. — ошибка, а не запись мимо каталога.
6. Трансформирующие цели: Cursor и Windsurf
Своя шапка вместо канонической, файл на навык — и почему расширение решает всё.
Ключевая мысль: трансформирующая цель заменяет каноническую шапку своей
Фронтендер пожаловался: «правило не подхватывается». Костя полез разбираться и нашёл ответ в одной строке комментария адаптера.
Cursor читает проектные правила из .cursor/rules/ — один файл на правило, и расширение обязано быть .mdc: обычный .md в этом каталоге Cursor игнорирует. Адаптер поэтому пишет ровно .cursor/rules/<id>.mdc.
Трансформирующая цель — это цель, у которой своя шапка, и адаптер заменяет нашу целиком. Каноническая шапка навыка несёт около 26 проектных ключей; Cursor понимает три: description, необязательный globs и alwaysApply. Всё остальное не переезжает — и это решение, а не недоделка: оба адаптера прямо говорят «не побайтовый» и исключены из набора проверок побайтового равенства.
ИЗМЕРЕНО. Тот же навык, что в предыдущей секции, скомпилирован в Cursor. Тело — слово в слово то же. Шапка — другая:
---
description: "Демонстрационный навык для курса про адаптеры …"
alwaysApply: false
---alwaysApply: false — это не «выключено». Это правило по запросу агента: оно подтягивается, когда модель сочтёт его уместным, вместо того чтобы вливаться в каждый ход. Экономия контекста прямо здесь.
Windsurf — та же идея с тремя отличиями: каталог .windsurf/rules/, обычный .md (не .mdc), и ключ активации называется trigger (always_on | manual | model_decision | glob) вместо alwaysApply. Адаптер эмитит trigger: model_decision — тот же смысл «по запросу агента».
И оба verify проверяют ровно несущее: у Cursor — что description стоит в ВЕДУЩЕЙ шапке, а не где-то в теле; у Windsurf — что есть trigger, потому что без него редактор просто не знает, когда включать правило.
7. Уплощающие цели: всё в один файл
GEMINI.md и AGENTS.md: что именно исчезает — и почему твои заметки всё-таки выживают.
Ключевая мысль: уплощающая цель сводит все навыки в один файл
Костя развернул два навыка в Gemini и пересчитал файлы. Их оказалось не два. Один.
ИЗМЕРЕНО, вывод дословно: dz init --target gemini: 2 skill(s), 1 file(s) written, 0 skipped, а find по проекту вернул ровно одну строку — GEMINI.md.
Уплощающая цель (flattening) — это цель, у которой нет ни каталога навыков, ни шапки: всё сводится в ОДИН файл в корне проекта. GEMINI.md читают Gemini CLI и Code Assist; AGENTS.md — договорённость, которую понимают около пятнадцати инструментов (Cursor, Zed, Warp, Aider, goose, RooCode, Junie, Devin, Windsurf и другие).
Что теряется — поимённо, из текста самого предупреждения адаптера:
- YAML-шапка навыка;
- постепенное раскрытие (progressive disclosure) — режим, при котором агент читает подробности навыка только когда к нему обратился; в плоском файле всё лежит открытым всегда;
- границы между навыками как отдельными файлами;
- активы
scripts/и прочие — они не переносятся вовсе.
А теперь неожиданное. Костя дописал в GEMINI.md руками свои заметки после управляемого блока и запустил dz init ещё раз. Заметки остались на месте. Управляемая часть обёрнута маркерами <!-- dz:skills BEGIN (managed by dz — do not edit) --> … <!-- dz:skills END -->, и стратегия записи — слияние, а не перезапись: dz меняет только то, что между маркерами.
Ещё одна тонкость для тех, кто полезет в код: compile уплощающего адаптера отдаёт СЕКЦИЮ одного навыка по пути GEMINI.md. Сборка всех секций и слияние с твоим файлом происходят слоем выше — адаптер один навык видит, а файл целиком собирает не он.
8. Практика: один навык в два редактора и diff
Полный проход руками: развернуть один и тот же навык в Claude Code и Cursor и сравнить.
Ключевая мысль: один навык в две цели: diff показывает, чем они отличаются
Это тот проход, после которого Костя перестал задавать вопросы. Повтори его целиком — он занимает минуту.
Шаг 1. Один канонический навык. Каталог canon/hello-adapters/ с файлом SKILL.md: шапка name и description, тело в Markdown.
Шаг 2. Развернуть в две цели.
dz init --target claude-code --skills-dir ./canon --project ./proj-claude
dz init --target cursor --skills-dir ./canon --project ./proj-cursorИЗМЕРЕНО: обе команды напечатали 1 skill(s), 1 file(s) written, 0 skipped.
Шаг 3. Посмотреть раскладку. find по обоим проектам дал две строки:
proj-claude/.claude/skills/hello-adapters/SKILL.md
proj-cursor/.cursor/rules/hello-adapters.mdcСлева — каталог на навык. Справа — один файл, и расширение другое.
Шаг 4. Сравнить. У Claude Code diff с каноном пустой, sha256 совпадает (3c8f59dd00e6…) — байт в байт. У Cursor тело совпадает слово в слово, а шапка заменена на description + alwaysApply: false.
Вывод словами, чтобы его можно было пересказать: тело инструкции доезжает до обоих редакторов одинаково, а цена цели видна ровно в двух местах — в шапке и в раскладке файлов. Именно поэтому diff здесь не формальность: это самый дешёвый способ увидеть, чем ты заплатил за совместимость.
9. Copilot: потерянный, но пофайловый
Странный случай: файл на каждый навык — и при этом самая заметная потеря.
Ключевая мысль: Copilot теряет адресность: инструкция на навык, но всегда включённая
Костя ждал, что Copilot окажется похож на Cursor. Оказалось — нет, и разница поучительная.
GitHub Copilot не сканирует каталог навыков вообще. У него нет такого механизма. Зато он сам читает инструкции репозитория из .github/instructions/*.instructions.md. Поэтому адаптер пишет туда — файл на каждый навык, <id>.instructions.md.
Формально Copilot в классе потерянных — вместе с gemini и agents-md. Но, в отличие от них, у него файл ОТДЕЛЬНЫЙ на каждый навык. Тогда в чём же потеря? Вот в чём, поимённо:
applyTo: ""— инструкция всегда включена** для всех файлов; постепенного раскрытия нет;- команды вызова навыка у Copilot нет — навык нельзя позвать по имени;
scripts/кладутся в отдельный корень.github/copilot-skills/<id>/как справочные: Copilot их не исполняет.
Открытый вопрос, на который стоит потратить минуту: «потерянный» и «трансформирующий» — это не про РАЗМЕР потери, а про то, ЧТО именно исчезает. Cursor теряет шапку, но сохраняет адресность: правило подтягивается по решению агента. Copilot сохраняет отдельный файл, но теряет адресность: инструкция висит всегда. Какая потеря дороже?
Честный ответ Кости: зависит от числа навыков. На трёх навыках всегда включённая инструкция — мелочь. На тридцати — это тридцать инструкций в каждом ходе, и цена уже не мелочь.
10. Потеря всплывает предупреждением — или отказом
Правило контракта: молчаливой потери не бывает, а strict превращает предупреждение в отказ.
Ключевая мысль: потеря всплывает предупреждением, а под strict — отказом
Костя спросил ровно то, что должен был спросить: «а как я УЗНАЮ, что цель что-то потеряла?»
Ответ записан в самом контракте Adapter: компиляция может быть с потерями — но потеря обязана всплыть предупреждением, никогда молча. Это не пожелание в документации, это то, как написан каждый непобайтовый адаптер.
Механика одинаковая у всех:
- адаптер собирает строку
lossyс ИМЕНЕМ навыка и перечислением того, что исчезает; - если
ctx.strict !== true— строка едет вwarningsрезультата; - если
ctx.strict === true— компиляция ОТКАЗЫВАЕТСЯ:refusing lossy compile under strict mode.
Строгий режим — это выключатель «лучше не собрать, чем собрать тихо неправильно». Он нужен там, где потеря недопустима: в конвейере сборки, а не на твоём ноутбуке.
Второе место, где это видно, — verify. Он не просто проверяет структуру: он ПЕРЕНОСИТ предупреждения дальше — const warnings = [...emit.warnings]. Комментарий в адаптере объясняет зачем прямым текстом: чтобы dz verify --target cursor никогда не отчитался «чисто», не сказав про потерю.
Сноска здесь не украшение (и это общее правило хорошего инструмента): предупреждение — часть контракта, а не примечание внизу экрана. Проверь себя прямо сейчас: если ты не можешь назвать, что теряет твоя цель, — ты цель не выбрал, ты взял первую попавшуюся.
11. adapter-claude: эталон и планировщик спутников
Единственный адаптер с четырьмя файлами: почему он и база сравнения, и планировщик MCP.
Ключевая мысль: adapter-claude — эталон побайтовости и планировщик спутниковой конфигурации
Костя пробежал find по исходникам всех десяти пакетов и заметил аномалию: у девяти адаптеров ровно один файл src/index.ts. У adapter-claude их четыре — index.ts, compile.ts, verify.ts и integrations.ts. Значит, он делает что-то ещё.
Роль первая — эталон. Формат Claude Code и есть канонический формат agentskills.io, поэтому именно этот адаптер служит базой побайтового сравнения для остальных. Когда где-то говорится «исключён из набора проверок побайтового равенства» — равенство измеряется относительно него.
Роль вторая — спутниковая конфигурация. claudeIntegrationAdapter планирует то, что живёт рядом с навыками: MCP-серверы и хуки. Он тоже ничего не пишет — он возвращает ПЛАН из двух частей:
- фрагменты-носители: например, файл
.mcp.json, корневой ключmcpServers, областьproject; - отказы — с кодом причины и подсказкой, что сделать.
И вот главное, ради чего эта секция вообще есть: отказ здесь ИМЕННОЙ, из закрытого словаря. INTENT_NOT_EXPRESSIBLE — «квитанция доказывает только локальную команду stdio, без env и url», то есть намерение нельзя выразить честно. NO_ACTIVATION_RECEIPT — «для хуков нужна канарейка с одноразовым значением и отрицательный контроль», то есть нет доказательства, что хук реально сработал. Словарь причин закрыт и живёт в core/src/adapter.ts — придумать новую причину на месте нельзя.
ИЗМЕРЕНО на реальном прогоне: dz init без явного согласия печатает MCP: NOT-REQUESTED и Hooks: NOT-REQUESTED. Спутниковая конфигурация не приезжает сама — её надо запросить, и согласие на манифест интеграций требует точной контрольной суммы.
12. dz parity: честная карта возможностей и целей
Двенадцать возможностей на десять целей, вычисленные из модели, а не написанные руками.
Ключевая мысль: паритет — вычисленная карта: что работает на цели и в какой форме
Костя дошёл до вопроса, который рано или поздно задают все: «ладно, навыки доехали — а остальной харнес?» Для этого есть одна команда.
dz parityОна печатает таблицу: двенадцать возможностей харнеса по строкам, десять целей по столбцам. Ключевое свойство: таблица не написана руками — она ВЫЧИСЛЕНА из модели возможностей (harness-core/src/parity.ts). Рукописная копия такой таблицы была бы вторым источником расхождения: код меняется, документ отстаёт, и читатель верит документу.
Три знака в клетках:
✓— полностью: возможность работает сама;◐— вручную: возможность ДОСТУПНА, но ведёшь её ты;—— недоступно на этой цели.
◐ — не «сломано». Это самая частая ошибка чтения. ИЗМЕРЕНО: у Cursor конвейер feature-adr стоит как ◐ — «интерактивный навык, ведёшь руками», а не «не работает».
ИЗМЕРЕНО из живого прогона: у всех десяти целей ✓ на строках «dz CLI (all commands)» и «Skill packs (compiled per target)» — базовая совместимость полная. Живая статусная панель ✓ только у claude-code, у остальных —. MCP-память: ✓ у claude-code, ◐ у codex, — у остальных восьми.
Читается это как компромисс, а не как рейтинг: чем ближе цель к родному формату, тем больше возможностей едет автоматом; чем дальше — тем больше остаётся на твоих руках.
13. Где карта честно неполна
Пустая клетка значит «не измерено», а знак вопроса — «улика устарела».
Ключевая мысль: непроверенное не помечается поддержанным: пустая клетка значит «не измерено»
Это секция, ради которой Костя и просил курс. Карта паритета полезна ровно настолько, насколько честно она признаётся в незнании.
Контракт честности записан в самом модуле: флаг возможности утверждает только то, что ПРОВЕРЕНО, и у каждого флага в коде рядом стоит источник. Неизвестная поддержка НЕ отмечается. Обоснование там же: ложно обещанная возможность хуже, чем консервативно отмеченная как отсутствующая.
Отсюда следствие, которое надо читать правильно. У семи целей — opencode, hermes, openclaude, copilot, cursor, gemini, windsurf — в модели ровно две возможности: shell и skills, с комментарием «консервативная первая версия: эмиссия навыков подтверждена адаптерами, более богатые среды не доказаны». Это надо читать как «не измерено», а не как «нет».
И есть четвёртый знак, которого нет в общей таблице, — ?. ИЗМЕРЕНО:
$ dz parity --target codex
? Self-learning: automatic apply-leg … INCONCLUSIVE: stale evidence for hooks-prompt
⚠ hooks-prompt: улика записана на codex-cli 0.147.0, свежайшая запись — 0.148.0Что здесь произошло: возможность когда-то была ДОКАЗАНА живой пробой, но проба относится к старой версии инструмента, а с тех пор появилась новая. Модель не стала утверждать по инерции — она понизила клетку до «неубедительно», пока не перепроверят. Важная тонкость: inconclusive — это уровень ОТЧЁТА, а не модели. Модель по-прежнему знает, что было доказано; отчёт отказывается это предъявлять как действующее.
Проверь себя одним вопросом: когда ты в следующий раз увидишь пустую клетку в чьей-нибудь таблице совместимости — ты сможешь сказать, это «не умеет» или «не проверяли»? В большинстве таблиц ответа нет. Здесь он есть, и в этом вся ценность.
14. Твой выбор: какой потерей ты платишь
Финальная развилка: подобрать цель под свою команду и назвать цену вслух.
Ключевая мысль: выбор цели — решение о том, какой потерей ты платишь
Теперь роль твоя, а не Костина. Костя уже прошёл этот выбор и вот к чему пришёл.
Правило одной фразой: цель выбирают не по названию редактора, а по тому, какую потерю ты готов принять. Три ответа, три цены:
- Редактор понимает формат agentskills.io (Claude Code, Codex, OpenCode, Hermes, OpenClaude) — бери побайтовую цель. Цена: ноль. Ограничение: список редакторов короткий.
- Редактор имеет свой формат правил (Cursor, Windsurf) — бери трансформирующую. Цена: каноническая шапка и активы
scripts/. Приобретение: правило по запросу агента, экономия контекста. - У редактора вообще нет понятия навыка (Copilot, Gemini CLI, всё семейство AGENTS.md) — бери уплощающую. Цена: шапка, постепенное раскрытие, границы навыков, активы. Приобретение: работает почти везде.
Две проверки перед тем, как объявить выбор сделанным:
- запусти
dz parity --target <имя>и прочитай, что уедет автоматом, а что останется на руках; - разверни ОДИН навык и сделай
diff— секция 8 занимает минуту и отвечает точнее любого README.
И последнее, что стоит унести из курса целиком. Слой адаптеров ценен не тем, что «работает везде» — так не бывает. Он ценен тем, что каждая потеря названа по имени, всплывает предупреждением и может быть запрещена строгим режимом. Инструмент, который честно говорит, чем ты платишь, лучше инструмента, который обещает бесплатно.
Частые вопросы
- Я поставил навыки в Cursor, а шапка выглядит совсем иначе — это баг?
Нет, это заявленное поведение трансформирующей цели. Cursor понимает три ключа (description, необязательный globs, alwaysApply), поэтому каноническая шапка заменяется целиком. Тело навыка при этом переезжает слово в слово — проверь diff тел, он будет пустым.
- Почему --target claude работает, если в списке написано claude-code?
Через таблицу псевдонимов, и dz об этом печатает: «dz init: --target "claude" → claude-code (alias)». Псевдонимы — данные, не логика: claude и cc ведут на claude-code, agents — на agents-md, gpt и openai — на codex.
- Я дописал свои заметки в AGENTS.md — их затрёт следующий dz init?
Нет, если они за пределами управляемого блока. dz меняет только то, что между маркерами dz:skills BEGIN и dz:skills END; стратегия записи — слияние, а не перезапись. Измерено повторным запуском: дописанные вручную строки остались на месте.
- Как узнать, что именно теряет моя цель, не читая исходники?
Потеря обязана всплыть предупреждением — это записано в контракте адаптера, и verify переносит предупреждения дальше. Если потеря вообще недопустима, включай строгий режим: под ним адаптер откажется компилировать с сообщением refusing lossy compile under strict mode.
- В dz parity у моей цели почти пустая колонка. Значит, она мало что умеет?
Не обязательно. Контракт честности запрещает отмечать непроверенное как поддержанное, поэтому пустая клетка значит «не измерено», а не «не умеет». Отдельно есть знак ?: он означает, что улика устарела — например, записана на codex-cli 0.147.0, а свежайшая запись 0.148.0.
- Можно ли из скомпилированного файла восстановить исходный навык?
У побайтовых целей — да: SKILL.md совпадает с каноном байт в байт, что проверяется diff и sha256sum. У трансформирующих и уплощающих — нет: каноническая шапка заменена или выброшена. Именно поэтому канонический каталог навыков остаётся единственным источником истины.
- Адаптер — это отдельная утилита, которую можно запустить?
Нет. Измерено по package.json: ни один из десяти адаптеров не объявляет bin, и у каждого ровно одна зависимость — @dzhechkov/core. Адаптеры всегда вызываются через dz init --target <имя>.