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.
This commit is contained in:
ahp
2026-10-11 12:04:54 +03:30
parent 714b2da0c7
commit ee9e130a92
2 changed files with 341 additions and 0 deletions
+172
View File
@@ -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).
+169
View File
@@ -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.