Командная строка: signallab
signallab — это Signal Lab без окна. Он доводит эксперименты до конца и завершается кодом, который понимает скрипт, отправляет одно OSC-сообщение, датаграмму, HTTP-запрос, сообщение WebSocket или публикацию MQTT, отправляет сигнал из вашей библиотеки, играет эмулятор, пока вы его не остановите, и говорит, что стоит между этой машиной и оборудованием.
Это тот же движок, что в приложении: запуск из командной строки делает те же шаги, пишет тот же отчёт и говорит то же самое — на языках интерфейса. С --server запуски выполняются на сервере Signal Lab: с его сетью и его секретами.
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). |
Проверьте так:
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 | Проверяет брандмауэр, сеть, папку данных и сервер. |
firewall | firewall 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 используют собственные тексты интерфейса, его формы множественного числа и стиль чисел. Язык определяется по первому из пунктов:
--lang;SIGNALLAB_LANG(ru,ru-RUиru_RU.UTF-8— всё это русский);- локаль: первая заданная из
LC_ALL,LC_MESSAGESиLANG; - английский.
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
signallab run [OPTIONS] <FILE>...Запускает эксперименты один за другим и завершается с кодом 0, только если все прошли.
| Параметр | Что делает | По умолчанию |
|---|---|---|
<FILE>... | Файлы экспериментов или имена встроенных шаблонов. | обязательно |
-p, --param NAME=VALUE | Значение параметра для этого запуска; повторите для других. | значения из документа |
--profile NAME | Запустить с этим профилем; он должен быть в каждом из заданных экспериментов. "" запускает со значениями по умолчанию. | профиль из документа |
-m, --matrix NAME=V1,V2 | Запустить по разу на каждое значение; повторите для других имён (см. Матрица запусков). | |
--matrix-file PATH | Комбинации из файла JSON. | |
--seed N | Seed случайных значений, от 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 или без:
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.
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 запусков из одной команды; больше отклоняется до того, как что-либо запустится.
Запуск на сервере
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не начал.
<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 КиБ.
SIGNALLAB_SECRET_API_TOKEN="$API_TOKEN" signallab run tests/api.jsonСекрет, который не задан, останавливает запуск до любого трафика, с кодом завершения 2 и именем недостающего секрета. Значение никогда не печатается: шаги, ошибки, отчёты и отчёт JUnit показывают на его месте ••••. С --server секреты — это секреты сервера.
Что печатает run
По ходу запуска каждый шаг — строка в stderr: время от начала, узел, его состояние и что он сделал — как в ленте приложения. Когда запуск заканчивается, одна строка в stdout сообщает, как он прошёл:
▶ 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 идёт то, о чём спрашивали каждый эмулятор запуска, — запросы, сколько из них не взяло ни одно правило, сколько провалилось и сколько попаданий на каждое правило:
✔ Retry a flaky API passed in 7 ms
Flaky API: 3 requests, 0 without a rule, 0 failed · #1 3и что сделало каждое реле помех: что получило, отбросило и ограничило, а каждая фаза — сколько переслано / получено:
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 двигает фрагменты потоков, а не датаграммы, и ничего не отбрасывает, поэтому его строка считает фрагменты, соединения, сбросы, полуоткрытые соединения и сколько раз поток был придержан ограничением полосы:
127.0.0.1:19120 → 127.0.0.1:19101: 14 chunks, 2 connections, 1 reset, 0 half-open, 3 held backHTTP-узел под нагрузкой сообщает о ходе работы шагом не чаще раза в секунду.
Если запусков несколько, вывод заканчивается строкой на каждый запуск и итогом: 3 runs: 2 passed, 1 failed. С --fail-fast незапущенные запуски подсчитываются в stderr.
С --json каждая строка — объект с полем type:
{"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
signallab validate [OPTIONS] <FILE>...Проверяет эксперименты так, как это делает редактор перед запуском, — граф, каждое поле, шаблоны, параметры и секреты, — и ничего не отправляет. Завершается с кодом 0, если запустился бы каждый.
Принимает те же входные данные, что и run: файлы и шаблоны, --param, --profile, --matrix, --matrix-file, а также --server, --token-file, --secrets, --secrets-dir. С --server их проверяет сервер, по своим секретам.
✔ tests/stage.json: Stage cues would run
Rehearsal: Would not run: …Проблема, которая есть только у другого профиля документа, перечисляется под ним, но проверку не проваливает. С --json — по строке на эксперимент (на комбинацию): {"experiment", "file", "valid": true, "profile_issues": […]} или "valid": false с error и exit_code.
send
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
signallab send osc <host:port> <address> [ARG]...Одно OSC-сообщение. Аргументы задаются префиксом типа или определяются сами:
| Аргумент | Тип OSC |
|---|---|
i:3 | int32 |
f:0.5 | float32 |
d:1.5 | float64 (double) |
h:64 | int64 |
s:text | строка |
b:de ad be ef | blob, байты в шестнадцатеричной записи |
T, F | true, false |
N | nil |
3, -3 | простое целое число — int32 |
2.5 | простая десятичная дробь — float32 |
| всё остальное | строка |
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
signallab send udp <host:port> (--text TEXT | --hex HEX)Одна датаграмма UDP. Содержимое задаётся через --text или байтами через --hex: "de ad be ef", deadbeef или 0xDE,0xAD.
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
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. |
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
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 |
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
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 стирает его. | выкл. |
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
signallab fire <signal> [--library PATH]Отправляет сигнал из библиотеки сигналов ровно так, как это делает экран Сигналы приложения: сигналы OSC, UDP, HTTP и MQTT. Сигнал ищется по id, иначе по имени без учёта регистра; имя, которое носят несколько сигналов, отклоняется с перечислением их id.
| Параметр | Что делает | По умолчанию |
|---|---|---|
<signal> | id или имя сигнала. | обязательно |
--library PATH | Файл библиотеки. | signals.json в папке данных приложения |
signallab fire "Fader value"
signallab fire go --library show/signals.jsonБиблиотека только читается, никогда не создаётся и не меняется. См. Сигналы.
emulate
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 N | Seed его случайных выборов: случайный порядок, разброс, генераторы. | |
--check | Проверить эмуляторы и выйти, не открывая порт. | выкл. |
--library PATH | Библиотека, в которой ищутся имена. | emulators.json в папке данных приложения |
--server URL, --token-file PATH | Запустить их на сервере, следить за ними через его API и остановить в конце. | |
--secrets, --secrets-dir | Как у run. |
$ 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 — его порт занят или не открывается либо сокет отказывает во время ответов.
В конвейере запустите его в фоне, проверьте на нём систему и прочитайте счётчики в конце:
signallab emulate tests/payments-mock.json --for 300 --json > mock.ndjson &
npm test # тестируемая система, настроенная на адрес эмулятора
wait # последние строки mock.ndjson — счётчикиНа сервере эмулятор, запущенный с --server, останавливается, когда signallab завершается нормально; тот, что остался после убитого процесса, можно остановить из интерфейса сервера. См. Эмуляторы.
emulators
signallab emulators [--library PATH]Выводит список эмуляторов библиотеки: id, имя, протокол, адрес и число правил. --library PATH читает другой файл библиотеки вместо emulators.json в папке данных приложения. signallab emulate <id> запускает один из них.
Библиотека только читается. Если такого файла нет — приложение создаёт файл в своей папке данных при первом запуске, — команда сообщает об этом и завершается с кодом 2.
templates
signallab templatesВыводит список встроенных шаблонов, которые run и validate принимают по имени. Это собственные шаблоны приложения:
| Имя | В приложении | Параметры |
|---|---|---|
empty | Пустая схема | |
http-check | Проверка HTTP | |
status-branch | HTTP → OSC | |
parallel-flows | Параллельные потоки | |
osc-ping-reply | OSC ping → ответ | device = 127.0.0.1:9000 |
poll-until-ready | Опрос до готовности | device = 127.0.0.1:9000 |
flaky-api | Повтор ненадёжного API | api = http://127.0.0.1:18080 |
fault-phases | Фазы сбоев | |
dependency-outage | Отказ зависимости | api = http://127.0.0.1:18090 |
websocket-echo | Эхо WebSocket | service = ws://127.0.0.1:9001/echo |
Каждый шаблон указывает на loopback. flaky-api, fault-phases и dependency-outage приносят собственные эмуляторы, поэтому запускаются, когда больше ничего не слушает, — быстрый способ посмотреть, как работает signallab.
nodes
signallab nodesПечатает в виде JSON то, из чего состоит эксперимент: форму и правила документа, каждый вид узла с его названием, описанием, полями, выходами и примером, который принимает движок, язык {{template}}, профили нагрузки и документ эмулятора. Это то, что ассистент читает через signallab mcp, чтобы написать эксперимент; для людей то же самое более подробно изложено на странице Узлы.
mcp
signallab mcp [OPTIONS]Предоставляет Signal Lab ИИ-ассистенту по Model Context Protocol через stdin и stdout. Всё — настройка в Claude Code, Claude Desktop, Cursor или VS Code, параметры и инструменты — изложено на странице Ассистенты (MCP).
doctor
signallab doctor [--server URL] [--token-file PATH]Говорит, что может стоять между Signal Lab и оборудованием, и завершается с кодом 1, если что-то стоит. Его строки следуют --lang так же, как остальная командная строка:
- сеть, в которой находится эта машина: её имя и адрес;
- папка данных: можно ли в неё писать (ещё не созданная — не помеха: приложение создаёт её при первом использовании);
- брандмауэр: в Windows — для
signallabи настольного приложения по отдельности — есть ли правило, пускающее другие машины в сеть того типа, в которой машина находится сейчас (частная, доменная или общедоступная), или правило их блокирует — то, что оставляет после себя Отмена в системном запросе; в Linux — включён ли ufw или firewalld и какая команда открывает порт; - с
--server(илиSIGNALLAB_SERVER): отвечает ли сервер и принимает ли он токен.
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
signallab firewall allow [--public]В Windows разрешает другим машинам достучаться до Signal Lab — то, что нужно монитору или ожиданию, чтобы услышать устройство. Windows сначала запрашивает права администратора; затем входящие правила signallab и настольного приложения (оно находится рядом или там, куда его кладут установщики) заменяются одним разрешающим правилом на каждую программу — блокирующие правила тоже — для частных и доменных сетей.
| Параметр | Что делает |
|---|---|
--public | Ещё и в общедоступных сетях — Wi-Fi площадки часто именно такая. |
Коды завершения: 0 — готово; 3 — запрос администратора отклонён или изменение не удалось. В Linux ничего не меняется: команда печатает команду ufw или firewalld, которая открывает порты, которые вы слушаете, и завершается с кодом 0.
Брандмауэр меняется только тогда, когда вы запускаете эту команду; ничто другое в signallab его не трогает.
version
signallab versionПечатает signallab 1.0.0 — с --json, {"version": "1.0.0"}. signallab --version печатает ту же версию.