diff --git a/Makefile.am b/Makefile.am index 96c1ee3cf17b6a19a1bec70364a9ef14ee031def..764435af0114c89e47ecbb2b8ae9c115c3faa82e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -14,13 +14,9 @@ core_sources = \ src/mode/mam.h src/mode/mam.c \ src/mode/openpgp.h src/mode/openpgp.c -man_sources = doc/xmppc.1 - AM_CFLAGS = @AM_CFLAGS@ -I$(srcdir)/src -dist_doc_DATA = README.md doc/xmppc.1.html +dist_doc_DATA = README.md bin_PROGRAMS = xmppc xmppc_SOURCES = $(core_sources) $(main_source) - -man_MANS = $(man_sources) diff --git a/README.md b/README.md index 6cddf17c886b7039744c7b01d5c04f5b7aa61236..8f6ed76ec5afe67b8febbef2636618661ad5a90d 100644 --- a/README.md +++ b/README.md @@ -1,57 +1,291 @@ # xmppc -CLI for XMPP written in C and using [libstrophe](http://strophe.im/libstrophe/). -This repo is a fork (likely hard) of the original -[xmppc](https://codeberg.org/Anoxinon_e.V./xmppc) and might get renamed. +`xmppc` is a CLI XMPP client written in C on top of +[libstrophe](http://strophe.im/libstrophe/). It's useful when you want a script, +shell, or agent to do one XMPP thing and then exit, like list a roster, send a +chat message, read recent archive entries, wait for a reply, inspect bookmarks, +and so on. -## Dependencies +This repository is a fork — probably a hard fork — of the original +[xmppc](https://codeberg.org/Anoxinon_e.V./xmppc). It may be renamed later. +Please do not send issues from using this fork straight upstream; see +[Issues](#issues). -- [libc6-dev](https://packages.debian.org/trixie/libc6-dev) (2.28-10) -- [libglib2.0-dev](https://packages.debian.org/trixie/libglib2.0-dev) (2.58.3) -- [libstrophe-dev](https://packages.debian.org/trixie/libstrophe-dev) (0.9.2-2) -- [libgpgme-dev](https://packages.debian.org/trixie/libgpgme-dev) (1.12.0) -- [automake](https://packages.debian.org/trixie/automake) (1.17) +## Install from source -## Build +On Debian or Ubuntu-like systems, install the build tools and libraries first: +```sh +sudo apt-get update +sudo apt-get install -y \ + autoconf \ + automake \ + gcc \ + libglib2.0-dev \ + libgpgme-dev \ + libstrophe-dev \ + libtool \ + make \ + pkg-config ``` -# on Debian/Ubuntu -apt install -y automake libstrophe-dev libc6-dev libglib2.0-dev libgpgme-dev + +Then build the binary: + +```sh ./bootstrap.sh ./configure make -# mv xmppc $HOME/.local/bin/ or somewhere else in your PATH ``` -## Config file +Put the resulting `xmppc` somewhere in your `PATH`, for example: + +```sh +mkdir -p ~/.local/bin +mv xmppc ~/.local/bin/xmppc +``` + +## Files + +- `~/.config/xmppc.conf` — account configuration. +- `~/.config/xmppc/AGENTS.md` — optional instructions for LLM agents using + `xmppc`. -`~/.config/xmppc.conf` +## Accounts and passwords -`[default]` is used when neither account nor JID is provided. +You can pass a JID directly: +```sh +xmppc --jid user@example.net --pwd 'secret' --mode roster list ``` + +If `--pwd` is omitted, `xmppc` asks for the password without echoing it. If you +want to pipe a password in, use `--pwd -`: + +```sh +pass show xmpp/example | xmppc --jid user@example.net --pwd - --mode roster list +``` + +Named accounts are probably nicer. `xmppc` reads them from +`~/.config/xmppc.conf`; the `[default]` account is used when neither `--account` +nor `--jid` is provided. + +```ini [default] -jid=user@domain.tld -pwd=YourSecret +jid=user@example.net +pwd=secret + +[work] +jid=user@work.example +pwd-cmd=pass show xmpp/work + +[bot] +jid=bot@example.net +pwd=another-secret +``` + +Prefer `pwd-cmd` if you already keep passwords in a local password manager. It +runs locally and its stdout, minus the trailing newline, becomes the password. + +## Command shape + +Most commands follow this pattern: + +```sh +xmppc [--account ACCOUNT] [--jid JID] [--pwd PASSWORD] --mode MODE COMMAND [args...] +``` + +Short options are available too: + +```sh +xmppc -a work -m roster list +xmppc -j user@example.net -p - -m mam list friend@example.net +``` -[account1] -jid=account1@domain.tld -pwd=YourSecret +Use `-v`, `-vv`, `-vvv`, or `-vvvv` for progressively noisier logging. Use +`--help` for the built-in summary. + +## Modes + +### Roster + +```sh +xmppc -a work -m roster list +xmppc -a work -m roster export ``` -## Usage +`list` shows the account's contacts. `export` exports them. + +### Message + +```sh +xmppc -a work -m message chat friend@example.net 'hello from xmppc' +``` + +`message chat` sends an unencrypted chat message. After the sent stanza appears +in Message Archive Management (MAM), it prints one compact XML line: + +```xml + +``` + +An important bit is the distinction between the two IDs: + +- `archive-id` is the MAM cursor. Use it with `mam receive after-id=...` when you + want to wait for the next reply. +- `message-id` is the client stanza ID. It's useful for matching messages, but + it's not a MAM cursor. +If `archive-id` is empty, the message was sent but the archive cursor wasn't +resolved before the lookup timed out. See [Send, then wait for a +reply](#send-then-wait-for-a-reply) for the fallback. + +### Message Archive Management (MAM) + +MAM commands use XEP-0313 to read archived messages. + +```sh +xmppc -a work -m mam list friend@example.net +xmppc -a work -m mam list with=friend@example.net start=-15m max=20 +xmppc -a work -m mam receive friend@example.net after-id=mam-id timeout=300s max=5 ``` -xmppc --jid user@domain.tld --pwd "password" --mode roster list -xmppc -j user@domain.tld -p "password" -m roster list -xmppc -a alice -m mam list bob@domain.tld -xmppc -m bookmark list -xmppc -h + +`mam list` accepts unordered `field=value` terms: + +- `with=` filters to a conversation. A bare JID is shorthand for `with=`. +- `start=