﻿# Gliver CLI

## Установка для сотрудника без репозитория

Потребуется Node.js 20+ и локальный терминал. CLI можно запускать напрямую либо из Codex, Cursor, Claude Code и других ассистентов с доступом к терминалу. Установщик скачивает проверенные контрольными суммами CLI и пользовательскую инструкцию для Codex, затем проверяет связь с продовым API. Как выбрать интерфейс, описано на [странице Gliver для ИИ](https://gliver.ru/ai/):

```bash
curl -fsSLo gliver-install.mjs https://gliver.ru/plugins/gliver-cli/install.mjs
node gliver-install.mjs
```

На Windows запустите в PowerShell:

```powershell
Invoke-WebRequest https://gliver.ru/plugins/gliver-cli/install.mjs -OutFile gliver-install.mjs
node .\gliver-install.mjs
```

CLI окажется в домашней папке `.gliver-cli/gliver.mjs`, инструкция Codex — в `.codex/skills/gliver-cli/SKILL.md` (или в `CODEX_HOME/skills`). Существующий файл авторизации установщик не изменяет. После установки откройте новую задачу Codex и попросите подключиться к Gliver; вход подтверждается в браузере под своей учётной записью. Повторный запуск установщика обновляет CLI и инструкцию.

## Запуск из репозитория

Node.js 20+; сторонние пакеты не нужны. Запуск из корня репозитория:

```bash
./bin/gliver help
./bin/gliver config set-url https://gliver.ru
./bin/gliver auth login
./bin/gliver auth complete
./bin/gliver me
```

Подтвердите вход по ссылке из `auth login` в своей учётной записи Gliver. Команда `auth complete` возвращает `authorization_pending`, пока подтверждение не сделано. Для проверки на dev-стенде переключите адрес командой `./bin/gliver config set-url https://dev.gliver.ru` до входа.

CLI работает в обычном терминале и в любых инструментах, которые могут запускать команды, включая Codex, Cursor и Claude Code. На странице подтверждения по умолчанию показывается «Gliver CLI». Чтобы различать подключения, передайте имя при входе, например `./bin/gliver auth login --client-name "Cursor · Gliver CLI"`. Название указывает клиент; оно не подтверждает его подлинность, поэтому сверяйте код подключения.

Примеры:

```bash
./bin/gliver catalog search диван --limit 10
./bin/gliver content list
./bin/gliver calc modules
./bin/gliver calc fabrics Омега
./bin/gliver calc module backrest --type free
./bin/gliver calc fabrics Вертикаль --module backrest --type free
printf '%s\n' '{"client":"Тестовый клиент","phone":"+7 999 000-00-00"}' | ./bin/gliver projects create
./bin/gliver orders list --limit 10
./bin/gliver projects checkout-options 123
./bin/gliver orders locations Москва
./bin/gliver projects create-order 123 < checkout.json
./bin/gliver orders get 456
./bin/gliver orders contractors 456 Название
./bin/gliver orders buyer 456 < buyer.json
./bin/gliver orders custom-classifiers 456 диван
./bin/gliver orders custom-create 456 < custom.json
./bin/gliver orders custom-update 456 789 < custom.json
./bin/gliver orders project-items 456
./bin/gliver orders add-project-item 456 < project-item.json
./bin/gliver orders catalog-colors 43662
./bin/gliver orders catalog-add 456 < catalog-item.json
./bin/gliver orders catalog-update 456 789 < catalog-item.json
./bin/gliver orders fabric-colors 43161
./bin/gliver orders fabric-add 456 < fabric-item.json
./bin/gliver orders stock-search кресло
./bin/gliver orders stock-add 456 < stock-item.json
./bin/gliver orders module-context 456 789
./bin/gliver orders module-update 456 789 < module.json
./bin/gliver orders update 456 < update.json
./bin/gliver orders update-item 456 789 < quantity.json
./bin/gliver audit list --source cli --user-id 22 --limit 50
./bin/gliver audit get REQUEST_ID
./bin/gliver orders operations 456
./bin/gliver orders references 456
./bin/gliver orders history 456
./bin/gliver orders shipping 456
./bin/gliver orders bill 456
./bin/gliver orders run 456 priority < priority.json
./bin/gliver orders download-file 456 789 --output ./order.pdf
./bin/gliver orders download-bill 456 --output ./bill.pdf
./bin/gliver pages list
./bin/gliver pages block-type title
```

### Конструктор страниц

Команды `pages` работают с существующим конструктором Bitrix в инфоблоке 31. Внутренние страницы используют шаблон `.default`, главная страница (ID 410, URL `/`) — шаблон `2023`. Для записи нужна учётная запись администратора либо право записи в инфоблок 31. Обычная роль менеджера такого права сама по себе не даёт.

Сначала найдите корневой раздел командой `pages roots` или вложенный раздел командой `pages list`, затем создайте черновик в действующем маршруте конструктора. Например, `parent_id` раздела `/blog/` на dev — 238:

```bash
printf '%s\n' '{"parent_id":238,"name":"Тестовая страница","code":"cli-test"}' | ./bin/gliver pages create
./bin/gliver pages block-type title
printf '%s\n' '{"if_version":"VERSION_ИЗ_PAGES_GET","type":"title","name":"Заголовок","properties":{"TITLE_TEXT":"Тестовая страница"}}' | ./bin/gliver pages add-block PAGE_ID
./bin/gliver pages get PAGE_ID
printf '%s\n' '{"if_version":"НОВАЯ_VERSION","active":true}' | ./bin/gliver pages update PAGE_ID
```

Чтобы работать с блоками главной, откройте её и запрашивайте схему именно шаблона `2023`:

```bash
./bin/gliver pages get 410
./bin/gliver pages block-types --template 2023
./bin/gliver pages block-type catsli --template 2023
printf '%s\n' '{"if_version":"VERSION_ИЗ_PAGES_GET","type":"title","name":"Заголовок","active":false,"properties":{"TITLE_TEXT":"Новый заголовок"}}' | ./bin/gliver pages add-block 410
```

Для существующих блоков главной используйте `pages update-block 410 BLOCK_ID`, `pages reorder 410` и `pages delete-block 410 BLOCK_ID` с актуальной версией. Блоки нельзя создать дочерним разделом главной; удаление и изменение настроек самой корневой страницы также закрыты. Новый блок на главной по умолчанию активен, поэтому при подготовке черновика укажите `active:false`.

### Конструктор в карточке товара

Вкладка «Технологии» берёт блоки из раздела конструктора каталога. Найдите раздел по ID товара или полной ссылке карточки (параметр `configuration` в ссылке игнорируется):

```sh
./bin/gliver pages product-card 'https://dev.gliver.ru/catalog/divany-francuz/divan-frantsuz-2-kh-mestnyy/?configuration=21'
./bin/gliver pages get 437
```

Ответ показывает разделы для обычной и express-карточки. `constructor_product_id` может отличаться от ID открытого товара: карточки товаров из конфигуратора используют раздел основного товара по той же логике, что сайт. Поле `product_card.product_ids` в `pages get` показывает **все** товары, на которые влияет редактирование общего раздела.

Чтобы собрать новую вкладку, создайте раздел под корнем `/catalog/` (ID 348) или его дочерним разделом, добавьте блоки через `pages add-block`, затем привяжите товар. Привязка делает блоки видимыми в карточке даже у неактивного раздела; проверьте содержимое до неё. Обычная и express-карточки настраиваются отдельно:

```sh
printf '%s\n' '{"parent_id":348,"name":"Технологии товара","code":"product-technology"}' | ./bin/gliver pages create
./bin/gliver pages get PAGE_ID
printf '%s\n' '{"if_version":"VERSION_ИЗ_PAGES_GET","product_id":1536,"express":false}' | ./bin/gliver pages link-product PAGE_ID
./bin/gliver pages product-card 1536
```

Если для товара и режима уже есть раздел, API вернёт 409: измените существующий раздел или снимите его привязку после проверки. Один раздел можно связать с несколькими товарами. Для снятия связи используйте свежий `version`: `printf '%s\n' '{"if_version":"VERSION","product_id":1536,"express":false}' | ./bin/gliver pages unlink-product PAGE_ID`. Привязывать товар из конфигуратора напрямую нельзя — используйте показанный `constructor_product_id`. Удаление раздела с привязанными товарами запрещено.

Все изменения страницы и блоков требуют свежего `if_version` из `pages get`; при конфликте API отвечает 409. Для перечислений используйте `xml_id` из `pages block-type <type>`. Файловые свойства получают `file_id` из `pages upload-file <путь>`. `pages reorder` принимает JSON вида `{"if_version":"...","block_ids":[11,22,33]}` со всеми ID блоков страницы. Чтобы скрыть блок, передайте `active:false` в `pages update-block`. Чтобы снять страницу с публикации, передайте `active:false` в `pages update`. `pages delete-block` удаляет блок; `pages delete` удаляет только неопубликованную страницу без блоков и дочерних страниц.

Для свойства с типом `ElementWithDescription` (например, `CONTENT_TABS_IDS`) передавайте массив объектов вида `[{"id":65687,"description":"Первая вкладка"}]`. Для свойства веб-формы (`EnumWithDescription`) выбирайте числовой `id` из `options` команды `pages block-type`. У обычных перечислений в `options` используется `xml_id`.

Если шаблон использует описание обычного свойства, передайте `{"value":"Текст","description":"Подпись"}`. Для файла передайте `{"file_id":123,"description":"Описание изображения"}`. В частности, шаблон `2023` использует описания изображений и заголовков слайдера `catsli`. При изменении множественного свойства передавайте весь массив: он заменяет прежний список, поэтому пропущенные слайды будут удалены.

Операции записи требуют соответствующей роли. CLI передаёт запросы в тот же API, которым могут пользоваться другие клиенты: `/api/agent/v1/openapi.json`.

Для расчёта найдите ткань через `calc fabrics Омега` и передайте её `id` в `fields.fabric_id`. CLI и API возьмут название и актуальную цену за погонный метр из справочника тканей сайта; вводить цену наугад не нужно. Пример запроса: `{"code":"french_double","fields":{"width":"1600","height":"1200","fabric_id":18178}}`. Для альтернативной ткани, как на сайте, вместо `fabric_id` можно передать вручную объекты `cloth_title` и `cloth_price` с одинаковыми ключами. Результат калькулятора предварительный, итоговая цена заказа определяется при оформлении.

Для модулей Фри и Драм (`angular`, `backrest`, `corner`, `puff`, `shaped` и их вариантов) поле `fields.type` обязательно: `free` или `drum`. Например: `{"code":"backrest","fields":{"type":"free","width":1200,"height":1050,"weight_correction":5,"fabric_id":20138}}`. Для правильного списка тканей используйте `calc fabrics Вертикаль --module backrest --type free`. Поле `weight_correction` означает процент: `0` — до 80 кг, `5` — 80–100 кг, `10` — 100–120 кг, `15` — 120–140 кг. При сохранении в проект передавайте те же `fields`, включая `type`.

Для Квадро доступны `quad_backrest`, `quad_angular` и `quad_puff`. Тип `quad` уже задан кодом модуля. Используйте `calc module quad_backrest`, чтобы получить допустимые размеры и фиксированные высоты. Например: `{"code":"quad_backrest","fields":{"width":1400,"height":1400,"fabric_id":104831}}`. Недопустимые для Квадро размеры API отклонит, как требует форма сайта.

Для добавления рассчитанного модуля в проект передайте `code`, `fields`, `item_index` и массив `configurations` через stdin в `projects add-calculated <id>`. Коды конфигураций берутся из `price_table` ответа `calc quote`. Если позиция пойдёт в заказ, передайте `fields.color` в обоих запросах и проверьте `ready_for_order` в `projects checkout-options`. Без цвета расчёт можно сохранить в проекте, но заказать нельзя. Повторяйте запрос после сбоя с тем же `--idempotency-key`.

Для изменения имени и телефона клиента получите карточку через `projects get <id>`, затем передайте в `projects update <id>` JSON с полями `client`, `phone` и `if_version` (значение `version` из карточки). Если проект успели изменить, API вернёт 409.

Работа с составом проекта: `projects update-calculated <id> <position>`, `remove-calculated`, `remove-configuration`, `color`, `custom-create/update/count/remove`, `catalog-create/update/count/remove`. Все новые операции записи требуют свежий `if_version` из `projects get`; CLI добавляет ключ идемпотентности. Для ручной позиции сначала найдите `classificator_id` командой `projects custom-classifiers <поиск>`. Для каталожной позиции возьмите `offer_id` из каталога и `color_id` из `orders catalog-colors <offer-id>`. Альтернативная ткань для каталожной позиции задаётся полями `material_mode: "alternative"`, `material_name`, `color` и `product_price` вместо `color_id`; можно добавить `second_color`. При замене каталожной позиции сайт создаёт новый ID — возьмите его из ответа.

Чтобы приложить изображение или PDF к ручной позиции проекта, выполните `projects upload-file <id> ./file.pdf --if-version HASH` и передайте полученный `path` в `pdf_paths` или `image_paths` команды `projects custom-create`/`custom-update`. При редактировании опущенное поле сохраняет прежние файлы, переданный массив заменяет их, пустой массив очищает.

`projects copy-with-fabric <id> < copy.json` повторно считает модули актуальным калькулятором. Передайте `positions`, `fabric_id` и `if_version`; цвет новых позиций очищается до выбора цвета новой ткани. Для старых позиций без `calculator_fields` передайте исходные параметры в `fields_by_position` по номерам позиций. `projects editor-select` выбирает модули по `xml_ids`, `projects scheme-save <id> ./scheme.png --if-version HASH` сохраняет PNG до 160 КБ, а `projects scheme-clear <id> < version.json` очищает схему перед новой расстановкой. `projects pdf <id> --type client|prod` формирует PDF, `projects history <id>` показывает изменения. Удаление проекта доступно автору или администратору по `projects delete <id> < version.json`.

Заказ оформляется из проекта по параметрам `checkout-options`: выберите позиции и варианты калькуляции, способ оплаты, доставку и город. В `checkout.json` укажите `if_project_version`, `items` и `checkout`. CLI автоматически передаёт ключ идемпотентности; после сбоя повторяйте с выведенным `idempotency_key`. Для изменения готового заказа используйте его свежий `version` в `if_version`. Контакты получателя, адрес, комментарий и количество позиции меняются отдельными запросами.

Команда `orders operations <id>` показывает действия, доступные при текущей роли и статусе заказа. `orders references <id>` возвращает справочники услуг, складов, организаций, дилеров, менеджеров, сроков доставки и статусов из карточки сайта. `orders contractors <id> <текст>` ищет существующих контрагентов. Покупатель и получатель меняются через `orders buyer <id>`: укажите `person_type` (`person` или `organization`), `recipient`, а для организации ещё `contractor_id` (число или `new`) и `company`. Смена юридического лица на физическое после выгрузки в 1С запрещена сайтом. Действия карточки выполняются через `orders run <id> <operation>` с JSON и свежим `if_version`, например `{"if_version":"HASH","value":"anytime"}` для `priority`. У заказов также доступны загрузка и удаление файлов, счёт, история, отгрузка, создание и отправка ссылки на оплату. Для смены покупателя, создания/отправки ссылки и изменения оплаты CLI создаёт ключ идемпотентности; после неопределённого результата повторяйте исходный запрос с выведенным `--idempotency-key`.

Операции с наличными, картой, возвратами и удалением платежей вызывают те же обработчики сайта, в том числе обмен с 1С и при необходимости фискализацию. Проверяйте заказ, сумму и адресата перед запуском. Полные примеры тел запросов — в [документации Gliver](https://gliver.ru/api/agent/v1/docs/).

Ручной товар создаётся через `orders custom-create`, а редактируется через `orders custom-update`. Сначала найдите `classificator_id` командой `orders custom-classifiers`; для существующей позиции вызовите `orders custom-context <id> <basket-id>`. В JSON передайте свежий `if_version`, `classificator_id`, `name`, `quantity`, `price`; размер, ткань, цвет и поправка на вес необязательны. Изображения JPEG/PNG/GIF и PDF загрузите через `orders upload-file` в этот заказ, затем передайте их ID в `image_file_ids` и `pdf_file_ids` (до 10 каждого типа). После каждой загрузки берите новый `version`. При редактировании отсутствие полей вложений сохраняет их, пустой массив удаляет. Обработчик сайта заменяет позицию и возвращает новый `basket_id`. Вложения позиции появятся в `orders get` и скачиваются через `orders download-file`.

В существующий заказ можно добавить готовый модуль из привязанного проекта: `orders project-items <id>` покажет позиции и доступные конфигурации, затем передайте в `orders add-project-item <id>` свежий `if_version`, `kind: "calculated"`, `position` и `configuration`. Для каталожной или ручной позиции проекта используйте `kind: "catalog"` либо `"custom"` и её `id`. Товар непосредственно из каталога добавляется через `orders catalog-add`: укажите `offer_id`, `color_id` и целое `quantity`; допустимые цвета вернёт `orders catalog-colors <offer-id>`.

Ткань из справочника добавляется через `orders fabric-add` с `kind: "catalog"`, `color_id` и `quantity`; `orders fabric-colors <fabric-id>` показывает цвета, цену для заказа и синхронизацию с 1С. Альтернативная ткань использует `kind: "alternative"`, `name`, `color`, `price`, `quantity`. Товар из наличия найдите через `orders stock-search`, затем передайте его `product_id` и `quantity` в `orders stock-add`. Для изменения товара каталога используйте `orders catalog-update <id> <basket-id>` с теми же полями, что при добавлении. Для пересчёта модуля получите `orders module-context <id> <basket-id>`, затем передайте в `orders module-update` свежий `if_version`, `fields` для калькулятора и `configuration`. Калькулятор сайта обновит позицию и проект; при смене комплектации `basket_id` изменится. Все команды записи требуют `if_version` из свежей карточки заказа и поддерживают повтор с тем же ключом идемпотентности.

Токен сохраняется в `~/.config/gliver-cli/state.json` с правами 0600. `GLIVER_CLI_STATE` задаёт другой путь для тестов. `GLIVER_BASE_URL` временно переопределяет адрес API.
