Agent Dev 101

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

Урок 16.9. Справочник CLI `specify`: core, MCP, аутентификация

На этой странице
  1. Зачем это нужно
  2. Основная идея
  3. specify init
  4. specify check
  5. specify version
  6. Экспериментальный MCP-сервер
  7. Аутентификация
  8. Практика
  9. Краткое резюме
  10. Вопросы для самопроверки
  11. Что дальше
  12. Источники

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

CLI specify управляет всем жизненным циклом проекта Spec Kit - от инициализации до автоматизации workflow (справочник по нему открывает блок D модуля). Этот урок - справочник по трем фундаментальным темам CLI: core-команды (init, check, version), переменные окружения, определяющие поведение в CI и монорепо; экспериментальный MCP-сервер; и opt-in аутентификация для приватных каталогов и расширений.

Справочные уроки блока D (16.10-16.16) предполагают, что эти основы усвоены.

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

Core-команды немногочисленны: init создает проект, check проверяет инструменты, version сообщает информацию о CLI. Вся мощь - в опциях init и переменных окружения, которые разделяют выбор проекта и выбор фичи как две независимые оси. MCP-сервер - экспериментальный stdio-мост к JSON-командам CLI (пока только version). Аутентификация opt-in: без ~/.specify/auth.json ни один запрос не несет креденшелов.

specify init

bash
specify init [<project_name>]
Опция Описание
--integration <key> интеграция coding-агента (copilot, claude, gemini и др.; полный список - урок 16.10)
--integration-options опции интеграции (например, --integration-options="--commands-dir .myagent/cmds")
--script sh|ps|py тип скриптов: sh (bash/zsh), ps (PowerShell), py (Python)
--here инициализировать в текущем каталоге вместо создания нового
--force слить/перезаписать без подтверждения при инициализации в непустом каталоге
--ignore-agent-tools пропустить проверку CLI-инструментов агентов
--preset <id> установить пресет при инициализации

Создает проект Spec Kit: структура каталогов, шаблоны, скрипты и файлы интеграции агента. Инициализацию Git-репозитория и ветвление ведет git-расширение, по умолчанию не ставящееся: specify extension add git после init включает git-workflows.

Примеры:

bash
# новый проект с интеграцией
specify init my-project --integration copilot

# в текущем каталоге
specify init --here --integration copilot

# принудительное слияние в непустой каталог
specify init --here --force --integration copilot

# PowerShell-скрипты
specify init my-project --integration copilot --script ps

# пресет при инициализации
specify init my-project --integration copilot --preset compliance

Без --integration интерактивный терминал предложит выбор; неинтерактивные сессии (CI, пайпы) берут GitHub Copilot - переопределите флагом или переменной SPECKIT_INTEGRATION_DEFAULT.

Переменные окружения

Переменная Назначение
SPECKIT_INTEGRATION_DEFAULT дефолтная интеграция specify init при отсутствии --integration (интерактивный дефолт и неинтерактивный fallback). Нераспознанное значение игнорируется с предупреждением, используется встроенный copilot. Явный --integration всегда важнее
SPECIFY_INIT_DIR целевой проект извне его каталога (например, из корня монорепо) без cd - для неинтерактива/CI. Указывает корень проекта - каталог, содержащий .specify/ (относительные пути резолвятся от текущего). Путь обязан существовать и содержать .specify/, иначе ошибка без fallback на текущий каталог. Значение наследуют core-скрипты фич (/speckit.plan, /speckit.tasks, ...) и создание веток git-расширения; те же правила валидации применяет каждая project-scoped-подкоманда (specify integration/extension/workflow/preset ...)
SPECIFY_FEATURE_DIRECTORY переопределить каталог активной фичи (приоритетнее .specify/feature.json). Относительный путь присоединяется к корню проекта без проверки вложенности - ../shared-feature тоже сработает; абсолютный используется как есть. Корень проекта по-прежнему задает контекст команд, но каталог фичи не обязан жить внутри него. Комбинируется с SPECIFY_INIT_DIR для неинтерактивного выбора проекта и фичи
SPECIFY_FEATURE явно переопределить метку активной фичи (например, 001-photo-albums) - идентификатор, который core-хелперы отдают как текущую фичу/ветку. Хелперы Git не инспектируют: с переменной возвращают ее дословно, без - пустую строку. Каталог фичи она не находит: с одной лишь SPECIFY_FEATURE разрешение путей фичи падает с ошибкой «Feature directory not found» - используйте SPECIFY_FEATURE_DIRECTORY или .specify/feature.json
SPECIFY_FEATURE_NO_PERSIST 1/true запрещает core-скриптам писать .specify/feature.json, даже когда они персистили бы SPECIFY_FEATURE_DIRECTORY. Полезно, когда несколько агентов работают параллельно с одним checkout и у каждого своя SPECIFY_FEATURE_DIRECTORY - без флага каждый вызов может перезаписать чужую закрепленную фичу

Две оси резолюции: SPECIFY_INIT_DIR выбирает проект (какой каталог содержит .specify/); SPECIFY_FEATURE_DIRECTORY / .specify/feature.json выбирают фичу - по умолчанию она под specs/ проекта, но явно выбранный каталог фичи не обязан быть внутри него. Оси независимы: сначала проект, затем фича.

Контроль версий: specify init scaffolds управляемый .specify/.gitignore, исключающий machine-local-состояние - feature.json (указатель текущей фичи, перезаписывается при каждом переключении) и per-machine оверрайды расширений extensions/*/local-config.yml - при сохранении шаримости всего остального (конституция, шаблоны, скрипты, конфигурация расширений). Файл отслеживается в манифесте общей инфраструктуры: правки сохраняются при re-init, specify init --here --force восстанавливает managed-контент. specify integration uninstall его не удаляет.

Симлинки: SPECIFY_INIT_DIR переносит, где находится проект, а не меняет отношение команд к симлинкам; команды с широкими путями записи (bundle, workflow run <file>) отказываются работать с симлинкованным .specify/, сохраняя конфайнмент записи.

Именование фич в helper-скриптах

Хелперы create-new-feature при прямом вызове сохраняют Unicode-буквы и цифры в UTF-8: описание «добавить пользователя» даст 001-добавить-пользователя (пример оригинала - 添加用户 -> 001-添加用户). Описание из одной пунктуации даст пустой суффикс 001-; скрипты предупреждают в stderr, JSON-вывод остается парсибельным. Сменить имя, не меняя описания:

bash
bash .specify/scripts/bash/create-new-feature.sh --json --short-name 用户管理 "添加用户"

Python-хелпер принимает --short-name, PowerShell - -ShortName. Короткое имя чистится теми же правилами и обязано содержать букву или цифру. ASCII-капитал переводится в нижний регистр; регистр не-ASCII букв сохраняется.

specify check

bash
specify check

Проверяет доступность CLI-based AI-агентов в системе. IDE-based агенты пропускаются - CLI-инструмент им не нужен. Команда остается офлайн. Если команда ведет себя как старая версия Spec Kit или ожидаемая фича отсутствует - прогоните specify self check, не отстает ли локальный CLI от последнего релиза.

specify version

bash
specify version

Показывает версию CLI, Python, платформу и архитектуру. Инспекция локальных возможностей без сети:

bash
specify version --features

Полная информация (версия, рантайм, система, фичи) как JSON:

bash
specify version --json

Комбинация --features и --json дает тот же полный JSON - --features в JSON-режиме не фильтрует. Недоступная информация OpenSSL отражается как runtime.openssl: null. Успешный JSON пишется только в stdout; при сбое stdout пуст, а в stderr уходит один санитизированный JSON-объект ошибки. Быстрая проверка: specify --version / specify -V.

Экспериментальный MCP-сервер

bash
specify mcp

Стартует сервер Model Context Protocol поверх только stdio. HTTP, SSE, управление демоном/сервисом и выбор транспорта не предоставляются; MCP-хост настраивается на запуск specify mcp как локального субпроцесса. Поскольку stdout несет кадры протокола MCP, сервер не печатает туда баннер, Rich-вывод, стартовые сообщения, предупреждения и логи.

Сервер экспонирует три generic-инструмента:

Инструмент Назначение
specify_list_commands список CLI-команд, поддержанных через MCP
specify_describe_command описание одной поддержанной dotted-команды
specify_run_command запуск одной поддержанной команды через реальный CLI

Первый экспериментальный релиз поддерживает только dotted-команду version; остальные имена отклоняются ошибкой unavailable_command. Сервер не экспонирует обнаружение проектов, артефакты, мутации, установку/обновление, workflows, подтверждения или уровни доступа.

specify_run_command вызывает каноническую команду specify version --json в изолированном дочернем процессе того же Python-окружения. Успех - прямой JSON-объект команды (cli_version, runtime, system, features) без обертки schema_version/ok/result. Сбой CLI - ошибка инструмента с error.code, error.message, error.details из stderr. Пустой/битый/смешанный вывод дочернего процесса - санитизированная adapter_internal_error; сервер никогда не подставляет success-shaped fallback и не раскрывает traceback.

Статус: experimental - инвентарь команд и контракты инструментов могут меняться до объявления MCP-поверхности стабильной.

Аутентификация

Specify CLI использует opt-in-аутентификацию для HTTP-запросов к источникам каталогов, загрузкам расширений и проверкам релизов. Без явной конфигурации креденшелов не отправляется ничего.

Конфигурация

Файл ~/.specify/auth.json включает аутентификацию:

json
{
  "providers": [
    {
      "hosts": ["github.com", "api.github.com", "raw.githubusercontent.com", "codeload.github.com"],
      "provider": "github",
      "auth": "bearer",
      "token_env": "GH_TOKEN"
    }
  ]
}

Безопасность: ограничьте файл доступом только владельца:

bash
chmod 600 ~/.specify/auth.json

Поля записи

Поле Обязательно Описание
hosts да массив имен хостов; точные имена или ведущий *. только для поддоменов (*.visualstudio.com матчит foo.visualstudio.com, но не visualstudio.com; прочие glob-паттерны не поддерживаются)
provider да встроенный провайдер: github, azure-devops, bitbucket
auth да схема (см. ниже)
token нет значение токена inline; предпочитайте token_env
token_env нет имя переменной окружения с токеном
username для basic имя пользователя Basic-креденшела (для API-токенов Bitbucket - email аккаунта Atlassian); без :

Для azure-ad дополнительно: tenant_id, client_id, client_secret_env (переменная с секретом service principal). Для схем bearer, basic-pat, basic обязателен token или token_env.

Провайдеры и схемы

GitHub. Схема bearer (Authorization: Bearer <token>) - PAT, fine-grained PAT, OAuth, токены GitHub App. Для GitHub Enterprise Server добавьте github-запись с вашими GHES-хостами: она аутентифицирует и fetch каталогов, и загрузки приватных release-ассетов через GHES REST API (/api/v3). Перечисляйте голый web-хост (ghes.example.com) - там живут URL загрузок релизов; при изоляции поддоменов добавьте и raw./codeload.-поддомены (wildcard *.ghes.example.com голый хост не матчит). Для GHE.com с data residency перечисляйте оба хоста - web и API (tenant.ghe.com, api.tenant.ghe.com).

Azure DevOps. Схемы: basic-pat (PAT), bearer (предвыданные OAuth/Azure AD-токены), azure-cli (токен из az account get-access-token, требует предварительного az login), azure-ad (OAuth2 client credentials flow - для CI/автоматизации).

json
{
  "hosts": ["dev.azure.com"],
  "provider": "azure-devops",
  "auth": "azure-ad",
  "tenant_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "client_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "client_secret_env": "AZURE_CLIENT_SECRET"
}

Bitbucket. Схемы: bearer (access-токены репозитория/проекта/workspace; Atlassian API-токены без email - только api.bitbucket.org; HTTP-токены Data Center) и basic (Atlassian API-токены с email аккаунта как username против api.bitbucket.org; app-пароли Bitbucket Cloud удалены Atlassian 28.07.2026 - используйте API- или access-токен).

Нюанс хостов: web-хост bitbucket.org (страницы браузера, ссылки .../raw/..., git clone по HTTPS) эти креденшелы не принимает. Направляйте каталоги и download_url на api.bitbucket.org (например, GET /2.0/repositories/<workspace>/<repo>/src/<ref>/catalog.json). Загрузки из секции Downloads идут редиректом на pre-signed S3 URL: Specify срезает заголовок Authorization при уходе с заявленных хостов - это ожидаемо, S3 URL самоавторизован; пин sha256 в записях каталога сохраняет integrity-check последнего неаутентифицированного хопа.

Множественные записи и механика

Записей может быть несколько - под разные хосты или организации (например, GitHub + Azure DevOps в одном файле). Как это работает:

  1. Для каждого исходящего HTTP-запроса hostname матчаится с паттернами hosts в auth.json.
  2. При совпадении провайдер резолвит токен и прикрепляет нужный заголовок Authorization.
  3. При ответе 401/403 пробуется следующая совпадающая запись.
  4. Когда совпадающие записи исчерпаны - финальная попытка без аутентификации.
  5. При редиректе заголовок Authorization срезается, если цель покидает заявленные хосты записи - креденшелы не утекают на CDN и сторонние сервисы.

Практика

  1. Инициализируйте тестовый проект с переменной SPECKIT_INTEGRATION_DEFAULT=gemini без флага --integration в неинтерактивном режиме - проверьте, что fallback сработал; затем задайте неверное значение и убедитесь в предупреждении.
  2. В монорепо-подобной структуре попробуйте пару SPECIFY_INIT_DIR + SPECIFY_FEATURE_DIRECTORY из корня: убедитесь, что команды находят проект и фичу без cd, а ошибочный SPECIFY_INIT_DIR (без .specify/) дает ошибку, а не fallback.
  3. Соберите auth.json с token_env для любого своего хостинга, проверьте chmod 600, затем запустите specify version --json - убедитесь, что команда работает независимо от auth-конфигурации (аутентификация opt-in, только для HTTP-запросов к каталогам/релизам).

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

Core-слой CLI мал и предсказуем: init (опции интеграции, скриптов, пресета, интерактива), офлайн check и многоформатный version. Поведение в CI и монорепо управляется пятью переменными окружения с двумя независимыми осями - проект (SPECIFY_INIT_DIR) и фича (SPECIFY_FEATURE_DIRECTORY), плюс защита параллельных агентов SPECIFY_FEATURE_NO_PERSIST. specify mcp - экспериментальный stdio-сервер с поверхностью из трех generic-инструментов и единственной командой version. Аутентификация - opt-in через ~/.specify/auth.json с провайдерами GitHub/Azure DevOps/Bitbucket, матчитнгом хостов, каскадом 401/403 и срезанием Authorization на внешних редиректах.

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

  • specify init не инициализирует Git - это делает opt-in git-расширение;
  • SPECIFY_FEATURE задает только метку фичи, не ее каталог - каталог выбирается SPECIFY_FEATURE_DIRECTORY или feature.json;
  • MCP-сервер пока version-only: не рассчитывайте на него для управления проектами;
  • без auth.json запросы анонимны; токены храните в переменных окружения (token_env), а не inline;
  • для Bitbucket указывайте api.bitbucket.org, не bitbucket.org/.../raw/....

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

  1. Перечислите опции specify init и их назначение. Какая опция устанавливает пресет при инициализации?
  2. Объясните разницу между SPECIFY_INIT_DIR, SPECIFY_FEATURE_DIRECTORY и SPECIFY_FEATURE. Почему оси проекта и фичи независимы?
  3. Зачем нужна SPECIFY_FEATURE_NO_PERSIST? Какую проблему параллельной работы она решает?
  4. Какую единственную команду поддерживает экспериментальный MCP-сервер и как обрабатываются сбои дочернего процесса?
  5. Опишите алгоритм аутентификации исходящего запроса: от матчинга хостов до финального fallback. Когда срезается Authorization?
  6. Почему для Bitbucket Cloud каталоги должны указывать на api.bitbucket.org? Что происходит с заголовком при редиректе на S3?

Что дальше

Интеграции - интерфейс между CLI и вашим coding-агентом. Урок 16.10 разбирает 38 интеграций: куда пишутся файлы команд, как переключаться между агентами, синтаксис вызова и каталог интеграций.

Источники

Обновлено 03.10.2026