FAQ - AsamK/signal-cli GitHub Wiki
Every invocation of signal-cli ... starts a Java Virtual Machine instance. This can take anywhere from a second to a long time, depending on the system.
To avoid it, signal-cli can be started as a daemon, with subsequent commands sent to it through DBus. See using dbus-send.
There is a also an experimental native library build using GraalVM that avoids JVM startup. See GraalVM section in README.
Some signal-cli's operations require that enough system entropy / randomness is available.
Available entropy can be monitored with
watch cat /proc/sys/kernel/random/entropy_avail
If it is hitting zero during signal-cli ... execution, signal-cli will block until enough entropy is available.
System entropy is more likely to get depleted on headless servers. There are programs that allow to increase the amount of available entropy, e.g. haveged.
#351 with links to past discussions.
The signal-cli program has a set of options, and each subcommand may have its own options. The correct order is:
signal-cli [SIGNAL-CLI_OPTIONS] [SUBCOMMAND] [SUBCOMMAND_OPTIONS]
So, for example:
$ signal-cli receive --output=json
signal-cli: error: unrecognized arguments: '--output=json'
The --output=... option belongs to the main program, and needs to be in front of the receive subcommand:
$ signal-cli --output=json receive
This is Argparse4j's behavior.
https://github.com/AsamK/signal-cli/issues/1504
See Troubleshooting DBus.
String indexing is required to properly interpret text formatting as well as mentions. Both involve specifying a substring using start and length. The units for string indexing are UTF-16 code units, not Unicode code points! This comes from the Signal protocol and the behavior of Android/Java.
Each Unicode character whose code point is within the Basic Multilingual Plane (that is, whose code point is less than 0x10000) is represented by one UTF-16 code unit. Characters with code point greater or equal to 0x10000 (such as Emoji) are represented by two UTF-16 code units. To illustrate, consider the string 0💩1💩2💩3. This string consists of 7 Unicode code points, but 10 UTF-16 code units (because the emoji U+1F4A9 is beyond the BMP, so each instance counts for two code units). So the following are substrings:
- start: 0, length: 3 -
0💩 - start: 1, length: 3 -
💩1 - start: 2, length: 3 - invalid
For users of programming languages which index strings by Unicode code points (e.g. Python), you will need to carefully convert indices. For example, this Python function properly converts UTF-16 string indices to Unicode indices:
>>> def utf16_to_unicode(string: str, utf16_index: int) -> int:
... for unicode_index, c in enumerate(string):
... if utf16_index <= 0:
... break
... utf16_index -= 2 if ord(c) >= 0x10000 else 1
... if utf16_index < 0:
... raise IndexError("UTF-16 index breaks surrogate pair")
... elif utf16_index > 0:
... raise IndexError("UTF-16 index past end of string")
... else:
... return unicode_index
>>> utf16_to_unicode("0💩1💩2💩3", 0)
0
>>> utf16_to_unicode("0💩1💩2💩3", 9)
6
>>> utf16_to_unicode("0💩1💩2💩3", 1)
1
>>> utf16_to_unicode("0💩1💩2💩3", 2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 7, in utf16_to_unicode
IndexError: UTF-16 index breaks surrogate pair
>>> utf16_to_unicode("0💩1💩2💩3", 3)
2On AARCH64 systems you might need to use GraalVM to generate a system-native binary of signal-cli. Doing this is a quite ressource-heavy process, on a Raspberry Pi CM4l (8GB) it took around 40 minutes using SD card. Some optimizations will need to be done to manage a sucessful build, especially regarding free memory. Without them, the system might get ressource deadlocked and not be able to finish the build in many hours.
i would recommend to set up ZRAM and disabling other very large services for the moment so you'll have more ram for compiling and a faster swap handling. i gave 2GB to zwap (pri 100 per default) plus added a 2GB swapfile (pri -2) just in case. without those steps even 4 hours weren't enough, with the steps it took 38 min. building on a slow sd card.
ZRAM howtos:
Raspbian, English Raspbian, German
- Stop other heavy daemons like EDR or similar for the time of the build. Every free GB counts in that moment.
- If you rather keep them running, it's best to switch to a
deadlineIO scheduler. - If you can, add a swap space on eMMC or an USB/NVMe SSD.
- Enable zSwap in the fast mode, and make a small pseudoswap SSD (I used 2GB, rule of thumb is 25% RAM). leave it at the highest priority (100, it's the default on debian etc.)
- make sure to start it and see if it's activated (
swapon -sor theSwapcolumn intop.) - Add a swapfile of the same size just to be safe in case the swap overflows. If you have multiple swap partitions / -files, use the same (low) priority for them, i.e.
-5Even SD cards will usually scale better for multiple IOs. - Make sure that is also active
- Make sure that you still have 5-10GB of disk space left for the actual build (exact number is not known but it's not a tiny amount)
- download Oracle GraalVM, look for:
graalvm-jdk-25_linux-aarch64_bin.tar.gz - extract to /opt/graalvm-jdk-25.0.3+9.1 symlink to /opt/graalvm-jdk-25
export GRAALVM_HOME=/opt/graalvm-jdk-25 ; export JAVA_HOME=/opt/graalvm-jdk-25- head to the
signal-clisource tree and check out the latest releasegit checkout <commit id> - start the build using
./gradlew nativeCompile[wait 20-90 mins]
then copy the resulting binary to /usr/local/bin:
$ sudo cp ./build/native/nativeCompile/signal-cli /usr/local/bin/ &&
sudo chmod 755 /usr/local/bin/signal-cli
Warning I noticed dropping the library in /usr/local/lib did not work to have it picked up. This is just a deployment detail, the library is fine. The missing steps for this are not clear yet. Please add them if you know what's missing.