Small TUI client for XMPP written in OCaml
  • OCaml 99.5%
  • Dune 0.5%
Find a file
2026-09-03 13:31:08 +02:00
bin v0.5.3: harden transport and improve roster 2026-09-03 13:31:08 +02:00
src v0.5.3: harden transport and improve roster 2026-09-03 13:31:08 +02:00
test v0.5.3: harden transport and improve roster 2026-09-03 13:31:08 +02:00
.gitignore v0.1.0: Giza — minimal terminal XMPP client 2026-07-24 19:50:00 +02:00
dune-project v0.5.3: harden transport and improve roster 2026-09-03 13:31:08 +02:00
giza.opam v0.5.3: harden transport and improve roster 2026-09-03 13:31:08 +02:00
LICENSE v0.1.0: Giza — minimal terminal XMPP client 2026-07-24 19:50:00 +02:00
README.md v0.5.3: harden transport and improve roster 2026-09-03 13:31:08 +02:00

Giza

Giza is a small terminal XMPP client written in OCaml. It handles direct chat, rooms, presence, replies, delivery state, file uploads, and media links without trying to replace a full desktop client.

Current version: 0.5.3

What works

  • STARTTLS on port 5222 and implicit TLS on port 5223
  • X.509 certificate checks against the system CA bundle
  • SASL SCRAM-SHA-1 and PLAIN, with SCRAM server-proof verification
  • Direct messages and multi-user chat
  • Message Carbons, delivery receipts, and chat markers
  • Replies with quoted context
  • Presence, unread counts, and desktop notifications through notify-send
  • A scrolling roster with case-insensitive filtering by name or JID
  • HTTP Upload through curl, restricted to HTTPS upload slots
  • Image, video, and audio links opened with a configured viewer
  • Automatic reconnects and room rejoining

Giza keeps message history in memory for the current process. It does not store chat logs.

Build

Giza needs OCaml 4.14 or newer, opam, and Dune.

opam install . --deps-only --with-test
dune build
dune runtest

Install it into the active opam switch with:

dune install

During development, run the current build directly:

dune exec -- ./bin/main.exe

Configure

Giza reads $XDG_CONFIG_HOME/giza/config, or ~/.config/giza/config when XDG_CONFIG_HOME is unset. The file contains one key = value per line. Blank lines and lines beginning with # are ignored.

jid = you@example.org
nick = you
host = xmpp.example.org
port = 5222
image_viewer = swayimg
video_viewer = mpv
audio_viewer = mpv
upload_service = upload.example.org

Only jid is normally required. The JID domain supplies the default host, nick defaults to the JID localpart, and viewers default to xdg-open. Viewer settings must name an executable, not a shell command.

The password is requested at startup with terminal echo disabled. Giza does not write it to disk or pass it on the command line.

Run

giza

Useful options:

Option Meaning
--user user@example.org Override the configured JID
--host xmpp.example.org Override the connection host and TLS name
--port 5222 Override the port
--starttls Use STARTTLS, which is the default
--implicit Use TLS from the first byte
--room room@conference.example.org Join and save a room at startup
--nick name Override the room nickname
--ca-bundle path Use another PEM CA bundle
--insecure Disable certificate verification

--insecure permits a man-in-the-middle attack. It is meant for temporary testing, not routine use.

Use the interface

Giza starts in normal mode. Press i to enter insert mode and type a message.

Key Action
i Enter insert mode
Esc Leave insert mode, clear a filter, or quit from normal mode
j / k Move through messages
J / K Move through contacts and rooms
/ Filter contacts and rooms by name or JID
Enter Keep the current filter
o Open media from the selected message
r Reply to the selected message
Tab Complete a room nickname or a path after /send

Commands are entered in insert mode:

Command Action
/join room@service [nick] Join and save a room
/part Leave the current room and remove it from saved rooms
/approve jid Approve a presence subscription
/deny jid Deny a presence subscription
/send /path/to/file Upload a file and send its URL
/help Show the command summary
/quit Quit

Saved rooms

Joined rooms and their nicknames live beside the main config in rooms. Giza writes this file after /join and /part, loads it at startup, and uses it again after reconnecting. Existing rooms = ... entries in the main config migrate to this file on first run.

External tools

curl is required for file uploads and opening media links. Desktop notifications need notify-send. Media opening also needs the configured viewer, such as xdg-open, mpv, or swayimg.

Giza starts these programs directly with argument arrays. It does not pass message text, URLs, filenames, or server-provided headers through a shell.

Limits

  • No Message Archive Management, so old server-side history is not loaded
  • No OMEMO encryption
  • One account per process
  • No service discovery for finding an upload component

License

AGPL-3.0-or-later. See LICENSE.