Agent Dev 101

Модуль 16 · Урок 16.12

Урок 16.12. Расширения

На этой странице
  1. Зачем это нужно
  2. Основная идея
  3. Поиск
  4. Установка
  5. Удаление и список
  6. Информация и версии
  7. Обновление и приоритеты
  8. Каталоги и модель доверия
  9. Конфигурация расширений
  10. Конфигурация расширений и хуков проекта
  11. Частые вопросы
  12. Практика
  13. Краткое резюме
  14. Вопросы для самопроверки
  15. Что дальше
  16. Источники

Зачем это нужно

Расширения - главный механизм добавления возможностей в Spec Kit: доменные команды, интеграции внешних инструментов, quality gates, хуки. Уже знакомые bundled-расширения bug (урок 16.6) и assess (урок 16.7) - частные случаи; каталог сообщества насчитывает 157 расширений (срез 2026-10-03, урок 16.19).

Этот урок - справочник жизненного цикла расширения: поиск, установка (из каталога, URL или локальной директории), обновление, enable/disable, приоритеты резолюции, каталоги с моделью доверия discovery-only против install-источников и конфигурация расширений и хуков.

Основная идея

Расширение добавляет новые команды, шаблоны, скрипты и хуки поверх встроенного SDD-workflow. Устанавливается в .specify/extensions/<ext>/, команды регистрируются в активной интеграции агента. Несколько расширений сосуществуют; конфликты имен команд решаются приоритетами (меньше число - выше приоритет). Каталоги делятся на install-источники и discovery-only - это граница безопасности, а не техническое ограничение.

Поиск

bash
specify extension search [query]
Опция Описание
--tag фильтр по тегу
--author фильтр по автору
--verified только verified-расширения

Ищет по всем активным каталогам; без запроса выводит все доступные расширения.

Установка

bash
specify extension add <name>
Опция Описание
--dev установка из локального каталога (для разработки)
--from <url> установка из кастомного URL вместо каталога
--version <v> точная версия, анонсированная каталогом
--force перезаписать установленное расширение
--priority <N> приоритет резолюции (дефолт 10; меньше = выше)

Команды расширения регистрируются в активной интеграции. Для generic вызовы идут в настроенный --commands-dir: плоские файлы команд по умолчанию или speckit-<name>/SKILL.md с --skills. Core-команда speckit.taskstoissues остается доступной рядом с namespaced-заменой GitHub-расширения на время миграции.

Если refresh generic-интеграции не может воспроизвести каждый вызов расширения (команда или скилл изменена пользователем или источник отсутствует), команда предупреждает и восстанавливает прежние зарегистрированные артефакты этого расширения; остальные обновляются.

Нюансы пиновки версий: неквалифицированная установка из каталога берет анонсированную текущую версию; --version использует только выигравший каталог-источник для этого ID и не падает обратно на источник ниже приоритетом, если версии там нет; discovery-only каталоги остаются неустанавливаемыми; --version не комбинируется с --dev или --from. ID и версия скачанного архива проверяются до установки.

Все команды расширений требуют проект, инициализированный specify init.

Удаление и список

bash
specify extension remove <name>   # --keep-config: сохранить конфиги; --force: без подтверждения
specify extension list [--available|--all|--json]

Удаление по умолчанию бэкапит конфигурационные файлы. Список показывает статус, версию и количество команд; --available - доступные (неустановленные), --all - и те и другие.

Формат --json: массив в stdout, каждый элемент с ключами id, name, description, version, author (null при отсутствии), priority, enabled, source ({"kind":"local"} или {"kind":"catalog","catalog":"<имя>"}) и provides (счетчики commands, templates, scripts, hooks). Успех - ровно один массив и exit 0; сбой рантайма - ровно один {"error":"..."} в stderr и exit 1; usage-ошибка с --json - JSON-объект ошибки в stderr с сохранением usage-кода (обычно 2).

Информация и версии

bash
specify extension info <name> [--versions]

Подробности об установленном или доступном расширении: описание, версия, команды, конфигурация. --versions перечисляет текущую и исторические версии выигравшего каталога; discovery-only источники помечаются как неустанавливаемые. Эквивалентные написания PEP 440 (v1.0 и 1.0) выбирают один релиз; видимое написание - как в каталоге.

Каталоги могут держать текущий релиз в верхних полях и исторические - в маппинге releases (у каждого релиза свои download_url и SHA-256; релиз-специфичные требования - в записи релиза, не наследуются). Текущая версия не должна повторяться в releases; битые и дублирующиеся записи отклоняются. Пины бандлов пока используют текущий путь резолюции каталога.

Обновление и приоритеты

bash
specify extension update [<name>]   # одно или все установленные

Bundled-расширения (agent-context, git) не имеют download URL - их обновления ставятся из копии, поставляемой с текущим релизом spec-kit. Если каталог анонсирует более новую версию, чем шипит ваш релиз, обновление потребует сначала апгрейда spec-kit. Для generic неудачное обновление восстанавливает hash-owned вызовы из ранее настроенных --commands-dir-папок, даже если активна другая интеграция.

bash
specify extension enable <name>     # включить
specify extension disable <name>    # выключить без удаления
specify extension set-priority <name> <priority>

Выключенное расширение не грузится, его команды недоступны. Hook-only расширения ставятся и переключаются даже при невалидных настройках generic-вывода; расширения с командами требуют валидных настроек. Для generic disable удаляет hash-owned вызовы даже после переезда каталога вывода, сохраняя посторонние одноименные файлы в новом каталоге. При конфликте имен команд выигрывает расширение с наименьшим числом приоритета.

Каталоги и модель доверия

Каталоги определяют, где search и add ищут расширения; проверяются в порядке приоритета (меньше число - выше).

Discovery-only против install-источников

Каталоги двух видов, и различие - граница безопасности, а не ограничение:

  • install-источники (install_allowed: true) - каталоги, которым вы доверяете как месту установки: встроенный default (официальный) и любые каталоги, которые вы авторите и вэтите сами;
  • discovery-only (install_allowed: false) - поисковые поверхности для нахождения расширений, без установки: встроенный community каталог discovery-only и активен для search из коробки.

community намеренно discovery-only: это открытый невэтченный список - one-command-install всего подряд означало бы тянуть произвольный сторонний код без ревью.

Не переключайте discovery-only каталог в install_allowed - это разрушает саму идею разделения. Два корректных пути установить найденное через community:

  1. Установить одно провэтченное расширение напрямую через --from (без авторинга каталогов). URL архива даст specify extension info - для discovery-only записей печатается «Candidate archive». Отревьюйте релизный архив, затем:

    bash
    specify extension info <name>          # печатает URL архива-кандидата
    specify extension add <name> --from <archive-url>
    

    Считайте URL недоверенным, пока не провэттили: он из невэтченного каталога.

  2. Кураторство собственного каталога под вашим контролем с install_allowed: true - для управляемого переиспользуемого источника установки (например, для организации).

Управление

bash
specify extension catalog list
specify extension catalog add <url>    # --name (обязательно), --priority, --install-allowed|--no-install-allowed, --description
specify extension catalog remove <name>

Каталог добавляется в .specify/extension-catalogs.yml. Повторное добавление именованного каталога с идентичными настройками - no-op; с другими - отказ. Порядок резолюции (первый матч выигрывает):

  1. переменная SPECKIT_CATALOG_URL перекрывает все;
  2. конфиг проекта .specify/extension-catalogs.yml;
  3. пользовательский ~/.specify/extension-catalogs.yml;
  4. встроенные дефолты: официальный default (install-allowed) + community (discovery-only).

Пример каталога организации:

yaml
catalogs:
  - name: "my-org-catalog"
    url: "https://example.com/catalog.json"
    priority: 5
    install_allowed: true
    description: "Our approved extensions"

--install-allowed включайте только для каталога, которым владеете и который вэтите; никогда - для непроверенного публичного.

Конфигурация расширений

Большинство расширений несут конфиги в каталоге установки:

text
.specify/extensions/<ext>/
├── <ext>-config.yml           # конфиг проекта (под версионным контролем)
├── <ext>-config.local.yml     # локальные оверрайды (gitignored)
└── <ext>-config.template.yml  # шаблон-референс

Слияние по возрастанию приоритета (последний - самый важный):

text
1. Дефолты расширения (extension.yml)
2. Конфиг проекта (<ext>-config.yml)
3. Локальные оверрайды (<ext>-config.local.yml)
4. Переменные окружения (SPECKIT_<EXT>_*)

Для настройки нового расширения скопируйте шаблон:

bash
cp .specify/extensions/<ext>/<ext>-config.template.yml \
   .specify/extensions/<ext>/<ext>-config.yml

Конфигурация расширений и хуков проекта

Регистрация расширений и хуков уровня проекта хранится в .specify/extensions.yml: установленные расширения, глобальные настройки и хуки, всплывающие до или после команд Spec Kit.

yaml
installed:
  - git
  - my-extension

settings:
  auto_execute_hooks: true

hooks:
  before_implement:
    - extension: git
      command: speckit.git.commit
      enabled: true
      optional: true
      priority: 10
      prompt: "Commit outstanding changes before implementation?"
      description: "Auto-commit before implementation"

  after_implement:
    - extension: my-extension
      command: speckit.my-extension.verify
      enabled: true
      optional: false
      priority: 5
      description: "Run verification after implementation"

Поля записи хука:

Поле Описание
extension ID расширения, зарегистрировавшего хук
command команда расширения, связанная с хуком
enabled активность; enabled: false - пропуск
optional true: хук показывается с prompt и может быть пропущен; false: эмитится как автоматический (с маркерами EXECUTE_COMMAND)
priority метаданные приоритета: целые >= 1; записи из манифестов без декларации получают 10. Текущие шаблоны команд выводят хуки в YAML-порядке конфигурации, не сортируя по priority
prompt сообщение при вопросе о запуске опционального хука
description человеческое пояснение
condition опциональное выражение для HookExecutor (config.<path> / env.<VAR>, операции is set, ==, !=). Текущие шаблоны команд условия не вычисляют и пропускают хуки с непустым condition

Имена событий: before_<command> / after_<command> - например, before_implement, after_implement, before_tasks, after_tasks.

Нормализация приоритетов: манифесты расширений отклоняют невалидные приоритеты при установке; для существующих записей HookExecutor.get_hooks_for_event() нормализует через normalize_priority() - отсутствующие значения, булеаны, отвергнутые int() строки и значения < 1 падают в 10; числовые строки и конечные float приводятся int(). Метод возвращает хуки, отсортированные по priority (меньше - раньше), но текущие шаблоны команд читают списки хуков напрямую и выводят в YAML-порядке.

Частые вопросы

  • Поиск не находит расширение: проверьте написание; расширение может быть не опубликовано или лежать в неподключенном каталоге (specify extension catalog list).
  • Команда расширения не появилась в агенте: проверьте specify extension list (installed + enabled), затем перезапустите агента - перезагрузка файлов может требоваться.
  • Конфликт версий: обновите Spec Kit до версии, требуемой расширением.
  • Кто поддерживает расширения: большинство создаются и поддерживаются авторами независимо; мейнтейнеры Spec Kit не ревьюят, не аудируют, не одобряют и не поддерживают код расширений. Ревьюйте исходники до установки; по проблемам конкретного расширения - к его автору или в репозиторий расширения.

Практика

  1. Установите bundled-расширение git, изучите .specify/extensions.yml (запись в installed), затем disable/enable и проверьте исчезновение/возвращение команд.
  2. Найдите в specify extension search расширение из discovery-only каталога, получите через info URL архива-кандидата и установите через --from - пройдите путь «обнаружение -> вэттинг -> установка».
  3. Скопируйте config-template любого установленного расширения в config.yml, поменяйте значение и проверьте порядок слияния с <ext>-config.local.yml.

Краткое резюме

Расширения добавляют возможности через команды, шаблоны, скрипты и хуки. Жизненный цикл: search -> add (каталог / --from URL / --dev локально / --version пин) -> update / enable / disable / set-priority / remove. Каталоги образуют стек приоритетов с границей безопасности: install-источники против discovery-only; community - discovery-only, установка найденного - через вэттинг --from или кураторский каталог организации. Конфигурация расширений сливается (дефолты -> проект -> локально -> env); хуки .specify/extensions.yml вешаются на before_/after_<command> с флагами optionality и приоритетами.

Главное из урока:

  • приоритет резолюции конфликтов - наименьшее число; дефолт 10;
  • bundled-расширения обновляются вместе с релизом spec-kit;
  • --version не падает на каталоги ниже приоритетом и не комбинируется с --dev/--from;
  • никогда не включайте install_allowed для невэтченного каталога;
  • хуки: optional: true - с промптом, optional: false - автоматический; condition текущими шаблонами не вычисляется.

Вопросы для самопроверки

  1. Перечислите источники установки расширения и их флаги. Какие флаги взаимно исключаемы?
  2. Почему community-каталог discovery-only? Какие два корректных способа установить найденное в нем?
  3. Опишите порядок резолюции каталогов расширений. Что перекрывает все?
  4. Как разрешается конфликт, когда два расширения дают команду с одним именем? Какой командой меняется приоритет установленного?
  5. Из каких слоев сливается конфигурация расширения? Какие файлы в каталоге расширения за что отвечают?
  6. Чем опциональный хук отличается от автоматического в .specify/extensions.yml? Что делает condition сегодня?

Что дальше

Пресеты меняют существующие шаблоны и команды без нового тулинга. Урок 16.13 - установка, стратегии композиции (replace/overlay), полный порядок резолюции файлов и управление каталогами пресетов.

Источники

Обновлено 03.10.2026