Nonstop Notify quangnv13
winget install --id=quangnv13.nonstop-notify -e A lightweight desktop notification
winget install --id=quangnv13.nonstop-notify -e A lightweight desktop notification
Nonstop Notify is a lightweight desktop notification bridge for scripts, automation, CI jobs, background services, and local developer tools. Send one JSON event through the CLI and it turns into a focused desktop toast.
It was originally built for the Nonstop test platform, but the event format and CLI are suitable for any workflow that needs visible desktop feedback.
toastId is reused.notify-ring.mp3 override beside the executable.No configuration is required for a first notification. Verify the executable, then send an event:
.\nonstop-notify.exe --self-check
Send an event from PowerShell:
'{"event":"deploy.started","toastId":"deploy:api","title":"Deploying API","message":"Publishing to staging","status":"loading","progress":0.35}' |
.\nonstop-notify.exe emit --stdin
Update the same toast when the work finishes:
'{"event":"deploy.completed","toastId":"deploy:api","title":"Deployment complete","message":"Staging is ready","status":"success","progress":1,"primaryLabel":"View deployment","primaryRoute":"https://example.com/deployments/42"}' |
.\nonstop-notify.exe emit --stdin
The daemon starts automatically. Running it explicitly is optional:
.\nonstop-notify.exe daemon
After installing the DEB package or placing the AppImage binary on PATH, verify it, then send an event from Bash:
nonstop-notify --self-check
printf '%s\n' '{"event":"deploy.started","toastId":"deploy:api","title":"Deploying API","message":"Publishing to staging","status":"loading","progress":0.35}' |
nonstop-notify emit --stdin
Update the same toast:
printf '%s\n' '{"event":"deploy.completed","toastId":"deploy:api","title":"Deployment complete","message":"Staging is ready","status":"success","progress":1,"primaryLabel":"View deployment","primaryRoute":"https://example.com/deployments/42"}' |
nonstop-notify emit --stdin
The daemon also starts automatically on Linux. Running it explicitly is optional:
nonstop-notify daemon
nonstop-notify emit --stdin [--config PATH]
nonstop-notify emit --json JSON [--config PATH]
nonstop-notify daemon [--config PATH]
nonstop-notify --self-check [--config PATH]
nonstop-notify config show [--config PATH]
nonstop-notify config set [--config PATH]
nonstop-notify status
nonstop-notify log
nonstop-notify start [--config PATH]
nonstop-notify stop
| Command | Purpose |
|---|---|
emit --stdin | Reads one JSON event from standard input. |
emit --json | Reads one JSON event from the next command argument. |
daemon | Starts the background notification process. |
--self-check | Validates configuration, event parsing, sound decoding, and URL handling. |
config show | Prints effective JSON config and selected config path. Does not create a file. |
config set | Validates and atomically writes one config value; restarts a healthy daemon. |
status | Prints running, stopped, or stale-heartbeat unresponsive JSON. |
log | Prints raw JSONL content from the newest log file. |
start | Starts a healthy daemon or returns its existing PID. |
stop | Sends graceful stop control; already-stopped daemon is success. |
Set NONSTOP_NOTIFY_DEBUG=1 to print CLI errors. Set NONSTOP_NOTIFY_CONFIG to provide a default configuration file without passing --config each time.
Minimal event:
{
"event": "job.completed",
"title": "Job completed",
"status": "success"
}
Full example:
{
"schemaVersion": 1,
"event": "backup.progress",
"toastId": "backup:nightly",
"groupId": "maintenance",
"timestamp": "2026-07-26T12:00:00Z",
"title": "Nightly backup",
"message": "Uploading archive 7 of 10",
"status": "loading",
"progress": 0.7,
"route": "https://example.com/backups/nightly",
"actions": [
{
"label": "Open logs",
"route": "https://example.com/backups/nightly/logs",
"kind": "primary"
}
]
}
| Field | Description |
|---|---|
event | Required event name. Also used as the title when title is empty. |
toastId | Stable identifier used to update an existing toast. Generated when omitted. |
title | Notification heading. |
message | Optional supporting text. |
status | loading, success, error, warning, or another informational value. state is accepted as an alias. |
progress | Optional number clamped to the 0 to 1 range. |
route | Fallback URL for the primary Open action when no explicit action route is supplied. |
actions | Optional action buttons with label, route, and kind. |
primaryLabel / primaryRoute | Flat-field alternative for a primary action. |
secondaryLabel / secondaryRoute | Flat-field alternative for a secondary action. |
Relative routes beginning with / open against the default local Nonstop dashboard at http://127.0.0.1:4137. General integrations should use absolute http:// or https:// URLs. Empty, protocol-relative, javascript:, and file: routes are rejected.
Configuration precedence is --config PATH, NONSTOP_NOTIFY_CONFIG, the per-user config file, then built-in defaults. config show reports effective values and does not create the default file.
Default config paths:
%LOCALAPPDATA%\Nonstop Notify\config.json$XDG_CONFIG_HOME/nonstop-notify/config.json, falling back to ~/.config/nonstop-notify/config.jsonThose paths are only fallbacks. A config file can live anywhere: pass its path with --config PATH, or set NONSTOP_NOTIFY_CONFIG to that path. --config wins over the environment variable and per-user default.
.\nonstop-notify.exe config set position bottom-right --config D:\tools\nonstop-notify\config.json
.\nonstop-notify.exe emit --stdin --config D:\tools\nonstop-notify\config.json
Default config sample. Copy this structure into config.json when creating a per-user config:
{
"position": "bottom-left",
"offsetLeft": 30,
"offsetRight": 30,
"borderWidth": 1,
"soundPath": null,
"logRotationHours": 24,
"logRetentionDays": 7
}
Supported positions: top-left, top-right, bottom-left, and bottom-right.
config set supports position, offsetLeft, offsetRight, borderWidth, soundPath, logRotationHours, and logRetentionDays. Use soundPath none to write null.
soundPath is optional and takes precedence when set. When omitted or null, the daemon first checks for a decodable notify-ring.mp3 beside the executable. If that runtime override is missing or invalid, Windows uses the native system notification sound and other platforms play a short deterministic WAV generated during the Rust build.
--self-check fails when an explicit soundPath cannot be read or decoded. A missing or invalid adjacent notify-ring.mp3 falls back to the default sound without discarding notifications; set NONSTOP_NOTIFY_DEBUG=1 to log the fallback.
Management examples:
.\nonstop-notify.exe config show
.\nonstop-notify.exe config set position bottom-right
.\nonstop-notify.exe config set soundPath none
.\nonstop-notify.exe start
.\nonstop-notify.exe status
.\nonstop-notify.exe log
.\nonstop-notify.exe stop
config set validates values and atomically writes config.json. A healthy running daemon receives graceful stop, then starts with new config; a stopped daemon only saves the file. An unresponsive daemon is not force-killed. If restart fails after saving, the command exits 1 and returns configSaved: true on stderr.
Management errors are JSON on stderr with exit code 1. emit stays silent unless NONSTOP_NOTIFY_DEBUG is set.
Runtime state is stored in runtime.json beside the config. JSONL logs are stored in logs/current.log; files rotate after logRotationHours (default 24) and files whose modified time is at least logRetentionDays old (default 7 days) are removed. Logs contain lifecycle and event metadata only; notification title, message, route, actions, and payload JSON are never written.
.\nonstop-notify.exe emit --stdin --config .\nonstop-notify.config.json
Tagged GitHub releases are built for:
Install with WinGet after the package is published:
winget install --id quangnv13.nonstop-notify --exact
WinGet installs the portable executable and registers the nonstop-notify command. This release does not mutate User PATH. Close existing terminal windows, open a new terminal, then verify the CLI:
nonstop-notify --self-check
You can also download the Windows .exe directly from a GitHub release and run it without an installer. To remove the WinGet package:
winget uninstall --id quangnv13.nonstop-notify --exact
The DEB package installs nonstop-notify in /usr/bin, so the CLI is immediately available:
nonstop-notify --self-check
AppImage is portable and does not install itself or update PATH:
chmod +x ./Nonstop.Notify_0.1.2_amd64.AppImage
./Nonstop.Notify_0.1.2_amd64.AppImage --self-check
Create a stable CLI command when ~/.local/bin is on PATH:
mkdir -p ~/.local/bin
ln -s "$PWD/Nonstop.Notify_0.1.2_amd64.AppImage" ~/.local/bin/nonstop-notify
nonstop-notify --self-check
Until a release is published, build from source using the steps below.
Requirements:
npm.cmd ci --prefix ui-react --ignore-scripts
npm.cmd --prefix ui-react run build
cargo test --locked
cargo tauri build --no-bundle # Windows portable executable
cargo tauri build --bundles deb,appimage # Linux packages
For frontend development:
npm.cmd --prefix ui-react run dev
Free code signing provided by SignPath.io, certificate by SignPath Foundation.
quangnv13/nonstop-notifyquangnv13quangnv13Current eligibility and application work are tracked in docs/signpath-free-code-signing-checklist.md.
Release and WinGet submission steps are documented in RELEASING.md.
Licensed under the MIT License.