Xepher is a WeeChat plugin written in C++23 that adds full XMPP support to WeeChat. It targets XMPP Compliance Suite 2022 (XEP-0459) and implements a broad set of modern XEPs — including OMEMO encryption, Message Archive Management, HTTP file upload, microblogging via PubSub, and more.
Fork of bqv/weechat-xmpp
Original author: Tony Olagbaiye <bqv@fron.io>
Maintained at github.com/ekollof/xepher
Binary packages for v0.8.1 and later are published on GitHub Releases. Pick the file for your distribution:
| Platform | Package |
|---|---|
| Debian / Ubuntu | xepher_*_amd64.deb |
| Fedora / RHEL | xepher-*-fc*.x86_64.rpm |
| Arch Linux | xepher-*-x86_64.pkg.tar.zst |
| Void Linux | xepher-*_x86_64.xbps |
| Alpine Linux | xepher-*-r0.apk |
Note: Avoid the v0.8.0 Fedora RPM and Alpine APK — they were built with a packaging bug that produced ~1 GB artifacts. Use v0.8.1 or newer.
Install examples:
# Debian/Ubuntu
sudo dpkg -i xepher_0.8.1-1_amd64.deb
# Fedora
sudo dnf install ./xepher-0.8.1-1.fc44.x86_64.rpm
# Arch (as root or with sudo)
sudo pacman -U xepher-0.8.1-1-x86_64.pkg.tar.zstAfter installing, restart WeeChat (or run /plugin load xmpp.so on first install).
| Library | Type | Linux | FreeBSD | OpenBSD | macOS (Homebrew) |
|---|---|---|---|---|---|
| libstrophe | runtime | ✅ package | ✅ pkg install libstrophe |
✅ pkg_add libstrophe |
✅ brew install libstrophe |
| libxml2 | runtime | ✅ package | ✅ pkg install libxml2 |
✅ pkg_add libxml |
✅ brew install libxml2 |
| lmdb | runtime | ✅ package | ✅ pkg install lmdb |
✅ pkg_add lmdb |
✅ brew install lmdb |
| libomemo-c | runtime | ✅ package | ✅ pkg install libomemo-c |
✅ pkg_add libomemo-c |
|
| libsignal-protocol-c | runtime | ✅ package | ✅ pkg install libsignal-protocol-c |
✅ pkg_add libsignal-protocol-c |
|
| gpgme | runtime | ✅ package | ✅ pkg install gpgme |
✅ pkg_add gpgme |
✅ brew install gpgme |
| libfmt | runtime | ✅ package | ✅ pkg install libfmt |
✅ pkg_add fmt |
✅ brew install fmt |
| clang/clang++ (C++23; ≥ 13) | build | ✅ package | ✅ pkg install llvm |
✅ base system / pkg_add |
✅ brew install llvm |
| gmake | build | — (GNU make default) | ✅ pkg install gmake |
✅ pkg_add gmake |
✅ brew install make |
| bison | build | ✅ package | ✅ pkg install bison |
✅ pkg_add bison |
✅ brew install bison |
| flex | build | ✅ package | ✅ pkg install flex |
✅ pkg_add flex |
✅ brew install flex |
| doctest (header-only) | test | ✅ vendored in deps/doctest/ |
— | — | — |
| WeeChat >= 3.0 | runtime | ✅ package | ✅ pkg install weechat |
✅ pkg_add weechat |
✅ brew install weechat |
On FreeBSD and OpenBSD, run ./install-deps.sh (or build from the port skeletons in
packaging/freebsd/ and packaging/openbsd/). Use gmake instead of make.
The plugin is developed and tested on Linux (Arch, Debian/Ubuntu, Fedora, Void, Alpine). CI builds packages for all five via GitHub Actions on each release tag.
macOS (Apple Silicon and Intel) receives best-effort support via Homebrew.
The build system auto-detects the Homebrew prefix and sets PKG_CONFIG_PATH
accordingly. See macOS build instructions below.
FreeBSD, OpenBSD, and NetBSD receive best-effort support: the build system and scripts have been ported to POSIX sh and BSD-compatible make, but these platforms are not routinely tested. Known considerations:
- Use
gmakeinstead ofmakeon BSD (BSD make has different syntax). - Default toolchain: Clang/Clang++ (≥ 13). The makefile sets
CC=clangandCXX=clang++on all platforms (Homebrew LLVM on macOS). This matches OpenBSD/FreeBSD and catches Clang-only warnings under-Werror. NetBSD 9.x ships Clang 7 and cannot build — use NetBSD 10.x+ or a newer Clang from pkgsrc. Override withCC=gcc CXX=g++ gmakeonly for experiments. libsignal-protocol-candlibomemo-care packaged on FreeBSD and OpenBSD; on NetBSD they may still need to be built from pkgsrc source.- Default builds use
-O2 -DNDEBUG. UseDEBUG=1for unoptimized dev builds (-O0 -DDEBUG). UseASAN=1for AddressSanitizer (-fsanitize=address;-lasan -lrton Linux only). Combine:gmake DEBUG=1 ASAN=1. - The
.sourceELF section embedding step (objcopy --add-section) is Linux-only, skipped on BSD, and skipped in distribution builds (PACKAGE_BUILD=1).
git clone --depth 1 git@github.com:ekollof/xepher.git
cd xepher
make install-deps # installs system packages (requires sudo)
make # optimized plugin (no doctests)
make DEBUG=1 # dev build + 123 doctests
make test # doctests only (handler slices, StanzaView, IQ builders, …)
make install # installs to ~/.local/share/weechat/plugins/ — do NOT run as rootOn BSD, replace make with gmake throughout.
Doctest is vendored under deps/doctest/ (v2.5.2). make DEBUG=1 or make test
runs the full 109 handler-slice tests on every supported platform without a system package.
Plain make skips doctests.
To build a distribution-style plugin locally (no .source embed, same as packages):
make PACKAGE_BUILD=1 weechat-xmppmake install-deps automatically detects your distribution (Debian/Ubuntu,
Fedora/RHEL, Arch, openSUSE, Void, Alpine, Gentoo, FreeBSD, OpenBSD, NetBSD,
macOS) and installs the required packages.
Note:
libsignal-protocol-candlibomemo-care not in Homebrew core and must be built from source before the plugin will compile.
Step 1 — Install Homebrew packages:
./install-deps.sh # detects macOS and runs the brew install blockOr manually:
brew install llvm make bison flex libstrophe libxml2 lmdb gpgme fmt curl openssl weechatStep 2 — Build libsignal-protocol-c from source:
git clone https://github.com/signalapp/libsignal-protocol-c
cd libsignal-protocol-c
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$(brew --prefix) .
make && make install
cd ..Step 3 — Build libomemo-c from source:
git clone https://github.com/gkdr/libomemo-c
cd libomemo-c
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$(brew --prefix) .
make && make install
cd ..Step 4 — Build Xepher:
git clone --depth 1 git@github.com:ekollof/xepher.git
cd xepher
git submodule update --init --recursive
make
make test
make installThe build system uses -dynamiclib instead of -shared and plain -g instead
of -gdwarf-4 on macOS automatically. install-deps.sh installs Homebrew
llvm; the makefile defaults to that Clang. No extra CXX= flags are needed.
Debugger: On macOS the make debug target uses lldb with
DYLD_INSERT_LIBRARIES instead of gdb/LD_PRELOAD.
WeeChat 4.3.0 (May 2024) changed the base64 API. This fork defaults to
>= 4.3.0. If you get a compilation error like
invalid conversion from 'int' to 'const char*', open omemo.cpp, find this
block near line 42, and change #if 1 to #if 0:
#if 1 // Set to 0 for WeeChat < 4.3.0
#define WEECHAT_BASE64 "64"
#else
#define WEECHAT_BASE64 64
#endifThen rebuild with make clean && make.
/account add work user@example.com mypassword
/account connect work
Use /help account for full details.
Add the xmpp_encryption bar item to your status bar to see the current
buffer's encryption mode (🔒OMEMO / 🔒PGP / empty for plaintext). In MUCs it may show "🔒OMEMO (pending)" while fetching occupant bundles.
/set weechat.bar.status.items "[time],[buffer_last_number],[buffer_plugin],buffer_number+:+buffer_name+(buffer_modes)+{buffer_nicklist_count}+buffer_zoom+buffer_filter,xmpp_encryption,[lag],[hotlist],completion"
-
Enable typing in WeeChat:
/set typing.look.enabled_nicks on /set typing.look.enabled_self on /set typing.look.input_min_chars 2 /save typing -
Add the typing bar item:
/set weechat.bar.typing.items "typing" /save
Sent PM messages show delivery and encryption status as aligned prefixes at the
start of the message text (WeeChat's private tag hides the nick column for
your own lines). Examples: ⌛ hello, ✓ 🔒 hello. Status updates
automatically when the recipient acknowledges the message:
| Glyph | Meaning |
|---|---|
| ⌛ | Pending — sent, no receipt yet |
| ✓ | Delivered — recipient's client received it (XEP-0184) |
| ✓✓ | Read — recipient marked it displayed (XEP-0333) |
A colored Unicode symbol (for example ◉) may appear before a contact's bare
JID in PM buffers. That is a deterministic avatar badge derived from their
XEP-0084 PEP avatar image — not an
OMEMO device ID. Contacts without a published avatar show only the colored JID.
The account nickname is automatically added as a highlight word to PM and FEED buffers so messages containing it trigger a notification. MUC rooms use WeeChat's native nick-based highlighting instead.
To disable this behaviour (e.g. if your short nickname causes false highlights):
/set xmpp.look.highlight_words off
/save
When a message contains an <html> body, the plugin renders it with WeeChat
color/attribute support instead of raw markup.
| Element | Rendered as |
|---|---|
<b>, <strong> |
Bold |
<i>, <em> |
Italic |
<u> |
Underline |
<del>, <s>, <strike> |
Darkgray |
<code>, <tt> |
Gray monospace |
<pre> |
Gray-wrapped preformatted block |
<a href="...">text</a> |
text (blue URL) |
<img alt="..."/> |
[alt] placeholder |
<br> |
Newline |
<blockquote> |
Green > prefix |
<span style="color:..."> |
Terminal color (16 named + #rgb hex) |
Incoming: When a message contains <rdf:Description> (XEP-0511) carrying
OpenGraph metadata, a compact preview is rendered in darkgray:
alice: Check this out! https://example.com/article
The Best Webpage This is a great webpage and you will really like it https://example.com/canonical-url [img]
To disable incoming previews:
/set xmpp.look.incoming_link_preview off
Outgoing: URLs in your messages automatically trigger a background fetch; a metadata stanza is sent as a follow-up so the recipient can render a preview even without server-side injection. To disable:
/set xmpp.look.outgoing_link_preview off
Opens an interactive picker showing your last 20 non-retracted sent messages so you can select which one to correct, then pre-fills the input bar with the original text ready for editing.
/edit # open interactive picker — select message, edit in input bar
/edit-to <id> <text> # correct a specific message by ID (used internally by picker)
How it works:
- Type
/editwith no arguments to open the interactive picker. - Navigate with
↑/↓and pressEnterto select the message you want to correct. - The picker closes and the input bar is pre-filled with
/edit-to <id> <original text>. Edit the text and pressEnterto send. - A correction stanza is sent referencing the original message ID. The local
buffer updates the line with an
[edit]prefix.
Notes:
- In MUC rooms, correction uses the server-assigned stanza-id (XEP-0359) when available, falling back to the origin-id.
- Recipients who do not support XEP-0308 will receive the correction as a new
message with a
[CORRECTION]fallback body. - You must be connected and inside a chat buffer (PM or MUC) to use
/edit.
Example:
you: Hello eweryone!
/edit
[interactive picker opens — select the message, press Enter]
> input bar is pre-filled: /edit-to abc123 Hello eweryone!
> edit to: /edit-to abc123 Hello everyone! [Enter]
you: [edit] Hello everyone!
Deletes one of your own messages from the current buffer.
/retract
Takes no arguments. Opens an interactive picker showing your last 20
non-retracted messages. Navigate with ↑/↓, press Enter to retract the
selected message, or q/Esc to cancel.
How it works:
- An interactive picker opens listing your last 20 sent messages (most recent at the top).
- Select the message to retract and press
Enter. - A retraction stanza is sent referencing that message's ID. In MUC rooms the server-assigned stanza-id (XEP-0359) is used, which is required by the spec.
- Supporting clients replace the original message with a tombstone. The local
buffer shows
[Message deleted]in place of the original text. - A
storehint (XEP-0334) is included so MAM archives record the retraction, and other devices that sync history will also see the tombstone.
Notes:
- Retraction is not a guarantee: recipients who already received the message
keep it. Clients that do not support XEP-0424 will instead display the
fallback body:
[user] retracted a previous message, but it's unsupported by your client. - You cannot retract another user's message with
/retract. Use/moderate(XEP-0425) for that (requires MUC moderator role). - You must be connected and inside a chat buffer (PM or MUC) to use
/retract.
Example:
you: I should not have said that
/retract
[interactive picker opens — select the message, press Enter]
-- xmpp: message retraction sent
you: [Message deleted]
Sends an emoji reaction to the last received message in the current buffer.
/react <emoji>
How it works:
- Type
/reactfollowed by one or more emoji (the entire argument after/reactis used as the reaction string). - The plugin finds the most recent message in the buffer that was not sent
by you (identified by having an
id_tag and noself_msgtag). - A reaction stanza is sent referencing that message's ID.
Notes:
- Reactions target the last incoming message, not your own messages.
- In MUC rooms, the stanza-id (XEP-0359) is used when available.
- Multiple emoji in a single argument are sent as one reaction (e.g.,
/react 👍❤️sends the two-emoji string as a single reaction). - Clients that do not support XEP-0444 ignore the reaction stanza silently.
- You must be connected and inside a chat buffer to use
/react.
Examples:
/react 👍
/react ❤️
/react 😂
/react 🎉
Sends a reply with a message reference so supporting clients can display a quoted preview.
/reply # open interactive picker to choose which message to reply to
/reply <text> # reply immediately to the last received message
/reply-to <id> <text> # reply to a specific message by ID (used internally by picker)
How /reply works (no arguments — interactive picker):
- An interactive picker opens listing the last 20 messages received from others (non-own, non-retracted).
- Navigate with
↑/↓and pressEnterto select. - The picker closes and the input bar is pre-filled with
/reply-to <id>. - Type your reply text and press
Enterto send.
How /reply <text> works (with text):
The plugin finds the most recent non-own message and sends a reply directly, without opening the picker. Useful for quick replies.
Notes:
- Clients that do not support XEP-0461 will display the plain message text without the quoted context.
- In MUC rooms, the MUC-assigned stanza-id (XEP-0359) is used when present,
as required by the spec for rooms with
stanza-idsupport. - You must be connected and inside a chat buffer to use
/reply.
Examples:
/reply # opens picker
/reply Thanks, that helped! # immediate reply to last received message
Removes another user's message from a MUC room (requires moderator role).
/moderate [reason]
Opens an interactive picker showing the last 20 non-retracted messages in
the room. Navigate with ↑/↓, press Enter to moderate the selected
message, or q/Esc to cancel. The optional reason is forwarded in the
moderation stanza.
How it works:
- An interactive picker opens listing the last 20 messages in the MUC buffer (both own and others', excluding already-retracted messages).
- Select the message to moderate and press
Enter. - A moderation stanza is sent referencing the server-assigned stanza-id (XEP-0359), which is required by XEP-0425 for MUC moderation.
- Supporting clients replace the original message with a moderation tombstone.
Notes:
- Requires MUC moderator role. The server will reject the request otherwise.
- Use
/retractto delete your own messages instead. - Moderation is not a guarantee: clients that do not support XEP-0425 may still show the original message.
- Must be used inside a MUC buffer (not a PM channel).
Examples:
/moderate
/moderate Spam message
/moderate Violates community guidelines
Publish and interact with microblog posts on PubSub services such as
Movim and Libervia/Salut-à-Toi.
XMPP microblogging is XMPP's equivalent of a federated social timeline — posts
are Atom entries stored on PubSub nodes; contacts who subscribe to your
urn:xmpp:microblog:0 PEP node receive your posts in real-time.
Feed content is rendered with full visual formatting: XHTML via the XEP-0071 renderer, HTML stripped to plain text, and plain-text entries processed through a lightweight Markdown renderer (headings, bold, italic, inline code, fenced blocks, blockquotes, lists, links, images, strikethrough, horizontal rules).
Note: XEP-0277 is Deferred and XEP-0472 is Experimental. Server support varies. Movim and Libervia implement the full stack; ejabberd supports the underlying XEP-0060 mechanics.
Short aliases (#N):
When you fetch a feed, each item is assigned a short #N alias shown in green.
Use it in place of the full item-id in any write command:
/feed reply #3 That's a great point!
/feed repeat #3 Great content
/feed comments #3
/feed retract #3
Publishing a post:
# Long form
/feed post movim.eu urn:xmpp:microblog:0 Hello from WeeChat!
/feed post movim.eu myblog --open My public post # --open = public node
/feed post movim.eu myblog --title My Headline -- Body text # with Atom title
# Short form from a feed buffer (service/node inferred)
/feed post Hello everyone!
/feed post -- https://example.com check this out # '--' avoids JID-like parse
# Compose in $EDITOR (requires feed_compose.py)
/feed post --edit
Sends an Atom <entry> to the PubSub node with pubsub#type=urn:xmpp:microblog:0
and the urn:xmpp:pubsub-social-feed:1 publish-option required by XEP-0472.
Failed publishes are reported in the buffer with the server error condition.
Embedding media in a post (XEP-0363 + XEP-0447):
Top-level microblog posts (not comments) support Jinja2-style embed tags that
upload files via HTTP File Upload and insert XEP-0447 <file-sharing> children
into the Atom entry:
{{ embed "photo.jpg" }} # inline image → 
{{ embed "photo.jpg" alt="sunset" }} # with alt text
{{ attach "paper.pdf" }} # download link → [paper.pdf](url)
{{ attach "paper.pdf" alt="My Paper" }}
{{ video "demo.mp4" }} # inline video → 
{{ video "demo.mp4" alt="Demo" }}
embedandvideosetdisposition='inline';attachsetsdisposition='attachment'- Files are uploaded one at a time (async); the Atom entry is published only when all uploads have completed
- On any upload failure the post is aborted and a draft is saved to
$weechat_data_dir/xmpp/drafts/<account>-<timestamp>.mdwith YAML frontmatter; the draft path is printed in the feed buffer - Embed tags are not supported in comments nodes; attempting them prints an error
Receiving clients that support XEP-0447 (Conversations, Dino, Gajim) render the media natively. Xepher displays a summary line for each attachment:
[Image: photo.jpg (image/jpeg, 1.2 MB) https://…]
[File: paper.pdf (application/pdf, 340 KB) https://…]
Replying to a post (threaded):
/feed reply movim.eu urn:xmpp:microblog:0 abc123 That's a great point!
/feed reply #3 That's a great point! # short form using alias
/feed reply #3 --edit # compose reply in $EDITOR
Adds a thr:in-reply-to element (RFC 4685) referencing the original item.
Clients such as Movim render threaded conversations from these references.
Boosting / repeating a post (XEP-0472 §4.5):
/feed repeat movim.eu urn:xmpp:microblog:0 abc123
/feed repeat movim.eu urn:xmpp:microblog:0 abc123 Great post!
/feed repeat #3 # short form using alias
/feed repeat #3 Great content! # short form with comment
Publishes a new entry with <link rel='via'> pointing to the original item.
An optional comment is included in the entry body.
Retracting (deleting) a post:
/feed retract movim.eu urn:xmpp:microblog:0 abc123
/feed retract #3 # short form using alias
Sends a PubSub retract IQ. Server errors are reported in the buffer.
Fetching comments for a post:
/feed comments movim.eu urn:xmpp:microblog:0 abc123
/feed comments #3 # short form using alias
If the post carried a <link rel='replies'> element (XEP-0277 §4.1), this
fetches the linked comments node into a dedicated FEED buffer. The hint is shown
in the feed buffer as Comments: /feed comments #N. Run
/feed movim.eu urn:xmpp:microblog:0 first if no hint is shown.
Subscribing and unsubscribing:
/feed subscribe news.movim.eu Phoronix
/feed unsubscribe news.movim.eu Phoronix
/feed subscriptions news.movim.eu
Sends XEP-0060 subscribe/unsubscribe IQ stanzas. Feedback (success or error condition) is printed in the originating buffer.
Receiving posts from contacts:
Incoming PEP pushes from contacts' urn:xmpp:microblog:0 nodes are
automatically rendered in the WeeChat buffer for that contact, showing the
author name, timestamp, content body, and — when present — threaded reply
references (thr:in-reply-to), boost/repeat provenance (Repeated from:),
comments links (Comments: /feed comments #N), category tags, enclosure URLs,
and geolocation. XHTML and HTML content is rendered with WeeChat formatting.
Duplicate items (already seen via IQ fetch) are suppressed via LMDB deduplication.
Reading a microblog feed:
/feed movim.eu urn:xmpp:microblog:0
/feed movim.eu urn:xmpp:microblog:0 --limit 5
/feed movim.eu urn:xmpp:microblog:0 --before <item-id> # older page (RSM)
/feed movim.eu urn:xmpp:microblog:0 --latest # reset cursor; newest page
The RSM cursor is persisted in LMDB. Use --latest to go back to the newest
page after paging back through older items.
Auto-discovering your server's PubSub services:
At connect time the plugin queries your server's disco#items (XEP-0030) to
find all components, then queries disco#info on each one. Any component
reporting identity category='pubsub' is remembered. You can then use:
/feed # fetch subscriptions from all discovered services
/feed discover # list discovered services without fetching
/feed discover --all # fetch every node from every discovered service
/feed close # close all open feed buffers (does not unsubscribe)
Closing feed buffers:
/feed close dismisses every open FEED buffer without unsubscribing from PubSub
nodes. Closed feeds do not receive pubsub push updates until opened again via
/feed.
Disabling feeds entirely:
If you do not use microblogging and want to prevent feed buffers from appearing:
/set xmpp.look.feeds off
When off: no feed buffers are created or restored on connect, pubsub pushes for
feed nodes are ignored, and /feed is disabled (except /feed close to dismiss
buffers that were already open). Default is on. Re-enable with
/set xmpp.look.feeds on.
Legacy OMEMO PEP nodes (eu.siacs.conversations.axolotl.*) are never
misclassified as feeds; this option is for users who want no PubSub timeline
buffers at all.
/adhoc example.com # list available commands
/adhoc example.com announce # execute a command (form rendered inline)
/adhoc example.com announce <id> subject=Hello body=World
Required fields are marked with *. Multi-step sessions are supported.
/account list
/account add <name> <jid> <password>
/account connect <account>
/account disconnect <account>
/account reconnect <account>
/account delete <account>
/account register <name> <jid> <password> # create account on server (XEP-0077)
/account unregister <account> # cancel account on server (XEP-0077)
/account password <account> <new-password> # change password in-band (XEP-0077)
| Command | Description |
|---|---|
/enter <jid> |
Join a MUC room |
/join <jid> |
Alias for /enter |
/open <jid> |
Open a direct chat (PM) |
/query <jid> [msg] |
Alias for /open |
/msg <text> |
Send a message to the current buffer |
/me <text> |
Send a /me action (XEP-0245) |
/ephemeral <seconds> <text> |
Send an ephemeral message that disappears after N seconds (XEP-0466) |
/notify [<jid>] [always|on-mention|never] |
Get or set per-chat notification preference (XEP-0492) |
/invite [--mediated] <jid> [reason] |
Invite a user to the current MUC (XEP-0249 direct by default; --mediated for XEP-0045 §7.8.2) |
/decline [room inviter [reason]] |
Decline a pending mediated MUC invitation (XEP-0045 §7.8.2; account buffer) |
/selfping |
Verify MUC membership (XEP-0410) |
/edit |
Picker: choose a sent message to correct (XEP-0308) |
/edit-to <id> <text> |
Correct a specific message by ID — used by the /edit picker |
/retract |
Picker: choose a sent message to delete (XEP-0424) |
/moderate [reason] |
Picker: choose a MUC message to moderate (XEP-0425) |
/react <emoji> |
React to the last received message (XEP-0444) |
/reply |
Picker: choose a message to reply to (XEP-0461) |
/reply <text> |
Reply to the last received message (XEP-0461) |
/reply-to <id> <text> |
Reply to a specific message by ID (XEP-0461) |
/spoiler [hint:] <text> |
Send a spoiler message (XEP-0382) |
/buzz |
Send attention request to current PM contact (XEP-0224) |
/whois [jid] |
Retrieve vCard information (XEP-0054) |
/setvcard <field> <value> |
Publish a vCard field (XEP-0054) |
/setavatar <filepath> |
Publish avatar image (XEP-0084) |
| Command | Description |
|---|---|
/enter <jid> |
Join a MUC room (creates it if it doesn't exist on the server) |
/join <jid> |
Alias for /enter |
/create <room@server> [nick] [--reserved] |
Create a new MUC room (XEP-0045 §10.1). With --reserved the room is created locked so the owner can configure it via /setmodes / /affiliation / /destroy before letting anyone in. Without --reserved the room is unlocked with server defaults (instant room) as soon as the server signals status 201 |
/kick <nick> [reason] |
Kick a user from the MUC (requires moderator role) |
/ban <jid> [reason] |
Ban a user by JID (requires admin/owner role) |
/voice <nick> [reason] |
Grant voice in a moderated room (role=participant; moderator) |
/devoice <nick> [reason] |
Revoke voice (role=visitor; moderator) |
/op <nick> [reason] |
Grant moderator role (admin/owner) |
/deop <nick> [reason] |
Revoke moderator role back to participant (not a kick) |
/affiliation list [owner|admin|member|outcast] |
Query affiliation list (default: member) |
/affiliation set <jid> <aff> [--nick <nick>] [reason] [--confirm] |
Change affiliation; --nick sets or unsets (empty) reserved member nick |
/mucregister query |
Show room registration / reserved-nick info (XEP-0045 §15) |
/mucregister [nick] |
Register with the room using the given nick |
/invite [--mediated] <jid> [reason] |
Invite a user (direct XEP-0249 by default; --mediated for XEP-0045 §7.8.2) |
/decline [room inviter [reason]] |
Decline a pending mediated MUC invitation (XEP-0045 §7.8.2) |
/topic [text] |
Set or clear the room topic |
/nick [newnick] |
Change your nickname in the current MUC |
/names |
List all known occupants in the current MUC with IRC-style role/affiliation prefixes (same symbols as the nicklist; sorted by rank then nick) |
/modes |
Display the MUC room modes and metadata (XEP-0045 §6.4/6.5). The mode flags alone also appear in the buffer's status-bar modes slot IRC-style (e.g. +miP for a moderated, members-only, persistent room) — automatically updated on join and on status-104 config-change notifications |
/setmodes [+/-][m][i][k][p][P][N][S] [secret] [--confirm] |
Set/clear room mode flags (XEP-0045 §10.2, owner-only). Without --confirm prints the planned diff |
/destroy [<reason> [<alt-jid> [<alt-password>]]] [--confirm] |
Destroy the current MUC room (XEP-0045 §10.7, owner-only). Irreversible — use --confirm to apply |
Each nick in a MUC room displays a prefix indicating their role or affiliation (XEP-0045). Affiliation takes precedence over role when both apply.
| Prefix | XEP-0045 role/affiliation | Meaning |
|---|---|---|
~ |
affiliation: owner | Room owner — full control |
& |
affiliation: admin | Administrator — can grant/revoke roles |
@ |
role: moderator | Can kick and mute participants |
% |
affiliation: member | Registered member (voice in members-only rooms) |
+ |
role: participant | Can send messages (standard occupant) |
? |
role: visitor | Read-only in a moderated room |
! |
affiliation: outcast | Banned from the room |
. |
(none) | No role or affiliation set yet |
| Command | Description |
|---|---|
/block <jid> [...] |
Block one or more JIDs (XEP-0191) |
/unblock [jid ...] |
Unblock JIDs, or all if no argument given |
/blocklist |
List all blocked JIDs |
Note: OMEMO for non-anonymous MUC rooms (XEP-0384 §5.8 multi-recipient) is
implemented but experimental and lightly tested. Use at your own risk. See
docs/planning-muc-omemo.md for architecture and status. PM OMEMO remains the
primary tested path.
MUC requirements: The room must be non-anonymous — every occupant's real
bare JID must be visible (check with /modes; N in the mode string). OMEMO is
refused in semi-anonymous or fully anonymous rooms.
MUC prefetch: When OMEMO is enabled in an eligible MUC, device lists and
bundles for occupants are fetched in the background so the first encrypted message
can be sent once the bar leaves 🔒OMEMO (pending). Passive prefetch establishes
Signal sessions quietly; it does not send key-transport groupchat stanzas into
the room (avoiding spurious undecryptable messages for strangers). Key-transport
is sent only when explicitly needed — e.g. /omemo kex or decrypt recovery after
you have exchanged encrypted traffic with that contact.
Trust model: This plugin uses Blind Trust Before Verification (BTBV) TOFU, matching Gajim's default behaviour. Trust levels are stored per {jid, device_id} in LMDB:
| Level | Name | Meaning |
|---|---|---|
BLIND |
Auto-trusted | First device seen for this JID (default) |
VERIFIED |
Manually verified | User ran /omemo trust <jid> [device-id] |
UNTRUSTED |
Explicitly distrusted | User ran /omemo distrust <jid> [device-id]; device is excluded from encryption |
UNDECIDED |
New device | A new device for a JID that already has VERIFIED or UNTRUSTED keys |
Only BLIND and VERIFIED devices receive encrypted key material. UNTRUSTED devices are silently skipped. When you enable OMEMO in a MUC, all occupant devices default to BLIND trust — verify important contacts with /omemo trust if desired.
| Command | Description |
|---|---|
/omemo |
Enable OMEMO for the current buffer. Works for both PMs and non-anonymous MUCs (MUC OMEMO support is experimental and untested — see planning doc). |
/omemo check |
Verify OMEMO bundle is published |
/omemo republish |
Republish legacy OMEMO bundle nodes (axolotl namespace) |
/omemo status |
Show device ID and status |
/omemo reset-keys |
Reset key database (forces renegotiation) |
/omemo fetch [jid] [device-id] |
Force devicelist/bundle refresh |
/omemo kex [jid] [device-id] |
Force key transport now |
/omemo fingerprint [jid] |
Show colon-hex fingerprint(s) with BTBV trust status ([BLIND]/[VERIFIED]/[UNTRUSTED]/[UNDECIDED]) |
/omemo devices <jid> |
List known OMEMO devices for a JID |
/omemo trust <jid> [device-id] |
Mark key(s) as VERIFIED (manual trust) |
/omemo distrust <jid> [device-id] |
Mark key(s) as UNTRUSTED (blocks encryption to that device) |
/pgp [keyid|status|reset] |
Manage PGP encryption |
/plain |
Disable encryption (use plaintext) |
/upload [filename] # interactive picker if no filename given
Uploads a file via HTTP File Upload (XEP-0363) and announces it in the current channel using a three-layer stanza for maximum client compatibility (implemented with the fluent stanza builder per project rules for XEP support):
- XEP-0447 Stateless File Sharing (
urn:xmpp:sfs:0,disposition='inline') — used by Conversations ≥ 2.10, Dino, and Gajim to display inline image previews without the user having to click a link. Includes XEP-0446<file>(media-type, name, size, sha-256 hash, width/height for images) + sources. - XEP-0385 SIMS (
urn:xmpp:sims:1) — older inline media sharing, understood by clients that pre-date XEP-0447. - XEP-0066 OOB (
jabber:x:oob) — plain URL fallback; renders as a clickable link in any client that does not understand the above.
For OMEMO-enabled channels the file is AES-256-GCM encrypted before upload (XEP-0448
ESFS); the stanza carries the <encrypted> block with b64 key/iv + cipher hash and
the visible body uses the aesgcm://...#ivkey convention so supporting clients can
decrypt. The outer <file> metadata always describes the original plaintext.
For JPEG and PNG images the plugin automatically detects <width> and <height>
from the file's binary headers (JPEG SOF markers, PNG IHDR chunk) and includes
them in the XEP-0446 <file> element so receiving clients can pre-size preview
boxes before the image finishes downloading.
Incoming XEP-0447 file-sharing stanzas sent by other clients are also parsed and displayed, deduplicated against any SIMS or OOB element for the same URL so the file appears only once per message.
XEP-0231 Bits of Binary (small images, plaintext only): On channels without
OMEMO, /upload on an image/* file of 8 KiB or less is sent as BoB instead
of HTTP upload (Movim sticker interop). The message carries XHTML-IM
<img src='cid:sha1+…@bob.xmpp.org'/>; payloads of 1 KiB or less also include
inline <data xmlns='urn:xmpp:bob'/>, and larger ones are IQ-hosted from
bob_hosted when peers fetch the cid. The plugin advertises urn:xmpp:bob in
entity capabilities. OMEMO-enabled channels still use HTTP upload with XEP-0448
ESFS for images — outbound BoB inside encrypted messages is not implemented.
The weechat-icat script is vendored in scripts/icat.py (built from
https://github.com/trygveaa/weechat-icat). Enabling xmpp.look.icat causes the
plugin to automatically display received images inline using the Kitty graphics
protocol:
- Outgoing uploads — the local file is shown via
/icatimmediately after the upload completes and the sharing link is posted (HTTP upload or XEP-0231 BoB). - Incoming SFS / SIMS / OOB — unencrypted image URLs are passed to
/icatwhen the message is received (including MAM replay). - Incoming encrypted uploads (XEP-0448 ESFS) — after the file is decrypted and
saved to
~/Downloads/xmpp/<jid>/<date>/,/icatis invoked on the local path. - XEP-0449 stickers —
<sticker xmlns='urn:xmpp:stickers:0'/>with sibling SFS image payloads; the[File: …]suffix is suppressed when icat displays the image. - XEP-0514 custom emoji —
<emoji xmlns='urn:xmpp:markup:emoji:0'/>spans in XEP-0394 markup resolved against sibling SFS/SIMS file hashes. - XEP-0231 BoB (Movim stickers) — XHTML-IM
<img src='cid:…@bob.xmpp.org'/>references are IQ-fetched from the sender, cached under~/.local/share/weechat/xmpp/bob_cache/<account>/, and displayed inline (the[Sticker]placeholder is not shown when icat is enabled).
Only image MIME types (image/*) trigger icat. Other file types are announced
normally without inline display.
Note: The plugin passes -print_immediately to icat so placeholder lines are
printed synchronously, directly under the message that shared the image. Kitty
terminals correctly scroll these image cells together with the buffer text.
During MAM replay, image URLs are never passed directly to icat (async HTTP downloads would land out of order). Instead the plugin resolves each image to a local file first — LMDB cache hit, synchronous download, or synchronous ESFS decrypt — then invokes icat on that path immediately after the message line. Live delivery still uses icat's async URL fetch, but also caches downloaded paths for faster MAM replay on reconnect.
Setup:
cp scripts/icat.py ~/.local/share/weechat/python/autoload/Inside WeeChat:
/script load icat.py
/set xmpp.look.icat on
Requires a terminal that supports the Kitty graphics protocol (e.g. Kitty, WezTerm, or foot).
Also requires Python PIL/Pillow (pip install Pillow or python-pillow package).
/mam [days] # fetch history (default: 7 days)
/mam prefs # show MAM preferences (XEP-0441)
/mam prefs default <always|never|roster> # set default archiving policy
/mam prefs always <jid> # add JID to always-archive list
/mam prefs never <jid> # add JID to never-archive list
| Command | Description |
|---|---|
/disco [jid] |
Discover services and features (XEP-0030) |
/adhoc <jid> [node] [id] [field=value ...] |
Execute ad-hoc commands (XEP-0050) |
/roster |
Display contact list |
/roster add <jid> [name] |
Add a contact |
/roster del <jid> |
Remove a contact |
/list [keywords] |
Search public MUC rooms (XEP-0433) |
/feed |
Fetch subscriptions from all auto-discovered PubSub services (XEP-0060) |
/feed close |
Close all open feed buffers (does not unsubscribe) |
/feed discover |
List auto-discovered PubSub services |
/feed discover --all |
Fetch every node from every discovered service |
/feed <service-jid> |
Fetch all subscribed nodes on a service |
/feed <service-jid> --all |
Discover and fetch all nodes via disco#items |
/feed <service-jid> <node> |
Fetch a specific node into a dedicated buffer |
/feed ... --limit N |
Override the per-node item limit (default: 20) |
/feed ... --before <id> |
Fetch items older than <id> (XEP-0059 RSM paging) |
/feed ... --latest |
Clear saved RSM cursor; return to the newest page |
/feed subscribe <service> <node> |
Subscribe to a PubSub node |
/feed unsubscribe <service> <node> |
Unsubscribe from a PubSub node |
/feed subscriptions <service> |
List subscribed nodes on a service |
/feed post <service> <node> [--open] [--title <t>] <text> |
Publish a microblog Atom entry (XEP-0472); --title sets Atom <title> |
/feed post [--open] [--title <t>] <text> |
Short form: post from a feed buffer (service/node inferred) |
/feed post --edit |
Open $EDITOR via feed_compose.py; YAML frontmatter for optional title |
/feed post -- <text> |
-- separator: body starts with JID-like word or URL |
/feed reply <service> <node> <item-id|#N> <text> |
Reply with thr:in-reply-to threading (no title) |
/feed reply #N <text> |
Short form reply using item alias |
/feed reply #N --edit |
Compose reply in $EDITOR via feed_compose.py (no frontmatter) |
/feed repeat <service> <node> <item-id> [comment] |
Boost/repeat a post (XEP-0472 §4.5) |
/feed repeat #N [comment] |
Short form boost using item alias |
/feed retract <service> <node> <item-id> |
Retract (delete) a published post |
/feed retract #N |
Short form retract using item alias |
/feed comments <service> <node> <item-id|#N> |
Fetch comments node for a post (XEP-0277) |
/feed comments #N |
Short form fetch comments using item alias |
/bookmark |
List bookmarks |
/bookmark add [jid] [name] |
Add a bookmark |
/bookmark del <jid> |
Remove a bookmark |
/bookmark autojoin <jid> <on|off> |
Toggle autojoin |
Rooms with autojoin enabled are joined in the background on connect (no buffer
switch). Use /enter or /join manually to join and switch to the room buffer.
| Command | Description |
|---|---|
/ping [jid] |
Send XMPP ping (XEP-0199) |
/mood [mood [text]] |
Publish mood via PEP (XEP-0107) |
/activity [category[/specific] [text]] |
Publish activity via PEP (XEP-0108) |
/xml <stanza> |
Send raw XML (advanced/debug) |
/xmpp |
Show plugin version |
/trap |
Trigger debug breakpoint (developers only) |
Several commands open an in-buffer interactive picker when invoked without arguments. Picker key bindings:
| Key | Action |
|---|---|
↑ / ↓ |
Navigate up/down |
Enter |
Confirm selection |
q / Esc |
Cancel and return to previous buffer |
Three complementary mechanisms are available for diagnosing protocol issues. All are opt-in and off by default so normal users see no extra noise.
Routes internal protocol messages (PEP events, avatar updates, vCard
auto-fetches, OMEMO device lists and session bootstrap, stream management,
client state, upload service discovery) to a dedicated xmpp.debug buffer
(xmpp.debug in WeeChat buffer notation) instead of cluttering account
buffers.
/set xmpp.look.debug on
The buffer is created lazily on first use. Each line carries a dim
[file:line] source prefix so you can trace back to the exact code path.
To jump to the debug buffer:
/buffer xmpp.debug
To turn it off again (messages stop appearing; buffer remains open):
/set xmpp.look.debug off
Appends every inbound (RECV) and outbound (SEND) XML stanza to a
per-account log file on disk. Useful when you need the full wire-level picture
for protocol analysis or when filing bug reports.
/set xmpp.look.raw_xml_log on
Log files are written to:
~/.local/share/weechat/xmpp/raw_xml_<account>.log
Each entry is formatted as:
[YYYY-MM-DD HH:MM:SS] SEND|RECV <stanza-name>
<full xml text>
Turn off to stop writing (existing log file is kept):
/set xmpp.look.raw_xml_log off
Controls whether PubSub microblog feed buffers (/feed, XEP-0060 / XEP-0472) are
enabled. On by default.
/set xmpp.look.feeds off # disable feed buffers and /feed (except /feed close)
/set xmpp.look.feeds on # re-enable (default)
See Microblogging — /feed for details.
When diagnosing OMEMO key transport or session bootstrap issues, the
correlate_omemo_xml.sh helper cross-references WeeChat log events with raw
XML stanzas so you can see what the plugin received at the exact moment an
error occurred:
tools/correlate_omemo_xml.sh --account <account>This is most useful when xmpp.look.raw_xml_log is also enabled, since the
helper reads from raw_xml_<account>.log.
Optional Python scripts live in scripts/. They are not loaded
automatically — install the ones you want by hand.
Opens a temporary Markdown file in your editor. For posts the file
includes a YAML frontmatter block with an optional title: field — fill it in
to set the Atom <title> headline, or leave it blank for a body-only post.
For replies and when run from a comments buffer the frontmatter is
omitted automatically (comments carry no Atom title). On save the content is
placed in the WeeChat input bar as a /feed post … or /feed reply … command
ready to review and send.
The easiest way to invoke it is with the --edit flag:
/feed post --edit # new post in $EDITOR
/feed reply #3 --edit # reply in $EDITOR
Or install and invoke directly:
cp scripts/feed_compose.py ~/.local/share/weechat/python/autoload/Inside WeeChat:
/alias add fc /feed-compose
/key bind meta-e /feed-compose
See scripts/README.md for full configuration options.
Displays shared images inline using the Kitty graphics protocol. Vendored from
https://github.com/trygveaa/weechat-icat (MIT license). Used automatically
when xmpp.look.icat is enabled.
Requires Python PIL/Pillow (pip install Pillow or python-pillow package).
cp scripts/icat.py ~/.local/share/weechat/python/autoload/Pull requests and issues are welcome. See the
Contributing wiki page and
AGENTS.md for architecture and style guidance.
- C++23 throughout — match existing style in the file you edit.
- Port abstraction — use
xmpp::StanzaViewfor inbound stanzas, fluentstanza::specbuilders for outbound stanzas, andweechat::UiPort/BufferPort/LineStorePortfor WeeChat output. Rawxmpp_stanza_get_*andweechat_printfbelong only in hook/adapter glue. - Tests — run
make DEBUG=1ormake test(123 doctests) after changes; manual WeeChat testing for integration behaviour. - Releases — see Releasing wiki;
pushing a
v*tag triggers GitHub Actions to build and attach packages.
The official Xepher MUC is the place to ask questions, report usage issues that don't belong in the GitHub issue tracker, share tips, and follow announcements:
- JID:
xepher@conference.hackerheaven.org - Web link: xmpp:xepher@conference.hackerheaven.org?join
You can join with the plugin itself once any account is connected:
/xmpp enter xepher@conference.hackerheaven.orgOr from any other XMPP client (Conversations, Gajim, Dino, Monal, etc.) using the JID above.
- ✅ XEP-0030: Service Discovery
- ✅ XEP-0045: Multi-User Chat —
/create, IRC-style admin (/kick,/ban,/voice,/devoice,/op,/deop), owner config (/setmodes,/affiliation,/destroy), registration (/mucregister), direct and mediated invites (/invite,/decline); no full interactive roomconfig UI - ✅ XEP-0054: vcard-temp (retrieval via
/whois, publishing via/setvcard) - ✅ XEP-0077: In-Band Registration (
/account register,unregister,password) - ✅ XEP-0115: Entity Capabilities (persistent caching)
- ✅ XEP-0163: Personal Eventing Protocol
- ✅ XEP-0191: Blocking Command
- ✅ XEP-0198: Stream Management — negotiates SM before application stanzas; session resume with stanza retransmit; resume failure falls back to fresh
<enable/>; on resume skips redundant roster/presence/MAM/feed fetches; honors server<enabled location='…'/>for reconnect; closes stream on invalid peer ack (handled-count-too-high); graceful final ack before disconnect
- ✅ XEP-0245: The
/meCommand - ✅ XEP-0249: Direct MUC Invitations
- ✅ XEP-0308: Last Message Correction
- ✅ XEP-0363: HTTP File Upload
- ✅ XEP-0393: Message Styling
- ✅ XEP-0410: MUC Self-Ping
- ✅ XEP-0424: Message Retraction
- ✅ XEP-0425: Message Moderation
- ✅ XEP-0444: Message Reactions
- ✅ XEP-0461: Message Replies
- ✅ XEP-0004: Data Forms (rendered in-buffer for Ad-Hoc Commands)
- ✅ XEP-0048: Bookmark Storage (Private XML)
- ✅ XEP-0049: Private XML Storage
- ✅ XEP-0050: Ad-Hoc Commands
- ✅ XEP-0059: Result Set Management (MAM paging)
- ✅ XEP-0066: Out of Band Data
- ✅ XEP-0071: XHTML-IM (bold, italic, underline, code, blockquotes, links, CSS colors)
- ✅ XEP-0085: Chat State Notifications (all 5 states)
- ✅ XEP-0092: Software Version
- ✅ XEP-0107: User Mood
- ✅ XEP-0108: User Activity
- ✅ XEP-0153: vCard-Based Avatars (receive; publishing not yet implemented)
- ✅ XEP-0172: User Nickname
- ✅ XEP-0184: Message Delivery Receipts
- ✅ XEP-0199: XMPP Ping
- ✅ XEP-0202: Entity Time
- ✅ XEP-0203: Delayed Delivery
- ✅ XEP-0223: Persistent Storage of Private Data via PubSub
- ✅ XEP-0224: Attention
- ✅ XEP-0280: Message Carbons
- ✅ XEP-0283: Moved (account migration notices)
- ✅ XEP-0292: vCard4 Over XMPP (fetch via
/whois; no publish support yet) - ✅ XEP-0297: Forwarded Messages
- ✅ XEP-0300: Cryptographic Hash Functions
- ✅ XEP-0313: Message Archive Management (with LMDB caching)
- ✅ XEP-0319: Last User Interaction in Presence
- ✅ XEP-0333: Chat Markers
- ✅ XEP-0334: Message Processing Hints
- ✅ XEP-0352: Client State Indication
- ✅ XEP-0359: Unique and Stable Stanza IDs
- ✅ XEP-0372: References
- ✅ XEP-0380: Explicit Message Encryption
- ✅ XEP-0382: Spoiler Messages
- ✅ XEP-0384: OMEMO Encryption (legacy axolotl namespace
eu.siacs.conversations.axolotlonly — OMEMO:2 /urn:xmpp:omemo:2is not supported; BTBV trust model with per-device LMDB trust store; random pre-key selection; own-device encryption for carbon-copy and self-message decryption; pre-key ID continuity across signed pre-key rotation; stale-session recovery via MAM bundle re-fetch) - ✅ XEP-0385: Stateless Inline Media Sharing (SIMS
<reference uri>extraction fixed forurn:xmpp:reference:0sources) - ✅ XEP-0392: Consistent Color Generation
- ✅ XEP-0402: PEP Native Bookmarks
- ✅ XEP-0422: Message Fastening
- ✅ XEP-0428: Fallback Indication
- ✅ XEP-0437: Room Activity Indicators (Deferred — subscribe via
<rai xmlns='urn:xmpp:rai:0'/>presence to own bare JID on connect; incoming<activity>notifications displayed in account buffer) - ✅ XEP-0446: File Metadata Element (image dimensions sent with uploads)
- ✅ XEP-0447: Stateless File Sharing (inline previews for Conversations/Dino/Gajim)
- ⚡ XEP-0231: Bits of Binary (Experimental — receive: inline
<data xmlns='urn:xmpp:bob'/>and XHTML-IMcid:…@bob.xmpp.orgimage refs; IQ-fetch uncached payloads; local cache + weechat-icat; send: plaintext/uploadof images ≤8 KiB as BoB + XHTML-IM with sha1 cid, inline data ≤1 KiB, IQ-get hosting;urn:xmpp:bobin caps; OMEMO outbound BoB not implemented) - ⚡ XEP-0449: Stickers (Experimental — receive:
<sticker xmlns='urn:xmpp:stickers:0'/>with SFS images; inline via weechat-icat; sticker pack pubsub not implemented) - ⚡ XEP-0514: Emoji Markup (Experimental — receive: custom emoji spans in XEP-0394 markup resolved against sibling SFS/SIMS hashes; inline via weechat-icat)
- ✅ XEP-0490: Message Displayed Synchronization
- ✅ XEP-0511: Link Metadata (incoming previews + outgoing OpenGraph)
- ⚡ XEP-0277: Microblogging over XMPP (Deferred — publish/reply/retract via
/feed post|reply|retract; receive PEP microblog push events; Atom metadata: title, author, categories, enclosures, geolocation, replies links;/feed commentsfetches comments nodes) - ⚡ XEP-0394: Message Markup (Experimental — receive-only:
<markup xmlns='urn:xmpp:markup:0'>parsed and rendered to WeeChat colour codes;<span emphasis>→ italic,<span strong>→ bold,<span code>→ cyan,<span deleted>→ grey,<bcode>→ grey block,<bquote>→ green-prefixed lines,<list>/<li>→ bullet markers; takes precedence over XEP-0393 when present; advertised in caps) - ⚡ XEP-0413: Order-By for MAM (Experimental —
urn:xmpp:order-by:1 field='creation-date'included in XEP-0442 pubsub MAM queries for newest-first ordering; advertised in caps) - ⚡ XEP-0442: Pubsub MAM (Experimental — on reconnect, disco#info probes each pubsub service; if
urn:xmpp:mam:2is supported, fetches feed history via MAM withnode=filter and XEP-0413 Order-By; falls back to XEP-0060max_itemsfor servers without pubsub MAM support; Atom entries extracted from forwarded MAM result messages and rendered to the feed buffer with dedup and alias assignment; RSM cursor persisted to LMDB) - ⚡ XEP-0452: MUC Mention Notifications (Experimental — receive side:
<addresses type='mentioned'>notification messages from MUC service detected and forwarded message body rendered to the MUC buffer with highlight, so missed @mentions surface even when not present in the room) - ⚡ XEP-0441: MAM Preferences (Experimental —
/mam prefsdisplays current server default policy and always/never JID lists;/mam prefs default <always|never|roster>sets default;/mam prefs always <jid>//mam prefs never <jid>add JIDs to the respective list) - ⚡ XEP-0466: Ephemeral Messages (Experimental — send:
/ephemeral <seconds> <message>attaches<ephemeral timer='N'/>+<no-permanent-store/>hint; receive: timer value displayed as[⏱ Ns]prefix, message automatically tombstoned after N seconds;urn:xmpp:ephemeral:0advertised in caps) - ⚡ XEP-0492: Chat Notification Settings (Experimental — per-chat notification preference (
always/on-mention/never) stored in XEP-0402 bookmark<extensions><notify>;/notify [<jid>] [always|on-mention|never]gets or sets the preference and re-publishes the bookmark) - ⚡ XEP-0448: Encrypted File Sharing (Experimental — send: when
/upload-ing a file to an OMEMO-enabled channel, the file is AES-256-GCM encrypted before HTTP PUT; the XMPP message carries<file-sharing>with<encrypted xmlns='urn:xmpp:esfs:0' cipher='urn:xmpp:ciphers:aes-256-gcm-nopadding:0'>containing the base64 key/IV/hash; receive:<encrypted xmlns='urn:xmpp:esfs:0'>detected inside SFS<sources>, cipher attribute validated againsturn:xmpp:ciphers:aes-256-gcm-nopadding:0(other ciphers skipped per §4), ciphertext downloaded in a background thread, decrypted with AES-256-GCM, saved to~/Downloads/<filename>;urn:xmpp:esfs:0advertised in caps) - ⚡ XEP-0472: Pubsub Social Feed (Experimental — publishes
pubsub#type=urn:xmpp:microblog:0, advertisesurn:xmpp:pubsub-social-feed:1in caps;thr:in-reply-to@refuses real Atom entry IRI; feed-level<feed>metadata items rendered; XHTML/HTML Atom content properly rendered) - ⚡ XEP-0433: Extended Channel Search (Searcher role; Search Service role not implemented)
- ⏳ XEP-0153: vCard-Based Avatars (publishing own avatar)
- ⏳ XEP-0398: Avatar Conversion
Known limitation: Plugin reload while WeeChat is running is not supported due to fundamental race conditions with timer hooks. Always restart WeeChat instead of reloading the plugin.
Licensed under the Mozilla Public License 2.0.
See LICENSE or https://www.mozilla.org/en-US/MPL/2.0/
Original project © Tony Olagbaiye — https://github.com/bqv/weechat-xmpp
