Перейти к содержимому

Командная строка: signallab ​

signallab — это Signal Lab без окна. Он доводит эксперименты до конца и завершается кодом, который понимает скрипт, отправляет одно OSC-сообщение, датаграмму, HTTP-запрос, сообщение WebSocket или публикацию MQTT, отправляет сигнал из вашей библиотеки, играет эмулятор, пока вы его не остановите, и говорит, что стоит между этой машиной и оборудованием.

Это тот же движок, что в приложении: запуск из командной строки делает те же шаги, пишет тот же отчёт и говорит то же самое — на языках интерфейса. С --server запуски выполняются на сервере Signal Lab: с его сетью и его секретами.

bash
signallab run tests/smoke.json --param api=http://127.0.0.1:8080 --junit junit.xml
signallab run flaky-api                                # встроенный шаблон, по имени
signallab validate tests/*.json                        # проверка, как в редакторе, ничего не отправляется
signallab send osc 127.0.0.1:9000 /cue/go f:0.75 s:main
signallab send http GET http://127.0.0.1:8080/health --expect-status 200
signallab fire "Fader value"
signallab emulate tests/orders-api.json --for 120      # эмулировать зависимость две минуты
signallab doctor                                       # брандмауэр, сеть, папка данных

Для конвейеров см. Signal Lab в CI; для ИИ-ассистента — signallab mcp.

Установка ​

ГдеКак получить signallab
Windows, установщик (.exe)Устанавливается рядом с приложением, а эта папка добавляется в PATH — пользовательский при установке «для меня», общий для машины при установке «для всех». После установки откройте новый терминал. Ключ установщика /NOPATH оставляет PATH в покое.
Windows, .msiУстанавливается рядом с приложением; папка установки находится в PATH машины, пока приложение установлено.
Linux, .deb и .rpm/usr/bin/signallab.
Linux, AppImageНе входит: используйте архив ниже.
Любая машина, без приложенияВ каждом выпуске есть signallab-<version>-windows-x64.zip и signallab-<version>-linux-x64.tar.gz, в каждом — программа и её лицензия; контрольные суммы перечислены в SHA256SUMS.txt на той же странице.
Образ сервера/usr/local/bin/signallab в ghcr.io/proanima/signallab (см. CI).

Проверьте так:

bash
signallab version

Команды ​

КомандаЧто делает
runЗапускает эксперименты один за другим; завершается с кодом 0, только если все прошли.
validateПроверяет эксперименты так, как это делает редактор перед запуском; ничего не отправляет.
sendОтправляет одно сообщение: osc, udp, http, ws или mqtt.
fireОтправляет сигнал из библиотеки сигналов по его id или имени.
emulateИграет HTTP API, OSC-, UDP- или TCP-устройство либо MQTT-брокер до Ctrl+C или --for.
emulatorsВыводит список эмуляторов из библиотеки приложения.
templatesВыводит список встроенных шаблонов экспериментов.
nodesОписывает каждый вид узла в виде JSON.
mcpПредоставляет Signal Lab ИИ-ассистенту по Model Context Protocol.
doctorПроверяет брандмауэр, сеть, папку данных и сервер.
firewallfirewall allow: разрешает другим машинам достучаться до Signal Lab через брандмауэр Windows.
versionПечатает версию.

signallab help <command> или signallab <command> --help выводит параметры команды.

Параметры всех команд ​

ПараметрЧто делаетПо умолчанию
--lang <code>Язык сообщений: en, ru, es, fr, de, pt, zh, ja, ko, hi или ar.SIGNALLAB_LANG, иначе локаль, иначе en
--jsonВывод для машин в stdout вместо текста (см. Вывод).выкл.
-h, --helpСправка по команде.
-V, --versionВерсия; перед любой командой, как signallab --version.

И --lang, и --json можно ставить в любое место строки: signallab --json run smoke.json и signallab run smoke.json --json — одно и то же.

Язык ​

Сообщения, тексты шагов, сбои и отчёт JUnit используют собственные тексты интерфейса, его формы множественного числа и стиль чисел. Язык определяется по первому из пунктов:

  1. --lang;
  2. SIGNALLAB_LANG (ru, ru-RU и ru_RU.UTF-8 — всё это русский);
  3. локаль: первая заданная из LC_ALL, LC_MESSAGES и LANG;
  4. английский.

TIP

Терминалы Windows обычно не задают ни одной переменной локали, поэтому signallab там говорит по-английски, пока вы не зададите SIGNALLAB_LANG или не передадите --lang.

Вывод для людей и для машин ​

Без --json результаты идут в stdout, а всё, что человек читает по ходу дела, — в stderr: шаги запуска по мере их выполнения, почему что-то не удалось, где лежит отчёт. signallab run … 2>/dev/null оставляет по одной строке-вердикту на запуск.

С --json в stdout идёт JSON и ничего больше, а stderr молчит:

КомандаЧто --json печатает в stdout
runПо объекту на строку: started, step на каждый шаг, ended (результат запуска), затем summary; error для запуска, который не удалось начать. См. Что печатает run.
validateПо объекту на строку, на каждый эксперимент: valid, а также profile_issues или error.
send, fire{"type": "sent", "result": …}; send http печатает {"type": "response", "response": …}, send ws — {"type": "exchange", "result": …}.
emulateПо объекту на строку: started, exchange на каждый запрос, summary на каждый эмулятор; valid с --check.
emulators{"path": …, "emulators": [{id, name, protocol, bind, rules, note}, …]}.
templates[{"name": …, "experiment": …}, …].
doctorОдин объект: version, network, data_dir, firewall, server, problems.
version{"version": "…"}.
nodesВсегда JSON, с --json и без него.

Сбой выглядит как {"type": "error", "error": {…}, "exit_code": N}. error — это ошибка движка: стабильный code (например, transport.refused или secret.missing), её params, а также node и field, о которых она. Скрипт может ветвиться по error.code на любом языке; тексты для всех кодов перечислены в Сообщениях об ошибках.

Коды завершения ​

КодЗначение
0Все эксперименты прошли; отправка удалась; ничто не мешает.
1Эксперимент запустился и не прошёл, не уложился во время или был остановлен; отправка не удалась (отказ в соединении, нет ответа, неожиданный статус); doctor нашёл то, что мешает.
2Неверна команда или документ: аргумент, файл, который не читается, ошибка проверки, неизвестный параметр, отсутствующий секрет.
3Ничего не удалось запустить по причине вне эксперимента: сервер недоступен или не принимает токен, не открывается порт, сбой хранилища учётных данных.

Если экспериментов несколько, решает самый серьёзный результат в таком порядке: 2, затем 3, затем 1, затем 0.

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

ПеременнаяЧто делает
SIGNALLAB_LANGЯзык, когда --lang не задан.
LC_ALL, LC_MESSAGES, LANGЯзык, когда не задана ни одна из переменных выше.
SIGNALLAB_SERVERСервер для run, validate, emulate, mcp и doctor, как его задаёт --server.
SIGNALLAB_TOKENТокен доступа сервера, когда файл токена не задан.
SIGNALLAB_TOKEN_FILEФайл с токеном сервера, как его задаёт --token-file.
SIGNALLAB_SECRET_<NAME>Значение секрета NAME для запусков в этом процессе (см. Секреты).
SIGNALLAB_DATA_DIRПапка данных приложения, где по умолчанию ищут fire, emulators, emulate, mcp и doctor; иначе Documents/SignalLab в вашей домашней папке.
GITHUB_ACTIONSЕсли она равна true, запуск, который не прошёл, дополнительно печатается как аннотация ::error, которую GitHub показывает на странице запуска.

run ​

text
signallab run [OPTIONS] <FILE>...

Запускает эксперименты один за другим и завершается с кодом 0, только если все прошли.

ПараметрЧто делаетПо умолчанию
<FILE>...Файлы экспериментов или имена встроенных шаблонов.обязательно
-p, --param NAME=VALUEЗначение параметра для этого запуска; повторите для других.значения из документа
--profile NAMEЗапустить с этим профилем; он должен быть в каждом из заданных экспериментов. "" запускает со значениями по умолчанию.профиль из документа
-m, --matrix NAME=V1,V2Запустить по разу на каждое значение; повторите для других имён (см. Матрица запусков).
--matrix-file PATHКомбинации из файла JSON.
--seed NSeed случайных значений, от 0 до 9007199254740991 (2⁵³ − 1).seed из документа, иначе новый на каждый запуск
--timeout SECONDSПровалить запуск, который длится дольше, 1–300.300
--fail-fastОстановиться на первом запуске, который не прошёл; остальные не запускаются.выкл.
--junit PATHЗаписать туда отчёт JUnit XML (см. Отчёты).
--report PATHСкопировать туда отчёт о запуске: файл для одного запуска, папку для нескольких.
--data-dir PATHПапка данных для запусков этого процесса; их отчёты остаются в ней.временная папка, удаляется при выходе
--server URLВыполнять на этом сервере, а не в этом процессе (см. Запуск на сервере).SIGNALLAB_SERVER
--token-file PATHФайл с токеном сервера.SIGNALLAB_TOKEN_FILE, иначе SIGNALLAB_TOKEN
--secrets files|systemОткуда в этом процессе берутся значения секретов.files
--secrets-dir PATHПапка файлов секретов, по одному на имя./run/secrets/signallab, если она существует

--data-dir, --secrets и --secrets-dir относятся к запускам в этом процессе; с --server их сочетать нельзя.

Файлы и шаблоны ​

FILE — это эксперимент в том виде, в каком приложение его сохраняет и экспортирует (кнопка Экспорт текущей схемы на экране Эксперименты). Подойдёт любая версия документа, которую открывает приложение; более старая приводится к новой при чтении — так же, как это делает приложение, когда её открывает. Имя, которое не является файлом, ищется среди встроенных шаблонов, с .json или без:

bash
signallab run tests/stage-cues.json tests/api.json
signallab run osc-ping-reply --param device=192.0.2.20:9000

Каждый эксперимент — и каждая комбинация матрицы — проверяется так, как его проверяет редактор, до того, как запустится первый. Неисправный третий файл останавливает и первый — до отправки чего-либо, с кодом завершения 2.

Параметры и профили ​

--param NAME=VALUE задаёт параметр только для этого запуска; файл не меняется. Значение — это всё, что стоит после первого =, поэтому работает --param url=http://127.0.0.1/?q=1, а --param note= задаёт пустое значение. Значение применяется к каждому заданному эксперименту, у которого есть такой параметр, и должно называть параметр хотя бы одного из них — опечатка в имени отклоняется с кодом завершения 2.

--profile NAME запускает с одним из профилей эксперимента — как если выбрать профиль в поле Профиль в редакторе. См. Данные и шаблоны.

Матрица запусков ​

Матрица запускает один и тот же эксперимент для каждой цели, каждого пользователя, каждого размера содержимого. Каждая комбинация — отдельный запуск со своим результатом, своим отчётом и своим набором тестов в отчёте JUnit.

bash
signallab run smoke.json \
  -m device=192.0.2.20:9000,192.0.2.21:9000 \
  -m user=admin,guest \
  --fail-fast --junit junit.xml

Это четыре запуска: device меняется медленнее всего, user — быстрее всего. Они называются по файлу и своим значениям: smoke.json [device=192.0.2.20:9000, user=admin].

  • --matrix NAME=V1,V2 добавляет ось. То же имя ещё раз добавляет к ней значения. Пробелы вокруг имён и значений отбрасываются; значение, заданное дважды, запускается один раз.

  • --matrix-file PATH читает JSON одного из двух видов:

    json
    { "device": ["192.0.2.20:9000", "192.0.2.21:9000"], "retries": [1, 3] }

    добавляет оси — запускается каждая комбинация, эти имена идут после имён из --matrix, в алфавитном порядке;

    json
    [
      { "device": "192.0.2.20:9000", "user": "admin" },
      { "device": "192.0.2.21:9000", "user": "guest" }
    ]

    перечисляет сами комбинации, каждая из которых скрещивается с осями --matrix. Значения — текст, числа или true/false; запятая внутри значения в файле остаётся его частью.

  • Каждое имя матрицы должно быть параметром хотя бы одного из заданных экспериментов. Эксперимент без какого-то из них запускается один раз, а не по разу на каждое значение, которое он бы игнорировал.

  • Имя, заданное и в --param, и в матрице, или и в --matrix, и в файле, отклоняется.

  • Не более 256 запусков из одной команды; больше отклоняется до того, как что-либо запустится.

Запуск на сервере ​

bash
signallab run tests/stage.json --server http://192.0.2.10:1430 --token-file token.txt

Эксперимент берётся с этой машины; сервер запускает его со своей сетью, своими секретами и своей папкой данных и присылает шаги обратно по мере их выполнения. Отчёт остаётся на сервере — его путь печатается, — а --report скачивает копию. Запуск на сервере там — такая же задача, как запущенная из его интерфейса: её видит каждая вошедшая страница. Если signallab пропадёт посреди запуска, запуск всё равно завершится на сервере и сохранит свой отчёт.

Токен читается из --token-file (или SIGNALLAB_TOKEN_FILE), иначе из SIGNALLAB_TOKEN, и отправляется как Authorization: Bearer. Недоступный сервер, отказ принять токен или то, что сервер перестал отвечать посреди запуска, — это код завершения 3. signallab doctor --server URL проверяет адрес и токен отдельно.

Отчёты ​

Каждый запуск пишет тот же отчёт, что пишет приложение. Без --data-dir запуски используют временную папку, которая удаляется при выходе из signallab, поэтому сохраняйте то, что нужно:

  • --report PATH копирует отчёт: в сам PATH для одного запуска или в папку PATH для нескольких — как 01-<file>.json, 02-<file>.json, … в порядке запуска.
  • --data-dir PATH хранит отчёты всех запусков в этой папке (в runs/) и печатает, где лежит каждый.

--junit PATH пишет отчёт JUnit XML — формат, который читает любая CI-система:

  • <testsuite> на каждый запуск (на каждую комбинацию матрицы), со свойствами: файл, seed, исход, профиль, путь к отчёту и каждое значение матрицы (param.NAME);
  • <testcase> на каждый выполнявшийся узел, названный по типу узла и его id, со своим временем;
  • <failure> на узле, который не прошёл: сообщение на выбранном языке, код ошибки как его type и шаги узла с техническими подробностями;
  • случай <skipped> для каждого узла, до которого запуск не дошёл (другая сторона ветвления);
  • набор с одним случаем <error> для эксперимента, который не удалось начать, и набор со случаем <skipped> для каждого запуска, который --fail-fast не начал.
xml
<testsuites name="Signal Lab" tests="6" failures="1" errors="0" time="2.006">
  <testsuite name="HTTP to OSC" tests="6" failures="1" errors="0" skipped="4" time="2.006" timestamp="2026-10-04T16:48:03">
    <properties>
      <property name="file" value="status-branch" />
      <property name="seed" value="42" />
      <property name="outcome" value="failed" />
      <property name="report" value="out/report.json" />
    </properties>
    <testcase name="Start (start)" classname="HTTP to OSC" time="0.001">
      <system-out>Started · seed 42</system-out>
    </testcase>
    <testcase name="HTTP request (request)" classname="HTTP to OSC" time="2.004">
      <failure message="http://127.0.0.1:8080/ refused the connection — nothing is listening on that port" type="transport.refused">…</failure>
    </testcase>
    <testcase name="Status branch (branch)" classname="HTTP to OSC" time="0.000">
      <skipped message="not reached in this run" />
    </testcase>
    …
  </testsuite>
</testsuites>

HTTP-узел под нагрузкой добавляет под своим последним шагом строку для каждого порога, выдержанного или нет (✕ p95 < 100 ms · 152.58 ms); не выдержанный порог проваливает запуск и его случай JUnit (type="load.threshold").

Секреты ​

Эксперимент читает секрет как {{secret.NAME}}. Для запусков в этом процессе значение берётся отсюда:

--secretsОткуда берётся значение NAME
files (по умолчанию)Переменная окружения SIGNALLAB_SECRET_NAME; иначе файл NAME в --secrets-dir (по умолчанию /run/secrets/signallab, если такая папка существует — раскладка секретов Docker).
systemДиспетчер учётных данных Windows — там приложение хранит значения из раздела Секреты. В Linux хранилища учётных данных, которое читает signallab, нет: там --secrets system завершается с кодом 3.

Перевод строки в конце файла не входит в значение, а пустое значение считается незаданным. Имена состоят из букв, цифр и _, не начинаются с цифры и содержат до 128 символов; значение — не больше 16 КиБ.

bash
SIGNALLAB_SECRET_API_TOKEN="$API_TOKEN" signallab run tests/api.json

Секрет, который не задан, останавливает запуск до любого трафика, с кодом завершения 2 и именем недостающего секрета. Значение никогда не печатается: шаги, ошибки, отчёты и отчёт JUnit показывают на его месте ••••. С --server секреты — это секреты сервера.

Что печатает run ​

По ходу запуска каждый шаг — строка в stderr: время от начала, узел, его состояние и что он сделал — как в ленте приложения. Когда запуск заканчивается, одна строка в stdout сообщает, как он прошёл:

text
▶ HTTP check (http-check) · seed 1185927457137919
     0.000  Start         Running
     0.000  Start         Passed · Started · seed 1185927457137919
     0.000  HTTP request  Running
     2.004  HTTP request  Failed · URL — http://127.0.0.1:8080/ refused the connection — nothing is listening on that port
✖ HTTP check failed after 2 s: HTTP request · URL — http://127.0.0.1:8080/ refused the connection — nothing is listening on that port
  Technical details: error sending request for url (http://127.0.0.1:8080/): … (os error 10061)
  To run it again with the same random values: --seed 1185927457137919

Запуск, который не прошёл, называет использованный seed: --seed с этим числом запускает его снова с теми же случайными значениями. После вердикта в stderr идёт то, о чём спрашивали каждый эмулятор запуска, — запросы, сколько из них не взяло ни одно правило, сколько провалилось и сколько попаданий на каждое правило:

text
✔ Retry a flaky API passed in 7 ms
  Flaky API: 3 requests, 0 without a rule, 0 failed · #1 3

и что сделало каждое реле помех: что получило, отбросило и ограничило, а каждая фаза — сколько переслано / получено:

text
  127.0.0.1:19110 → 127.0.0.1:19100: 155 datagrams, 38 dropped, 0 throttled · lan 0.0–2.0 s 39/39, wifi 2.0–4.0 s 39/39, offline 4.0–6.0 s 0/38, lan 6.0–8.0 s 38/38

Реле по TCP двигает фрагменты потоков, а не датаграммы, и ничего не отбрасывает, поэтому его строка считает фрагменты, соединения, сбросы, полуоткрытые соединения и сколько раз поток был придержан ограничением полосы:

text
  127.0.0.1:19120 → 127.0.0.1:19101: 14 chunks, 2 connections, 1 reset, 0 half-open, 3 held back

HTTP-узел под нагрузкой сообщает о ходе работы шагом не чаще раза в секунду.

Если запусков несколько, вывод заканчивается строкой на каждый запуск и итогом: 3 runs: 2 passed, 1 failed. С --fail-fast незапущенные запуски подсчитываются в stderr.

С --json каждая строка — объект с полем type:

json
{"type":"started","experiment":"Empty experiment","file":"empty","job_id":1,"overridden":false,"profile":null,"seed":1,"started_ms":1791132204585}
{"type":"step","node_id":"start","state":"passed","detail":"Started","message_key":"exp.step.started","message_params":{"seed":1},"job_id":1,"ts":1791132204585}
{"type":"ended","experiment":"Empty experiment","file":"empty","outcome":"passed","seed":1,"params":{},"steps":[…],"report_path":"…","started_ms":1791132204585,"ended_ms":1791132204585,…}
{"type":"summary","total":1,"passed":1,"failed":0,"not_started":0,"exit_code":0}

Строки started, ended и error несут file (аргумент как он задан) и, в матрице, matrix (значения комбинации). ended — весь результат запуска: outcome (passed, failed или stopped), seed, profile, params, error, каждый шаг, emulators и impairments, если они были в запуске, и report_path. Последний шаг нагрузки несёт load со всеми измеренными числами: planned, sent, ok, failed, missed, rps, error_rate, min_ms, mean_ms, max_ms, от p50_ms до p99_ms, statuses, каждую секунду (seconds), histogram и вердикт по каждому порогу (thresholds).

validate ​

text
signallab validate [OPTIONS] <FILE>...

Проверяет эксперименты так, как это делает редактор перед запуском, — граф, каждое поле, шаблоны, параметры и секреты, — и ничего не отправляет. Завершается с кодом 0, если запустился бы каждый.

Принимает те же входные данные, что и run: файлы и шаблоны, --param, --profile, --matrix, --matrix-file, а также --server, --token-file, --secrets, --secrets-dir. С --server их проверяет сервер, по своим секретам.

text
✔ tests/stage.json: Stage cues would run
  Rehearsal: Would not run: …

Проблема, которая есть только у другого профиля документа, перечисляется под ним, но проверку не проваливает. С --json — по строке на эксперимент (на комбинацию): {"experiment", "file", "valid": true, "profile_issues": […]} или "valid": false с error и exit_code.

send ​

text
signallab send <osc|udp|http|ws|mqtt> …

Отправляет одно сообщение теми же командами, что и экраны приложения, поэтому на проводе те же байты. Отправка не читает ни библиотеку, ни секреты.

Коды завершения: 0 — отправлено, 1 — отправка не удалась, 2 — неверен аргумент.

<host:port> — это IP-адрес или имя хоста и порт: 127.0.0.1:9000, [::1]:9000 (адрес IPv6 в скобках) или device.local:9000. Имя разрешается при выполнении команды, берётся его адрес IPv4, если он есть, так что localhost:9000 достаёт получателя на 127.0.0.1. Имя, которое не разрешилось, проваливает отправку (1); цель без порта — неверный аргумент (2).

send osc ​

text
signallab send osc <host:port> <address> [ARG]...

Одно OSC-сообщение. Аргументы задаются префиксом типа или определяются сами:

АргументТип OSC
i:3int32
f:0.5float32
d:1.5float64 (double)
h:64int64
s:textстрока
b:de ad be efblob, байты в шестнадцатеричной записи
T, Ftrue, false
Nnil
3, -3простое целое число — int32
2.5простая десятичная дробь — float32
всё остальноестрока
bash
signallab send osc 127.0.0.1:9000 /cue/go f:0.75 s:main 3
# ✔ sent /cue/go (32 bytes) → 127.0.0.1:9000

Аргумент с пробелами берите в кавычки: "s:hello world". s:7 отправляет текст 7. Адрес должен начинаться с /; иначе это неверный аргумент (2).

Git Bash в Windows

Git Bash переписывает аргументы, которые начинаются с /, в пути Windows, поэтому /cue/go приходит как C:/Program Files/Git/cue/go. Пишите //cue/go или запускайте с MSYS_NO_PATHCONV=1. PowerShell и cmd это не затрагивает.

См. OSC.

send udp ​

text
signallab send udp <host:port> (--text TEXT | --hex HEX)

Одна датаграмма UDP. Содержимое задаётся через --text или байтами через --hex: "de ad be ef", deadbeef или 0xDE,0xAD.

bash
signallab send udp 127.0.0.1:7000 --text "PLAY 1"
signallab send udp 127.0.0.1:7000 --hex "de ad be ef"

send http ​

text
signallab send http <METHOD> <URL> [OPTIONS]

Один HTTP-запрос. Строка состояния идёт в stderr — HTTP 200 OK · 3 ms · 1,234 B — а тело ответа в stdout, чтобы его можно было передать дальше по конвейеру. Тело длиннее 256 КиБ там обрезается, и stderr сообщает об этом.

ПараметрЧто делаетПо умолчанию
-H, --header "Name: value"Заголовок запроса; повторите для других.
--body TEXTТело запроса. @FILE отправляет содержимое текстового файла.нет
--expect-status STATUSЗавершиться с кодом 1, если у ответа не этот статус.любой статус — 0
--timeout MSСколько миллисекунд ждать ответ.10000
-u, --user NAME:PASSWORDУчётные данные, отправляются как Basic.
--digestВместе с --user: ответить на Digest-вызов сервера (MD5 или SHA-256).выкл.
--bearer TOKENОтправить Authorization: Bearer TOKEN. Нельзя вместе с --user.
bash
signallab send http GET http://127.0.0.1:8080/health --expect-status 200
signallab send http POST http://127.0.0.1:8080/cue -H "Content-Type: application/json" --body '{"cue": 1}'
signallab send http GET http://127.0.0.1:8080/admin -u admin:secret --digest

Без --expect-status успехом считается любой ответ, включая 500. Запрос, на который нет ответа (отказ в соединении, тайм-аут, имя не разрешилось), — это код завершения 1, как и Digest-вызов, на который не удалось ответить, — причина печатается после ответа.

TIP

Аргументы видны другим пользователям той же машины. Настоящие пароли держите для экспериментов, где они — секреты.

См. HTTP.

send ws ​

text
signallab send ws <URL> [OPTIONS]

Один обмен по WebSocket: подключиться к ws://… или wss://…, отправить сообщение, при желании дождаться ответа, закрыть соединение. Рукопожатие и отправленное идут в stderr, ответ — в stdout (двоичные сообщения — шестнадцатеричными байтами).

ПараметрЧто делаетПо умолчанию
--text TEXTОтправить это текстовое сообщение.ничего не отправляется
--hex HEXОтправить эти байты двоичным сообщением. Нельзя вместе с --text.
-H, --header "Name: value"Заголовок запроса на переключение протокола; повторите для других.
--protocol NAMEПодпротокол, который нужно предложить; повторите для других, в порядке предпочтения.
--expect TEXTЖдать сообщение, содержащее этот текст.
--expect-regex REGEXЖдать сообщение, подходящее под это регулярное выражение.
--waitЖдать любое сообщение.
--timeout MSСколько миллисекунд ждать ответ.2000
bash
signallab send ws ws://127.0.0.1:9001/echo --text '{"ping": 1}' --expect '"ping"'
signallab send ws ws://127.0.0.1:9001/feed --wait        # ничего не отправляется: первое сообщение сервера

Без --expect, --expect-regex и --wait команда подключается, отправляет и закрывает соединение, ничего не ожидая. Если ожидаемый ответ не пришёл вовремя, код завершения — 1. См. WebSocket.

send mqtt ​

text
signallab send mqtt <host:port> <topic> [payload] [--qos 0|1|2] [--retain]

Одна публикация MQTT 3.1.1 по обычному TCP, без учётных данных, от отдельного клиента с новым идентификатором клиента, поэтому она никогда не сбивает уже существующее соединение. Без порта брокер ищется на 1883. Топик — это один топик: если в нём есть + или # либо он пуст, команда отклоняется до подключения (2).

ПараметрЧто делаетПо умолчанию
[payload]Содержимое.пусто
--qos 0|1|2Качество обслуживания.0
--retainСохранить как retained-значение топика. Пустое содержимое с --retain стирает его.выкл.
bash
signallab send mqtt 127.0.0.1:1883 lab/light/1/set on --qos 1
signallab send mqtt 127.0.0.1 lab/light/1/state "" --retain     # стереть retained-значение

См. MQTT.

fire ​

text
signallab fire <signal> [--library PATH]

Отправляет сигнал из библиотеки сигналов ровно так, как это делает экран Сигналы приложения: сигналы OSC, UDP, HTTP и MQTT. Сигнал ищется по id, иначе по имени без учёта регистра; имя, которое носят несколько сигналов, отклоняется с перечислением их id.

ПараметрЧто делаетПо умолчанию
<signal>id или имя сигнала.обязательно
--library PATHФайл библиотеки.signals.json в папке данных приложения
bash
signallab fire "Fader value"
signallab fire go --library show/signals.json

Библиотека только читается, никогда не создаётся и не меняется. См. Сигналы.

emulate ​

text
signallab emulate [OPTIONS] <FILE|NAME>...

Играет другую сторону — HTTP API, OSC-, UDP- или TCP-устройство, MQTT-брокер — до Ctrl+C или --for и печатает каждый запрос по мере ответа на него. FILE содержит один эмулятор, список эмуляторов или целую библиотеку в том виде, в каком её пишет приложение; NAME — id или имя эмулятора из библиотеки приложения (с экрана Эмуляторы).

ПараметрЧто делаетПо умолчанию
-p, --param NAME=VALUEЗначение, которое его шаблоны читают как {{NAME}}; повторите для других.
--bind IP:PORTСлушать там. Только с одним эмулятором.собственный адрес эмулятора
--for SECONDSОстановиться через столько секунд.до Ctrl+C
--seed NSeed его случайных выборов: случайный порядок, разброс, генераторы.
--checkПроверить эмуляторы и выйти, не открывая порт.выкл.
--library PATHБиблиотека, в которой ищутся имена.emulators.json в папке данных приложения
--server URL, --token-file PATHЗапустить их на сервере, следить за ними через его API и остановить в конце.
--secrets, --secrets-dirКак у run.
text
$ signallab emulate tests/orders-api.json --for 60
Orders API (http) answering on 127.0.0.1:18099
answering for 60 s
+   1.209 s Orders API  #1  GET /orders/42 → 200 OK · 12 B  1 ms  ← 127.0.0.1:55744
+   1.209 s Orders API  —  GET /nothing → 404 Not Found · 20 B  2 ms  ← 127.0.0.1:55745
Orders API: 2 requests, 1 without a rule, 0 failed · #1 1

Каждая строка — это время от начала, эмулятор, правило, которое ответило (#1 или —, если никакое), запрос и что он получил, сколько это заняло и кто его отправил. В конце — счётчики каждого эмулятора: запросы, сколько из них не взяло ни одно правило, сколько провалилось, сколько попало под отключение или осталось недоставленным, если такие были, и попадания на каждое правило.

Коды завершения: 0 — остановка по Ctrl+C или --for; 2 — эмулятор недопустим; 3 — его порт занят или не открывается либо сокет отказывает во время ответов.

В конвейере запустите его в фоне, проверьте на нём систему и прочитайте счётчики в конце:

bash
signallab emulate tests/payments-mock.json --for 300 --json > mock.ndjson &
npm test          # тестируемая система, настроенная на адрес эмулятора
wait              # последние строки mock.ndjson — счётчики

На сервере эмулятор, запущенный с --server, останавливается, когда signallab завершается нормально; тот, что остался после убитого процесса, можно остановить из интерфейса сервера. См. Эмуляторы.

emulators ​

text
signallab emulators [--library PATH]

Выводит список эмуляторов библиотеки: id, имя, протокол, адрес и число правил. --library PATH читает другой файл библиотеки вместо emulators.json в папке данных приложения. signallab emulate <id> запускает один из них.

Библиотека только читается. Если такого файла нет — приложение создаёт файл в своей папке данных при первом запуске, — команда сообщает об этом и завершается с кодом 2.

templates ​

text
signallab templates

Выводит список встроенных шаблонов, которые run и validate принимают по имени. Это собственные шаблоны приложения:

ИмяВ приложенииПараметры
emptyПустая схема
http-checkПроверка HTTP
status-branchHTTP → OSC
parallel-flowsПараллельные потоки
osc-ping-replyOSC ping → ответdevice = 127.0.0.1:9000
poll-until-readyОпрос до готовностиdevice = 127.0.0.1:9000
flaky-apiПовтор ненадёжного APIapi = http://127.0.0.1:18080
fault-phasesФазы сбоев
dependency-outageОтказ зависимостиapi = http://127.0.0.1:18090
websocket-echoЭхо WebSocketservice = ws://127.0.0.1:9001/echo

Каждый шаблон указывает на loopback. flaky-api, fault-phases и dependency-outage приносят собственные эмуляторы, поэтому запускаются, когда больше ничего не слушает, — быстрый способ посмотреть, как работает signallab.

nodes ​

text
signallab nodes

Печатает в виде JSON то, из чего состоит эксперимент: форму и правила документа, каждый вид узла с его названием, описанием, полями, выходами и примером, который принимает движок, язык {{template}}, профили нагрузки и документ эмулятора. Это то, что ассистент читает через signallab mcp, чтобы написать эксперимент; для людей то же самое более подробно изложено на странице Узлы.

mcp ​

text
signallab mcp [OPTIONS]

Предоставляет Signal Lab ИИ-ассистенту по Model Context Protocol через stdin и stdout. Всё — настройка в Claude Code, Claude Desktop, Cursor или VS Code, параметры и инструменты — изложено на странице Ассистенты (MCP).

doctor ​

text
signallab doctor [--server URL] [--token-file PATH]

Говорит, что может стоять между Signal Lab и оборудованием, и завершается с кодом 1, если что-то стоит. Его строки следуют --lang так же, как остальная командная строка:

  • сеть, в которой находится эта машина: её имя и адрес;
  • папка данных: можно ли в неё писать (ещё не созданная — не помеха: приложение создаёт её при первом использовании);
  • брандмауэр: в Windows — для signallab и настольного приложения по отдельности — есть ли правило, пускающее другие машины в сеть того типа, в которой машина находится сейчас (частная, доменная или общедоступная), или правило их блокирует — то, что оставляет после себя Отмена в системном запросе; в Linux — включён ли ufw или firewalld и какая команда открывает порт;
  • с --server (или SIGNALLAB_SERVER): отвечает ли сервер и принимает ли он токен.
text
signallab 1.0.0
Network: LAB-PC · 192.0.2.15
Data folder: C:\Users\lab\Documents\SignalLab — writable
Firewall · signallab (C:\…\Signal Lab\signallab.exe) · private network: not allowed yet — signallab firewall allow
Firewall · app (C:\…\Signal Lab\signal-lab.exe) · private network: allowed
✖ 1 thing in the way

--json печатает то же самое одним объектом. См. Устранение неполадок.

firewall ​

text
signallab firewall allow [--public]

В Windows разрешает другим машинам достучаться до Signal Lab — то, что нужно монитору или ожиданию, чтобы услышать устройство. Windows сначала запрашивает права администратора; затем входящие правила signallab и настольного приложения (оно находится рядом или там, куда его кладут установщики) заменяются одним разрешающим правилом на каждую программу — блокирующие правила тоже — для частных и доменных сетей.

ПараметрЧто делает
--publicЕщё и в общедоступных сетях — Wi-Fi площадки часто именно такая.

Коды завершения: 0 — готово; 3 — запрос администратора отклонён или изменение не удалось. В Linux ничего не меняется: команда печатает команду ufw или firewalld, которая открывает порты, которые вы слушаете, и завершается с кодом 0.

Брандмауэр меняется только тогда, когда вы запускаете эту команду; ничто другое в signallab его не трогает.

version ​

text
signallab version

Печатает signallab 1.0.0 — с --json, {"version": "1.0.0"}. signallab --version печатает ту же версию.