ntfyx
v0.4.1
Published
End-to-end encrypted agent notifications and one-time replies
Readme
Ntfyx
Send task completion notifications and answer agent questions from your phone. Ordinary Agent and CLI messages are end-to-end encrypted. A Ntfyx phone app and an approved phone pairing are required before sending messages or using the MCP tools. CLI 0.4.0 adds Windows x64/arm64 installation, private storage and updates. CLI 0.4.1 keeps reply waits alive through temporary network failures, shares concurrent waits in one process, and reduces local history and credential writes. Fixed POST webhooks use separately phone-authorized webhook keys. My Monitor management and structured Agent discovery remain available.
Requires Node.js 24 or later on macOS (Apple silicon or Intel), Windows (x64 or arm64), or Linux glibc (x64 or arm64). Musl Linux is not supported. Installation downloads the version-pinned binary from ntfyx.me and verifies its release signature and hash.
npm install -g [email protected]
ntfyx connect
ntfyx send "Task finished"
ntfyx ask "Continue?" --allow-denyWindows standalone installation uses PowerShell without administrator rights:
irm https://ntfyx.me/install.ps1 | iex
ntfyx connectManual script / ZIP downloads and npm installation are alternatives in the detailed guide.
The per-user installation is %LOCALAPPDATA%\Ntfyx\bin, and credentials are
%LOCALAPPDATA%\Ntfyx\credentials.json. Windows standalone ntfyx upgrade
verifies the new binary, then schedules replacement after that CLI process exits;
its private receipt records completion or failure. Run ntfyx version --json
before continuing. A successful replacement retains .rollback; failed updates
restore the prior binary. npm installations continue to use the package manager.
Windows downloads use the P-256 release manifest; Authenticode signing is not
configured. Native host permission approvals remain limited to the separately
verified host/platform combinations; ordinary CLI and MCP questions are available
on Windows and Intel Mac.
Windows direct setup supports Claude Code hooks with version 2.1.139 or newer; older or unknown host versions get MCP only. Codex on Windows registers local MCP without automatic hooks. The current 0.2.0 marketplace plugin uses POSIX shell hooks; use direct setup on Windows. Native host approval policy is unchanged.
Scan the connection QR code in Ntfyx and approve the connection on your phone. Keep the resulting local credentials on that machine.
Discover command options, input schemas, effects and required permissions:
ntfyx capabilities --json
ntfyx help monitor --json
ntfyx monitor add --help --jsonTo manage the same My Monitor items shown in the app, first open My Monitor in Ntfyx once. Then request monitor access from an existing paired Source:
ntfyx monitor authorize --async --expires 24h --json
# Approve the specific monitor-access question on your phone, then use the returned ID:
ntfyx monitor auth-status AUTHORIZATION_ID --json
ntfyx monitor add --name "API health" --url https://example.com/health --rule reachable --json
ntfyx monitor list --json
ntfyx monitor show MONITOR_ID --json
ntfyx monitor update MONITOR_ID --name "Production API" --dry-run --json
ntfyx monitor update MONITOR_ID --name "Production API" --json
ntfyx monitor test MONITOR_ID --json
ntfyx monitor preview https://example.com/health --json
ntfyx monitor pause MONITOR_ID --json
ntfyx monitor resume MONITOR_ID --json
ntfyx monitor delete MONITOR_ID --json
ntfyx monitor revoke --jsonUse --contains "ready" for a text rule, or --json-field ok --equals true for
a typed JSON boolean comparison. JSON string values need JSON quoting, for example
--json-field status --equals '"ok"'. A complete monitor configuration can be read
with monitor add --stdin; partial updates preserve fields you do not specify.
--dry-run returns a plan without saving. Reuse an --operation-id and the exact
same input after an uncertain result; --generation rejects stale edits.
Use --operation-id=ID when supplying an operation ID, so IDs beginning with a
dash are parsed as string values.
Monitor access covers all My Monitor URLs, rules, status and recent results in the
paired Inbox, plus create, edit, pause, resume, delete, test and preview. The phone
must explicitly approve this scope. Authorization prompts expire after 10 minutes;
grants default to 24 hours and accept --expires from 5 minutes to 24 hours, capped
by the Source's own lifetime. Revoke the grant with the CLI or revoke the Source in
the app. Neither the CLI nor its monitor SDK needs the phone/root private keys.
Only this explicit authorization question and its signed answer are disclosed to the Ntfyx service for verification using the two individual encryption contexts. Ordinary messages keep their encryption. The hosted monitor executor processes target URLs and bounded responses; observation notifications are encrypted to authorized receivers. Monitor permission does not grant Inbox administration, Topic/subscription changes, or access to other Sources' message history.
Prepare HTTPS Push once on the primary phone to use a fixed incoming webhook.
The whole HTTPS Push link already copied by the app accepts POST with dynamic
JSON text/body/message/content, plain text, or URL-encoded form bodies;
GET keeps its original URL-message behavior. No new app version is required.
For independent child keys, request separate webhook management permission:
ntfyx webhook authorize --async --no-input --expires 24h --json
# Approve the fixed Topic and webhook scope on your phone:
ntfyx webhook auth-status AUTHORIZATION_ID --json
ntfyx webhook create --name "Deploy alerts" --url-file ./private-webhook-url.txt --json
ntfyx webhook list --json
ntfyx webhook show WEBHOOK_ID --json
ntfyx webhook update WEBHOOK_ID --name "Production deploys" --dry-run --json
ntfyx webhook rotate WEBHOOK_ID --url-file ./next-private-webhook-url.txt --json
ntfyx webhook disable WEBHOOK_ID --json
ntfyx webhook enable WEBHOOK_ID --json
ntfyx webhook delete WEBHOOK_ID --json
ntfyx webhook revoke --json--url-file exclusively creates a new private file (0600 on macOS/Linux,
current-user DACL on Windows); ordinary stdout, MCP and the
ledger return metadata and the path, never its raw URL/key. The management API
receives only key digests. Each URL is a send-only secret for one HTTPS Topic.
Webhook management grants last up to 24 hours; keys last until their owner Source
expires. webhook revoke stops management, while existing keys continue to send.
Use disable/delete or revoke the owner Source to stop sending. Parent HTTPS pause
is recoverable with the same token; rotating that token invalidates old children.
Monitor permission cannot manage webhooks, and phone/root private keys stay on
the phone. Source/phone/root bindings and generation checks fence stale keys. Child keys
share the HTTPS sender's 60/minute admission limit, plus ordinary Source limits
of 30 new messages/minute and 10 per 2 seconds.
Child keys optionally use --signature-mode github|standard with a private
--verification-secret-file. Windows verifies file ownership, DACLs and links;
POSIX chmod bits are not used as a substitute for Windows permissions. GitHub signs only the raw body, without binding the delivery ID or timestamp.
Standard Webhooks also binds ID/time with a 300-second window. This separate verification secret
is encrypted and stored by the service, then used in plaintext to verify requests.
Webhook bodies are processed by the service before encrypted delivery. Switching
to none clears the hosted secret. Ordinary Agent messages keep their encryption.
Body reads have an absolute five-second deadline (408 is retryable).
Raw requests are limited to 64 KiB, messages to 12,000 characters and titles to
120. The final JSON message also has a 16 KiB encrypted-payload limit including
JSON overhead; multibyte text may reach it first. Present text aliases must be strings with the same value; duplicate keys,
invalid UTF-8 and conflicting inputs reject. Other event JSON is displayed as
JSON text and rejects with 413 if too long, never truncates. Attachments/URLs are
not fetched; full Slack blocks or Discord embeds/files are not implemented.
Reuse the same Idempotency-Key and exact input after an uncertain result;
provider delivery IDs must agree with it. Without an ID, each request is new.
Honor Retry-After on 429/503. A 2xx response proves acceptance, not phone receipt.
Inspect your local encrypted request ledger and the signed public plugin directory:
ntfyx requests list --limit 20 --json
ntfyx requests show REQUEST_ID --json
ntfyx result REQUEST_ID --json
ntfyx marketplace list --json
ntfyx marketplace show tech-digest --jsonrequests shows this computer's Source ledger, not complete Inbox history. Reading
it never claims an answer. Only a verified answered result with an acquired claim
can authorize execution; sending or accepting a prompt is not approval. Marketplace
browsing requires no pairing and creates no subscription. Invalid command flags
are rejected before remote work; for example, send --dry-run is an error.
--no-input refuses flows that need local interaction; explicit
monitor authorize --async --no-input can create a pending phone request.
For an MCP client, first pair using npx [email protected] connect, then configure:
{
"mcpServers": {
"ntfyx": {
"command": "npx",
"args": ["-y", "[email protected]", "mcp"]
}
}
}The MCP server uses local stdio and the local paired identity. It does not offer
a hosted MCP endpoint. Monitor MCP tools share the CLI's authorization, update,
dry-run and operation-ID behavior. ntfyx_monitor_authorize creates a pending
phone request; ntfyx_monitor_auth_status verifies the reply before activating
access. Webhook MCP tools use the same separate grant, metadata-only results,
explicit private file exports and update/replay controls. ntfyx_ask accepts an idempotency key for repeated calls with identical input.
Native tool approval is separate from MCP questions:
Apple silicon Mac validation covers Claude Code 2.1.303 and Codex 0.163.0 with
CLI 0.1.5 or later; Intel Mac native approval remains unverified and returns to
the terminal. Claude permission hooks require explicit --permissions on during
setup. Codex requires interactive TUI and /hooks trust; codex exec does not
trigger permission hooks.
