CLI
Install
Prebuilt binaries (prelay-<os>-<arch>) ship with every
Codeberg release — no toolchain
needed; verify the release's SHA-256 checksum. Building from the repo shares
the server module:
cd server && go build -o prelay ./cmd/prelayConfiguration
Flags, then environment variables, then ~/.config/prelay/config
(KEY=VALUE lines). Flags win.
| Flag | Env | Config key |
|---|---|---|
--server | PRELAY_SERVER | server |
--token | PRELAY_TOKEN | token |
Example config file:
# ~/.config/prelay/config
server=https://prelay.example.com
token=prelay_1_...The file holds a credential in plaintext: it must not be readable by other
users. prelay config set creates it that way; if you write it by hand, run
chmod 600 ~/.config/prelay/config.
prelay config set
Persist credentials to the config file ($PRELAY_CONFIG or
~/.config/prelay/config), merging over existing keys. The file is created
with 0600 permissions via an atomic replace — the preferred way to store a
token:
prelay config set server=https://prelay.example.com token=prelay_1_...
# wrote /home/you/.config/prelay/config (0600)Commands
prelay send
Send a notification.
# Mode A — the server encrypts (default)
prelay send --title "Deployment failed" --message "Production is down." \
--priority high --device phone
# Mode B — encrypt locally, zero-knowledge (server can't read it)
prelay send --encrypted --device 0193f8e2-... \
--title "Secret" --message "Encrypted before leaving this machine"Action buttons (both modes; validated --action is Label=ack or
Label=https://…, repeatable, max 3, label ≤ 24 chars):
prelay send --encrypted --device 0193f8e2-... \
--title "Deploy failed" --message "Production is down" \
--action "View run=https://ci.example.com/runs/1" --action "Ack=ack"Flags: --device (id or name; empty = all), --title, --message,
--priority (normal/high), --channel, --ttl (seconds),
--encrypted (Mode B; requires a device id), --action (above).
Mode B fetches the device's public key via the read-only public-key endpoint,
so it works with a notify:send token — no device:manage needed. A token
cannot combine notify:send and device:manage unless it also carries
admin (see docs/api.md); use a
device:manage token in the Android app and a notify:send token for
senders.
prelay device ls
List registered devices with status and key fingerprints.
prelay token create
Create a scoped API token. Requires an admin token.
prelay token create --scopes device:manage
# prints the full token (shown once)
# Bind the token to a single device id: a bound token may only act on that
# device (e.g. a notify:send token can only send to it). Unbound without it.
prelay token create --scopes notify:send --device 0193f8e2-...Flags: --scopes (required; comma-separated notify:send, device:manage,
admin — notify:send and device:manage cannot be combined unless admin
is also present),
--device (optional device id; restricts the token to that device).
prelay keygen
Generate an X25519 keypair — useful when registering a device from a script:
prelay keygenprelay version
Print the CLI version (prelay --version does the same):
prelay versionExamples
# One-shot from CI, no config file:
PRELAY_SERVER=https://prelay.example.com PRELAY_TOKEN=prelay_1_... \
prelay send --title "Build failed" --message "main branch is red"Protocol
The v2 wire protocol: envelope format, X25519 + ChaCha20-Poly1305, replay protection, key rotation.
Database schema
The schema and its migration history are defined in a single source of truth: `server/internal/store/migrate.go`. The same schema runs on SQLite (self-hosted) and PostgreSQL (SaaS) via the dual-dialect store — all queries