From ee9e130a923e5d1a23a1cf2af72e08f310dee68c Mon Sep 17 00:00:00 2001 From: Amir Husayn Panahifar Date: Sun, 11 Oct 2026 12:04:54 +0330 Subject: [PATCH] docs: expand the README and add the lazyntfy(1) man page Document features, installation, usage, key bindings, configuration, history, development, and project layout. Add a complete man page covering options, keys, files, and exit status. --- README.md | 172 +++++++++++++++++++++++++++++++++++++++++++++++++ man/lazyntfy.1 | 169 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 341 insertions(+) create mode 100644 man/lazyntfy.1 diff --git a/README.md b/README.md index 98ed87b..b868415 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,174 @@ # lazyntfy +A [lazygit](https://github.com/jesseduffield/lazygit)-style terminal client for +[ntfy](https://ntfy.sh): topics in the left pane, messages in the middle pane, +and the selected message in the right pane. + +``` +╭ topics ─────╮ ╭ messages ─────────────────╮ ╭ detail ───────────────╮ +│ ● alerts 12 │ │ 06-14 09:21 CRIT DiskFull │ │ CRITICAL │ +│ ○ backups │ │ 06-14 09:03 high Backup… │ │ DiskFull │ +│ ○ deploy │ │ 06-13 22:47 def Deploy… │ │ 2026-06-14 09:21:07 │ +│ │ │ │ │ mK3n9Qx… │ +│ │ │ │ │ │ +╰─────────────╯ ╰────────────────────────────╯ ╰───────────────────────╯ + lazyntfy alerts 12/12 ● connected ? help q quit +``` + +lazyntfy talks to the ntfy HTTP API directly (`GET /topic/json` to subscribe, +`POST /topic` to publish). It reads `~/.config/ntfy/client.yml` for credentials +and subscriptions, groups topics that share a server and credentials onto one +stream, and reconnects automatically — resuming from the newest event it has +already seen so nothing is delivered twice. + +## Features + +- **lazygit-style layout** — topics, messages, and message detail in three panes. +- **Account discovery** — with no topic on the command line it lists your + subscriptions, reservations, and ACL grants. +- **Alert-aware** — Grafana and Alertmanager webhook bodies are summarized + (status, alert name, severity, summary); `v` shows the raw JSON. +- **Persistent** — topics you add and the messages that arrive are stored in a + small SQLite file and restored on the next start. +- **Resilient** — reconnects with exponential backoff, honoring `message_delete` + and `message_clear` events. +- **Single binary, no CGo** — pure Go, including the SQLite driver. + +## Requirements + +- Go 1.26 or newer (to build) +- A reachable ntfy server + +## Installation + +### From source + +```sh +git clone https://src.panahifar.ir/ahp/lazyntfy.git +cd lazyntfy +make install # installs the binary and the man page under ~/.local +``` + +`make install` honors `PREFIX` (default `~/.local`): + +```sh +make install PREFIX=/usr/local +``` + +### With `go install` + +```sh +go install ./cmd/lazyntfy@latest # or: go install lazyntfy/cmd/lazyntfy +``` + +## Usage + +```sh +lazyntfy # topics from the account, their history, and client.yml +lazyntfy alerts # one topic, expanded with default-host +lazyntfy --since 1h alerts # replay the last hour +lazyntfy --host https://ntfy.example alerts +lazyntfy --token tk_xxx alerts +lazyntfy --user name:pass alerts +``` + +With no topic on the command line, lazyntfy asks the server for your account +subscriptions, reserved topics, and ACL grants (`GET /v1/account` and, when +allowed, `GET /v1/users`), then adds the topics remembered from previous +sessions. You can always add a topic for the current session with `a`. + +## Key bindings + +Keys act on the focused pane. Use `tab` / `shift-tab` or `1` / `2` / `3` to +change panes. + +| Key | Action | +| --- | --- | +| `j` / `k`, arrows | move in the focused pane | +| `g` / `G` | first / last | +| `ctrl-u` / `ctrl-d` | page up / down | +| `1` / `2` / `3` | focus topics, messages, detail | +| `tab` / `shift-tab` | next / previous pane | +| `enter` | topics → messages → detail | +| `esc` | back from detail, or clear the filter | +| `/` | filter title, body, tags, and id | +| `r` | reconnect | +| `p` | publish to the focused topic | +| `a` | subscribe to another topic for this session | +| `v` | toggle raw JSON | +| `o` | open the message click URL | +| `?` | help | +| `q` | quit | + +On a narrow terminal the detail pane is hidden until it is focused. + +## Configuration + +lazyntfy reads the official ntfy client configuration at +`~/.config/ntfy/client.yml`: + +```yaml +default-host: https://ntfy.example +default-token: tk_xxxxxxxxxxxxxxxx +subscribe: + - topic: alerts + - topic: https://other.example/backups + user: alice + password: secret +``` + +Positional topics on the command line replace the file's `subscribe` list. +Credentials are sent in the `Authorization` header and are never printed or +written back. See `man lazyntfy` for every flag. + +## History and storage + +Topics you add and the messages that arrive are kept in a small SQLite database +at `$XDG_DATA_HOME/lazyntfy/history.db` +(`~/.local/share/lazyntfy/history.db` by default), so the last session is +restored on the next start. Each topic keeps its newest 1000 messages; expired +messages are pruned on startup. Credentials are never written to the database — +the current run's authentication is always used. History is best effort: if the +file cannot be opened, the client still runs. + +## Development + +```sh +make build # build ./lazyntfy +make test # go test ./... +make vet # go vet ./... +make fmt # gofmt -w . +make run TOPIC=alerts +make man # install just the man page +``` + +Run a single package's tests, for example: + +```sh +go test ./internal/history/... +``` + +## Project layout + +| Path | Purpose | +| --- | --- | +| `cmd/lazyntfy` | flags and program startup | +| `internal/config` | `client.yml` plus CLI overrides | +| `internal/history` | on-disk topics and messages (SQLite) | +| `internal/ntfy` | HTTP subscribe, publish, reconnect | +| `internal/store` | newest-first messages, delete, clear | +| `internal/alert` | Grafana / Alertmanager summary | +| `internal/theme` | Catppuccin adaptive palette | +| `internal/textutil` | width-aware text wrapping and clipping | +| `internal/tui` | Bubble Tea interface | +| `man` | `lazyntfy(1)` man page | + +## Contributing + +1. Fork the repository and create a topic branch. +2. Keep commits focused and conventional (`feat:`, `fix:`, `docs:`, …). +3. Run `make fmt vet test` before opening a pull request. + +## License + +GNU General Public License, version 3 or later. See [LICENSE](LICENSE). diff --git a/man/lazyntfy.1 b/man/lazyntfy.1 new file mode 100644 index 0000000..779c013 --- /dev/null +++ b/man/lazyntfy.1 @@ -0,0 +1,169 @@ +.\" lazyntfy(1) - a lazygit-style terminal client for ntfy +.TH LAZYNTFY 1 "2026-10-11" "lazyntfy 0.1.0" "User Commands" +.SH NAME +lazyntfy \- a lazygit-style terminal client for ntfy +.SH SYNOPSIS +.B lazyntfy +.RI [ options ] +.RI [ topic ...] +.SH DESCRIPTION +.B lazyntfy +is a terminal user interface for the +.BR ntfy (1) +pub\-sub notification service, laid out like +.BR lazygit (1): +topics in the left pane, messages in the middle pane, and the selected +message in the right pane. +.PP +It speaks the ntfy HTTP API directly, subscribing with +.B GET +.IR topic /json +and publishing with +.B POST +.IR topic . +When no topic is given on the command line it asks the server for the +account subscriptions, reserved topics, and ACL grants, then adds any +topics remembered from previous sessions. Short topic names are expanded +with +.IR default\-host . +.PP +Messages from Grafana and Alertmanager webhooks are summarized (status, +alert name, severity, and summary); the raw JSON is available with the +.B v +key. A message that is deleted or cleared on the server is removed from +the list as well. +.PP +When the connection drops, +.B lazyntfy +reconnects and sets the stream's +.B since +parameter to the newest event time it has already seen, so no message is +delivered twice. +.SH OPTIONS +.TP +.BI \-\-config " path" +Read the ntfy client configuration from +.IR path +instead of +.IR ~/.config/ntfy/client.yml . +.TP +.BI \-\-host " url" +Override +.I default\-host +from the configuration file. +.TP +.BI \-\-token " token" +Use +.I token +as a Bearer credential, overriding the configuration file. +.TP +.BI \-\-user " user[:password]" +Use HTTP basic authentication, overriding +.I default\-user +and +.I default\-password . +A token and a user are mutually exclusive; the last one given wins. +.TP +.BI \-\-since " value" +Replay window to request when a stream is opened. The value is +.B all +(the default), a duration such as +.BR 1h , +a Unix timestamp, or a message id. +.TP +.B \-\-version +Print the version and exit. +.TP +.B \-\-help +Print a short usage summary and exit. +.SH KEYS +Keys act on the focused pane. Use +.B tab +or +.BR 1 , +.BR 2 , +.B 3 +to change panes. +.TP +.B j ", " k ", " \(dqup\(dq ", " \(dqdown\(dq +Move within the focused pane..TP +.B g ", " G +Jump to the first or last item. +.TP +.B ctrl\-u ", " ctrl\-d +Page up or down. +.TP +.B enter +Descend: topics to messages to detail. +.TP +.B esc +Leave the detail pane, or clear an active filter. +.TP +.B / +Filter by title, body, tags, and message id. +.TP +.B r +Reconnect the streams. +.TP +.B p +Publish a message to the focused topic. +.TP +.B a +Subscribe to another topic for this session and remember it. +.TP +.B v +Toggle the raw JSON view of the selected message. +.TP +.B o +Open the selected message's click URL in the default browser. +.TP +.B ? +Show the in\-app help. +.TP +.B q +Quit. +.SH FILES +.TP +.I ~/.config/ntfy/client.yml +The ntfy client configuration read at startup. It supplies +.IR default\-host , +.IR default\-token " / " default\-user " / " default\-password , +and the +.I subscribe +list. Credentials are sent in the +.B Authorization +header and are never printed or written back. +.TP +.IR $XDG_DATA_HOME /lazyntfy/history.db +The SQLite database that remembers topics and messages between runs. +When +.B XDG_DATA_HOME +is unset it falls back to +.IR ~/.local/share/lazyntfy/history.db . +Credentials are never stored. History is best effort: if the file cannot +be opened the client still runs, it simply does not remember the session. +.SH ENVIRONMENT +.TP +.B XDG_DATA_HOME +Base directory for the history database. +.SH EXIT STATUS +.TP +.B 0 +Success, including +.B \-\-help +and +.BR \-\-version . +.TP +.B 1 +The terminal interface failed. +.TP +.B 2 +Invalid arguments or configuration. +.SH SEE ALSO +.BR ntfy (1), +.BR curl (1) +.PP +The ntfy HTTP API: +.IR https://docs.ntfy.sh/publish/ . +.SH LICENSE +GNU General Public License, version 3 or later.