CLI-клиент
Notifly-CLI — это маленькая консольная утилита notifly для отправки
сообщений в ваш канал прямо из терминала, cron-задач и shell-скриптов.
Она хранит токен и адрес сервера в конфиге, умеет читать сообщение из
stdin и отслеживать изменение вывода произвольной команды (watch).
Утилита не обязательна для отправки уведомлений — то же самое можно
сделать через curl (см. REST API). CLI просто избавляет
от повторения токена и URL в каждой команде.
Установка
Заголовок раздела «Установка»Готовых сборок CLI для скачивания пока нет: утилита собирается из исходников —
каталога cli/ репозитория Notifly (по вопросам доступа к исходникам пишите на
support@notifly.ru). Нужен Go 1.27+ и рядом —
каталог sdk/go того же репозитория: CLI использует Go SDK из рабочего дерева.
cd cligo build -o notifly cli.go./notifly versionmake build соберёт сразу набор бинарников в подкаталог build/ — под Linux
(amd64, 386, arm64, armv7), macOS (amd64, arm64) и Windows (amd64, 386); файлы
называются по-старому, gotify-cli-<ОС>-<архитектура> — наследство форка.
При желании положите бинарник в каталог из $PATH:
sudo mv notifly /usr/local/bin/notiflyКоманды
Заголовок раздела «Команды»notifly init # мастер настройки (запишет конфиг)notifly version # показать версию (алиас: v)notifly config # показать текущий конфигnotifly push # отправить сообщение (алиас: p)notifly watch # следить за выводом команды и слать измененияnotifly create-app # создать канал (нужен API-токен)notifly list # последние сообщения (алиас: ls; нужен API-токен)notifly ask # задать вопрос и, если нужно, дождаться ответаnotifly help # помощь по командам (алиас: h)Помощь по конкретной команде: notifly help push, notifly help watch.
Настройка: notifly init
Заголовок раздела «Настройка: notifly init»Самый простой способ начать — мастер init. Он спросит адрес сервера,
токен и приоритет по умолчанию, проверит соединение и запишет конфиг.
$ notifly initNotifly URL: https://api.notifly.ruNotifly v2.7.4@2025-09-25-16:27:04
Configure an application token1. Enter an application-token2. Create an application token (with user/pass)Enter 1 or 2: 2
Sign in (credentials are used now and not saved; only the issued tokens are)Email: me@example.comPassword:Signing in -> Success!
Application name: deploy-botApplication description (can be empty): CI notificationsCreating -> Success!
Default Priority [0-10]: 6
API token for the account-level commands (create-app, list)1. Enter an API token (issued on the "API tokens" page of the admin UI)2. Issue a new API token (with user/pass)Press Enter to skip — pushing works without one.Enter 1, 2 or nothing: 2
API token name [notifly-cli (myhost)]:Issuing API token -> Success!Issued API token "notifly-cli (myhost)" (M…d8Fs); manage it on the "API tokens" page of the admin UI.
Written config to: /home/user/.config/notifly/cli.jsonНа шаге App-токена два варианта:
- 1 — ввести готовый App-токен. Возьмите его из админки; утилита тут же проверит его, отправив тестовое сообщение в канал.
- 2 — создать App-токен по логину/паролю. Вы вводите email и пароль, CLI
входит в аккаунт как временное устройство
notifly-cli setup (имя машины), создаёт канал с указанными именем и описанием и сохраняет его токен. Если в аккаунте включена 2FA, мастер спросит код из приложения-аутентификатора или recovery-код; при подключённом методе «Notifly mobile» можно подтвердить вход в приложении и просто нажать Enter. Логин и пароль не сохраняются — только итоговый токен.
Приоритет по умолчанию должен быть числом от 0 до 10.
Последний шаг — API-токен для команд create-app и
list. Enter пропускает его: отправка работает и без API-токена.
- 1 — вставить готовый API-токен со страницы API-токены в админке; мастер проверит его одним запросом на чтение.
- 2 — выпустить новый API-токен по логину/паролю. Тот же вход, что и для
App-токена: если вы уже входили на предыдущем шаге, пароль второй раз не
спрашивается. Токен выпускается с правом
write, без ограничения по каналам и без срока действия, с именемnotifly-cli (имя машины); сузить скоуп или поставить срок можно потом на странице API-токены.
Временное устройство мастер удаляет перед записью конфига: ни слот в лимите
устройств, ни токен устройства после него не остаются. Как любой вход по
паролю, он шлёт владельцу письмо «новый вход», а на заполненном лимите
устройств на время усыпляет самое старое из них (оно проснётся при следующем
обращении). Если мастер прерван до конца, устройство notifly-cli setup (…)
останется на странице Устройства — удалите его вручную.
Файл конфига мастер создаёт с правами 0600: в нём лежат живые токены.
Где хранится конфиг
Заголовок раздела «Где хранится конфиг»init предложит выбрать путь, а остальные команды ищут конфиг в этих
местах (первый найденный — побеждает):
./cli.json(рядом с текущим каталогом);$XDG_CONFIG_HOME/notifly/cli.json(обычно~/.config/notifly/cli.json);~/.notifly/cli.json;/etc/notifly/cli.json(кроме Windows).
Следом, если ничего не нашлось, просматриваются те же пути с gotify вместо
notifly — наследство форка, чтобы старый конфиг продолжал работать.
Конфиг вручную
Заголовок раздела «Конфиг вручную»Конфиг — это обычный JSON. Можно создать его руками, не запуская мастер:
{ "token": "AbC3dEf5gHi7jKl9mNo1pQr", "url": "https://api.notifly.ru", "defaultPriority": 6, "apiToken": "Mx7Kp2Lq9Wz4Rt6Yb1Nd8Fs"}| Поле | Описание | Пример |
|---|---|---|
token | App-токен (API-токен и токен устройства для отправки не подойдут) | AbC3dEf5gHi7jKl9mNo1pQr |
url | Адрес API Notifly | https://api.notifly.ru |
defaultPriority | Приоритет по умолчанию (0, если не задан) | 6 |
apiToken | (необязательно) API-токен для команд create-app и list | Mx7Kp2Lq9Wz4Rt6Yb1Nd8Fs |
Команды уровня аккаунта: create-app и list
Заголовок раздела «Команды уровня аккаунта: create-app и list»Кроме отправки CLI умеет две операции над аккаунтом — завести канал и прочитать
последние сообщения. Им нужен не app-токен, а
API-токен (M…): его выпускают в админке на странице
API-токены или прямо в мастере notifly init по логину/паролю, а CLI
берёт его из поля apiToken, флага --apiToken или переменной окружения
NOTIFLY_API_TOKEN.
$ export NOTIFLY_API_TOKEN=Mx7Kp2Lq9Wz4Rt6Yb1Nd8Fs
$ notifly create-app -n "deploy-bot" -d "Уведомления CI"Channel createdID: 42Name: deploy-botApp-Token: AbC3dEf5gHi7jKl9mNo1pQr
$ notifly list -n 10create-app печатает app-токен нового канала — его и кладут в token, чтобы
дальше слать в этот канал через notifly push. Канал, созданный API-токеном с
ограниченным скоупом, автоматически попадает в его скоуп.
notifly init предлагает API-токен на отдельном шаге — вставить готовый или
выпустить новый по логину/паролю (см. Настройка);
пропустите его клавишей Enter, если аккаунтные команды не нужны.
Посмотреть, какой конфиг используется сейчас:
$ notifly configUsed Config: /home/user/.config/notifly/cli.jsonURL: https://api.notifly.ruDefault Priority: 6Token: AbC3dEf5gHi7jKl9mNo1pQrAPI Token: set (M…d8Fs)Вопрос человеку: notifly ask
Заголовок раздела «Вопрос человеку: notifly ask»notifly ask задаёт вопрос через канал — уведомление приходит с кнопками
ответа, а CLI может дождаться нажатия. Это готовый approval-гейт для скрипта
развёртывания: подробнее о самой механике — на странице
Вопросы (Ask). Нужен app-токен канала, тот же, что у push.
$ notifly ask -o yes,no --wait "Выкатывать в прод?"question created, id: 8260183728527568 — waiting for the answer (Ctrl+C to stop)...answer: yesФлаги идут до текста вопроса: всё, что стоит после него, считается частью вопроса.
| Флаг | Назначение | По умолчанию |
|---|---|---|
-o, --options | Варианты ответа через запятую; без них ответ свободным текстом | — |
--timeout | Через сколько секунд вопрос истечёт | без срока |
--default-answer | Ответ, засчитываемый по истечении (нужен --timeout) | — |
-t, --title | Заголовок уведомления | имя канала |
-w, --wait | Ждать ответа, а не печатать только id | выкл. |
--poll | Интервал фолбэка при ожидании, в секундах | 3 |
-q, --quiet | Печатать только сам ответ — удобно для $(...) | выкл. |
--token, --url | Переопределить app-токен и адрес (env: NOTIFLY_TOKEN) | из конфига |
С --wait ответ приходит push-ом по WebSocket, поэтому команда завершается в
тот же момент, когда человек нажал кнопку. Если сокет недоступен, CLI
переходит на опрос раз в --poll секунд. Ctrl+C прекращает ожидание, сам
вопрос остаётся неотвеченным.
Коды выхода делают команду пригодной для if: 0 — ответ получен, 1 —
вопрос истёк, отменён или ожидание прервано.
if answer=$(notifly ask -q -o yes,no --wait "Выкатывать в прод?") && [ "$answer" = yes ]; then ./deploy.shfiОтправка сообщений: notifly push
Заголовок раздела «Отправка сообщений: notifly push»Текст сообщения передаётся аргументом или через stdin:
notifly push my messagenotifly push "моё сообщение"echo "моё сообщение" | notifly pushnotifly push < somefileЗаголовок и приоритет:
notifly push -t "Деплой" -p 10 "Прод выкатился"Флаги команды push:
| Флаг | Назначение | По умолчанию |
|---|---|---|
-p, --priority | Приоритет сообщения | из defaultPriority |
-t, --title | Заголовок (если пусто — берётся имя приложения) | имя приложения |
--token | Переопределить App-токен (env: NOTIFLY_TOKEN, GOTIFY_TOKEN) | из конфига |
--url | Переопределить адрес сервера | из конфига |
-q, --quiet | Ничего не печатать при успехе | выкл. |
--contentType | Content-type сообщения, например text/markdown (см. msgextras) | — |
--clickUrl | URL, открываемый по тапу на уведомление (см. msgextras) | — |
--bigImageUrl | URL картинки, показываемой в уведомлении (см. msgextras) | — |
--disable-unescape-backslash | Не раскрывать \n и \t (оставить как обычный текст) | раскрывает |
Если -p не указан, берётся defaultPriority из конфига; если нет и его,
приоритет не передаётся вовсе и сервер берёт умолчание канала.
Переопределение токена и URL
Заголовок раздела «Переопределение токена и URL»Не обязательно держать конфиг — можно передать токен и адрес прямо в команде
или через переменную окружения NOTIFLY_TOKEN (старое имя GOTIFY_TOKEN
тоже принимается):
notifly push --url https://api.notifly.ru --token AbC3dEf5gHi7jKl9mNo1pQr "без конфига"
NOTIFLY_TOKEN=AbC3dEf5gHi7jKl9mNo1pQr notifly push --url https://api.notifly.ru "из env"Markdown и переносы строк
Заголовок раздела «Markdown и переносы строк»По умолчанию notifly раскрывает \n и \t в реальные перенос строки и
табуляцию. Это удобно для многострочных сообщений из одной строки аргумента:
notifly push -t "Отчёт" "Строка 1\nСтрока 2\tс табом"Чтобы оставить \n и \t как буквальный текст — добавьте
--disable-unescape-backslash.
Markdown включается через --contentType:
notifly push --contentType text/markdown -t "Релиз" "**v2.0** готов — [changelog](https://notifly.ru)"Кликабельные уведомления и картинки
Заголовок раздела «Кликабельные уведомления и картинки»notifly push -t "Сборка упала" \ --clickUrl https://ci.example.com/build/42 \ --bigImageUrl https://ci.example.com/build/42/graph.png \ "Джоба #42 завершилась с ошибкой"Подробнее про эти поля — на странице Доп. поля сообщений.
Слежение за командой: notifly watch
Заголовок раздела «Слежение за командой: notifly watch»watch периодически выполняет заданную команду и, как только её вывод
изменился по сравнению с прошлым запуском, отправляет новый вывод в канал.
Удобно для самодельного мониторинга «на коленке» без отдельного сервиса.
notifly watch "curl -s https://api.example.com/status | jq '.state'"По умолчанию команда запускается каждые 2 секунды через sh -c. Заголовком,
если он не задан, становится сама команда.
Флаги команды watch:
| Флаг | Назначение | По умолчанию |
|---|---|---|
-n, --interval | Интервал опроса в секундах (дробное допустимо) | 2 |
-p, --priority | Приоритет | из defaultPriority |
-x, --exec | Чем исполнять команду | sh -c |
-t, --title | Заголовок (если пусто — текст команды) | команда |
--token | Переопределить App-токен (env: NOTIFLY_TOKEN) | из конфига |
--url | Переопределить адрес сервера | из конфига |
-o, --output | Подробность тела сообщения: short, default, long | default |
Режимы --output:
short— только новый вывод, без обёрток;default— новый вывод в блоке== BEGIN NEW OUTPUT == … == END NEW OUTPUT ==;long— и старый, и новый вывод (полный diff в блоках OLD/NEW).
Пример: следить каждые 30 секунд за числом контейнеров и слать длинный diff:
notifly watch -n 30 -o long -t "docker ps" "docker ps -q | wc -l"TLS и самоподписанные сертификаты
Заголовок раздела «TLS и самоподписанные сертификаты»Если сервер за самоподписанным сертификатом, есть переменные окружения:
# полностью отключить проверку TLS (небезопасно)export NOTIFLY_SKIP_VERIFY_TLS=True
# или указать собственный корневой CA / закреплённый сертификатexport SSL_CERT_FILE=/path/to/cert.pemАльтернатива без CLI: curl
Заголовок раздела «Альтернатива без CLI: curl»Любую отправку из CLI можно повторить обычным curl — это тот же REST API:
curl -X POST "https://api.notifly.ru/message" \ -H "X-Notifly-Key: AbC3dEf5gHi7jKl9mNo1pQr" \ -H "Content-Type: application/json" \ -d '{"title": "Деплой", "priority": 10, "message": "Прод выкатился"}'REST API
Заголовок раздела «REST API»CLI работает поверх того же публичного API, что и всё остальное.
Авторизация — заголовком X-Notifly-Key с App-токеном (A…).
| Метод | Путь | Назначение | Токен |
|---|---|---|---|
POST | /message | Отправить сообщение в канал | App-токен |
GET | /version | Версия сервера (используется мастером init) | — |
Тело POST /message (JSON): message (обязателен), title,
priority (0–10), extras (например client::display.contentType,
client::notification.click.url, client::notification.bigImageUrl).
Подробности — на страницах Отправка сообщений и
Доп. поля сообщений.