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:
@@ -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
@@ -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.
|
||||
Reference in New Issue
Block a user