Skip to content
rcq-messengerPublic

About

Terminal client for RCQ — the same end-to-end encryption as the phone and desktop clients (libsignal, sealed sender), driven from a shell or script. One Node bundle, no GUI, registers as a secondary device of your account. AGPL-3.0.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

8 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 

Repository files navigation

rcq: the RCQ console client

A terminal client for RCQ, driven from a shell. No app store, no browser, no GUI. Runs anywhere Node 22+ runs: a laptop, a VPS, a Raspberry Pi.

The crypto is the real thing, shared with the phone, web and desktop clients: libsignal v=2 with sealed sender, per-device fan-out, sender-key group broadcasts. The client is smaller than they are, and the Known gaps at the bottom say exactly where.

It registers as a secondary device of your account: your phone keeps the primary slot, and every device gets its own copy of each 1:1 message.

Install

Download and unpack the latest release:

curl -sL https://github.com/rcq-messenger/rcq-cli/releases/latest/download/rcq.tar.gz | tar xz
./rcq/rcq --help

Optional, to make it a real command:

sudo ln -sf "$PWD/rcq/rcq" /usr/local/bin/rcq

First five minutes

rcq register --nick alice     # prints your UIN and the 24-word phrase, WRITE IT DOWN
rcq                           # and you are chatting

Bare rcq is the client. It opens on your most recent conversations, prints incoming messages as they arrive, and sends whatever you type to whoever the prompt names:

  #396    Ivan (#396)            07:22:36  see you at ten
  g21     [Работа]               06:41:36  you: will look tonight
rcq> /to 396
[07:22:36] Ivan (#396): see you at ten
Ivan (#396)> on my way
[07:31:02] me -> Ivan (#396): on my way
[07:31:03] ✓ delivered to Ivan (#396): on my way

To reach somebody new: rcq find "name" or rcq who <uin> to see who a number belongs to, /add <uin> to ask them into your contacts, /accept <uin> when somebody asks you. Writing to a person who is neither a contact nor anybody you have written to is confirmed once first: the mailbox is open by design, hitting a stranger by typo is not.

/help lists everything: rooms (/g), history (/log, /recent), requests, blocking, /quit. Up-arrow walks back through the commands you have typed. Ctrl+C on a half-typed line drops the line; on an empty line it leaves, and so does Ctrl+D.

Commands

Start here, the bare command IS the client:

rcq                                         the conversation: live incoming + a prompt that sends
rcq register [--nick NAME] [--island URL]   create an account
rcq restore "<24 words>" [--island URL]     restore an account from its phrase

For scripts and one-shots:

rcq whoami                                  uin, nickname, island, device id
rcq contacts                                list contacts
rcq who <uin> | rcq find "NAME"             who is this number, or who is called that
rcq add <uin>                               send a contact request
rcq requests | accept <uin> | decline <uin> | cancel <uin>
rcq block <uin> | unblock <uin> | remove <uin> [--yes]
rcq groups | join <id>                      your rooms, and joining an open one
rcq log [<uin>|g<id>] [n]                   last n lines of a thread, from the history file
rcq send <uin>|g<id> "text" [--yes]         one-shot: drain, send, wait for the receipt, exit
rcq watch [--groups]                        read-only stream of incoming messages
rcq export                                  history file path and line count
rcq lang [en|ru]                            show or set the language
rcq island trust <host[:port]> <fp> [--replace]   pin an island by its certificate fingerprint
rcq island fingerprint [host]               how an island is trusted, and its address with the fingerprint
rcq island forget <host[:port]>             drop the pin

An island without a certificate authority (the installer's fingerprint mode, or one reachable only by IP) is trusted by the SHA-256 fingerprint of its certificate, like an ssh host key. --island host:port#fingerprint, the address the operator hands out, pins it before the first connection; an island met without one is pinned on first use and the fingerprint is said once on stderr; a certificate that later differs is refused, with both fingerprints and the island trust … --replace line that accepts it, and the command does not run. The flagship is only ever trusted through an authority. A certificate whose SAN does not name the address, or an expired one, cannot be an anchor here even though the phone and desktop apps pin it.

The client speaks English and Russian: unset, it follows LC_ALL/LANG (a ru* locale answers Russian), and rcq lang ru persists the choice in the state dir. Data output for scripts (uin numbers, history lines, whoami values) stays byte-identical in either language.

For the subcommands, stdout carries data only; status goes to stderr, pipes and scripts welcome. Bare rcq on a pipe prints usage instead of hanging: the prompt is for people, send/watch are for scripts. Protocol internals are quiet by default; RCQ_VERBOSE=1 shows them, and NO_COLOR strips colour.

Where things live

State (identity, keys, history) sits in $RCQ_CLI_HOME (default ~/.config/rcq), file mode 0600. The 24-word phrase IS the account: anyone holding it holds the account, and nobody can recover it for you. One rcq process per state dir: a second one refuses to start rather than corrupt the encryption state, which also means the prompt and a one-shot command cannot run at the same time (every verb worth having at a prompt has a /slash of its own). A second account is one RCQ_CLI_HOME=/path away.

Messages you receive and send are appended to history-<uin>.jsonl in that directory, in plaintext. rcq export prints the path. Commands typed at the prompt are remembered for up-arrow in prompt-history; the text of your messages deliberately is not written there.

Known gaps

Real ones, so nothing here is a surprise on the day it matters:

  • No files or photos. Inbound media is announced (kind, name, size) and cannot be downloaded; nothing can be uploaded.
  • Groups: read and post, not administer. Rooms work in both directions, including encrypt-once broadcasts, and you can join an open one by id. Creating, renaming, and moderating a room belong where you can see it.
  • No circumvention. No CDN front, no proxy support, no relay use: on a network that blocks the island's host, this client cannot connect. If you already run your own tunnel, put the whole process behind it.
  • No device management, no burn, no QR link. A second box takes the 24-word phrase on a command line for now.
  • Reactions, edits, deletes and replies are dropped. A message the sender retracts on their phone stays in this client's history file.
  • No cross-island send. Messages from another island do arrive and are labelled #500@other.island so they cannot be mistaken for a local number, but there is no way to answer one from here.
  • No calls, rooms, stories or nearby, and a terminal has no business with them. An incoming call is currently invisible, which it should not be.
  • No typing notifications, deliberately: sending them from a headless box would leak keystroke timing from the client whose whole point is running where nobody is watching.

Build from source

The CLI lives in the web/desktop client repo (one protocol core, several clients); this repo is the distribution point:

git clone https://github.com/rcq-messenger/rcq-desktop
cd rcq-desktop && npm install
npm run cli:build          # -> cli/dist/rcq.mjs
npm run cli:test           # offline v=2 round-trip under Node

Source: https://github.com/rcq-messenger/rcq-desktop/tree/main/cli

AGPL-3.0, like the rest of RCQ.

About

Terminal client for RCQ — the same end-to-end encryption as the phone and desktop clients (libsignal, sealed sender), driven from a shell or script. One Node bundle, no GUI, registers as a secondary device of your account. AGPL-3.0.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors