Introduction
Welcome to the gomuks docs!
Discussion
Matrix room: #gomuks:maunium.net
Installation
Installing a package
The releases on GitHub contain binaries and debian packages: https://github.com/tulir/gomuks/releases
GitLab CI builds binaries for each commit: https://mau.dev/tulir/gomuks/-/pipelines (currently available for linux/amd64, linux/arm, linux/arm64, darwin/amd64, darwin/arm64).
The release and CI binaries for Linux are statically built and have no
dependencies at all. The binaries for macOS require installing libolm, either
with brew install libolm
or by placing libolm.3.dylib
from the CI in the
same directory as the gomuks
binary.
Direct links to latest CI binaries:
- gomuks legacy: linux/amd64, linux/arm64, linux/arm, macos/arm64
- gomuks web: linux/amd64, linux/arm64, linux/arm, macos/arm64
There are also community maintained packages for several distributions (gomuks legacy only). If you've made a new distro package, please add it to the list below.
- Arch Linux (AUR): gomuks, gomuks-bin, and gomuks-git
- NixOS: gomuks
- OpenSUSE (OBS): home:albino:matrix/gomuks
- Alpine Linux: gomuks
- Debian: gomuks
- macOS (Homebrew Tap): aaronraimist/tap/gomuks
- macOS (MacPorts): gomuks
Compiling from source
- Install Go 1.21 or higher.
- If you want end-to-end encryption, also install
libolm-dev
. - If you don't want encryption, disable CGO with
export CGO_ENABLED=0
. - gomuks web requires Go 1.23 or higher and does not support disabling encryption.
- Compiling the frontend for gomuks web also requires the latest LTS of Node.js or higher (currently v20).
- If you want end-to-end encryption, also install
- Clone the repo:
git clone https://github.com/tulir/gomuks.git && cd gomuks
- To get gomuks web, run
git checkout webmuks
after cd.
- To get gomuks web, run
- Build:
./build.sh
(build.sh will simply call go build with some additional flags).
Simply pull changes (git pull
) and run ./build.sh
again to update.
Common compilation issues
fatal error: olm/olm.h: No such file or directory
means you forgot to install libolm-dev, or that you installed it in a weird place which isn't in your default library lookup path.- In the latter case, set the
LIBRARY_PATH
andCPATH
environment variables, e.g.export LIBRARY_PATH=/usr/local/lib CPATH=/usr/local/include
.
- In the latter case, set the
fatal error: olm/pk.h: No such file or directory
means you installed libolm2 instead of libolm3.cgo: C compiler "gcc" not found: exec: "gcc": executable file not found in $PATH
means you forgot to install C/C++ compilers.//go:build comment without // +build comment
means your Go version is slightly outdated.cannot load embed: malformed module path "embed"
orpackage embed is not in GOROOT
means your Go version is very outdated.cannot find package "maunium.net/go/gomuks/..." in any of:
usually means your Go version is extremely outdated.
Docker (gomuks web)
The backend for gomuks web can also run in Docker. Docker images are available
at dock.mau.dev/tulir/gomuks
.
Keep in mind that the backend has all your encryption keys, which means it must be ran in a secure location.
FAQ
N.B. These only apply to gomuks legacy unless otherwise noted.
How do I verify the gomuks session?
To self-sign the device using your security key, use /cs fetch
, enter your
security key in the dialog that appears, then use /cs self-sign
.
Alternatively, find yourself in the user list on Element Web or Desktop, click
on "X sessions", click on the gomuks session and use "Manually verify by text",
then compare the fingerprint to what gomuks outputs with the /fingerprint
command. Note that the text verification option is not available in the
security & privacy settings, it's only in the right panel user list.
Why are old messages undecryptable?
gomuks currently doesn't support key backup and doesn't request keys
automatically, so only messages sent after initial login will be decryptable.
To see older messages, export keys to file from another client and use the
/import
command. After importing keys, you need to clear cache to have gomuks
retry decrypting old messages.
How do I use a proxy?
Go's HTTP library reads the https_proxy
environment variable by default
(see https://pkg.go.dev/net/http#ProxyFromEnvironment for more info).
How do I copy text from gomuks?
Most terminals allow selecting text even when mouse mode is enabled by using
shift+drag. However, that way doesn't work for copying multiline text, so you
may prefer the /copy
command for copying a single message, or
Ctrl+L to enter plaintext mode where you can copy
whatever you want.
Can I use gomuks with multiple accounts?
gomuks currently only supports one account at a time, but you can run multiple instances of gomuks with different data directories. See the entry below for details.
Debug logs
To get debug logs from gomuks, launch it with DEBUG=1
in the environment.
Logs will be stored in ~/.local/state/gomuks
by default. Prior to v0.3.1,
the default path was /tmp/gomuks
. The path can be changed using the DEBUG_DIR
environment variable.
Where does gomuks store data?
By default, data is stored in the default config/cache/data directories using
OS-specific conventions. To store all gomuks data in a custom directory, use
the GOMUKS_ROOT
environment variable.
You can also override individual directories using GOMUKS_THING_HOME
(where
THING
is CONFIG
, DATA
or CACHE
).
- Config contains the main local config file.
- Data contains encryption keys.
- Cache contains things that can be refetched from the server: message history, room state, automatically downloaded files, preferences that are synced to the server, etc.
The default directory for manual file downloads (using the /download
command)
is the same on all systems: $GOMUKS_DOWNLOAD_HOME
, $(xdg-user-dir DOWNLOAD)
,
or $HOME/Downloads
.
Note that the environment variables only take effect before first startup. After first startup, everything except the config path is saved to the config and will be read from there. To move existing gomuks data to a different path, you must change the paths in the config file.
Storage in gomuks web
The GOMUKS_*
environment variables work mostly the same way as gomuks legacy,
with a few exceptions:
- There's no /download command and therefore no DOWNLOAD_HOME
- Data also contains message history and other Matrix state, not only encryption keys (but media is still in cache).
- Logs can be redirected using
GOMUKS_LOG_HOME
instead ofDEBUG_DIR
.
System-specific defaults
These are the base directories for each OS, data will be stored in the gomuks
directory inside each base directory.
*nix
- Config:
$XDG_CONFIG_HOME
or$HOME/.config
- Cache:
$XDG_CACHE_HOME
or$HOME/.cache
- Data:
$XDG_DATA_HOME
or$HOME/.local/share
- Logs:
$XDG_STATE_HOME
or$HOME/.local/state
macOS
- Config & Data:
$HOME/Library/Application Support
- Cache:
$HOME/Library/Caches
- Logs:
$HOME/Library/Logs
Windows
- Config & Data:
%AppData%
- Cache:
%LocalAppData%
- Logs:
%LocalAppData%
Commands
This page only applies to gomuks legacy.
General
/help
- View command list./quit
- Close gomuks./clearcache
- Clear room state and close gomuks./logout
- Log out, clear caches and go back to the login view./fingerprint
- Shows the Device ID and fingerprint, allowing verification of the session./copy [register]
- Copy the selected message to the specified clipboard register (defaults toclipboard
)./toggle <thing>
- Toggle user preferences.rooms
- Room list sidebar.users
- User list sidebar.baremessages
- Bare message mode where the sender name is inline with the messages.images
- Text image rendering.typingnotif
- Outgoing typing notifications.emojis
-:emoji:
conversion when sending messages.html
- HTML input.markdown
- Markdown input.downloads
- Automatic downloads (this will also preventimages
from working).notifications
- Desktop notifications.unverified
- Sending (e2ee keys for) messages to unverified devices. You need to restart gomuks for this setting to take effect.inlineurls
- Inline URLs in text. May not be supported in all terminals. You need to restart gomuks for this setting to take effect.
Media
Tab-completing file paths is supported in all these commands.
/download [path]
- Downloads file from selected message. If path is not specified, it defaults to<download_dir>/<message.body>
.download_dir
defaults to$HOME/Downloads
./open [path]
- Download file from selected message and open it withxdg-open
. If path is not specified, the file will be downloaded to the media cache./upload <path>
- Upload the file at the given path to the current room. Note that to include audio/video file metadata (dimensions and duration), you must haveffprobe
installed.
Sending special messages
/me <text>
- Send an emote./notice <text>
- Send a notice (generally used for bot messages)./rainbow <text>
- Send rainbow text./rainbowme <text>
- Send rainbow text in an emote./rainbownotice <text>
- Send rainbow text in am.notice
message./reply [text]
- Reply to the selected message. If text is not specified, the next message will be used./react <reaction>
- React to the selected message./redact [reason]
- Redact (delete) the selected message./edit
- Edit the selected message.
Encryption
These commands support tab-completing file paths and user/device IDs using the displaynames of users/devices.
Accepting incoming interactive verification requests is not yet supported, only
outgoing requests via /verify
work.
/fingerprint
- View the fingerprint of your device (for legacy/non-interactive verification)./devices <user id>
- View the device list of a user./device <user id> <device id>
- Show info about a specific device./unverify <user id> <device id>
- Un-verify a device./blacklist <user id> <device id>
- Blacklist a device. Message keys are never sent to blacklisted devices./verify <user id> <device id> [fingerprint]
- Verify a device. If the fingerprint is not provided, interactive emoji verification will be started./export <path>
- Export all message decryption keys to the given path./export-room <path>
- Export message decryption keys for the current room to the given path./import <path>
- Import message decryption keys from the given path./cross-signing <subcommand> [...]
- Cross-signing commands. Somewhat experimental. (alias:/cs
).status
- Check the status of your own cross-signing keys.generate [--force]
- Generate and upload new cross-signing keys. This will prompt you to enter your account password. If you already have existing keys,--force
is required.self-sign
- Sign the current device with cached cross-signing keys. (or in other words, verify the current device).fetch [--save-to-disk]
- Fetch your cross-signing keys from SSSS and decrypt them. If--save-to-disk
is specified, the keys are saved to disk.upload
- Upload your cross-signing keys to SSSS.
/ssss <subcommand> [...]
- Secure Secret Storage (and Sharing) commands. Very experimental.status [key ID]
- Check the status of your SSSS.generate [--set-default]
- Generate a SSSS key and optionally set it as the default.set-default <key ID>
- Set a SSSS key as the default.
Rooms
Creating
/pm <user id> [...]
- Start a private chat with the given user(s)./create [room name]
- Create a new room.
Joining
/join <room> [server]
- Join the room with the given room ID or alias, optionally through the given server./accept
(in a room you're invited to) - Accept the invite./reject
(in a room you're invited to) - Reject the invite.
Existing
/invite <user id>
- Invite the given user ID to the room./roomnick <name>
- Change your per-room displayname./tag <tag> <priority>
- Add the room to<tag>
.<tag>
should start withu.
and<priority>
should be a float between 0 and 1. Rooms are sorted in ascending priority order./untag <tag>
- Remove the room from<tag>
./tags
- List the tags the room is in./powerlevel [thing] [level]
- View or change power levels in rooms.
Leaving
/leave
- Leave the current room./kick <user id> [reason]
- Kick a user./ban <user id> [reason]
- Ban a user./unban <user id>
- Unban a user.
Aliases
/alias add <localpart>
- Add#<localpart>:your.server
as an address for the current room./alias remove <localpart>
- Remove#<localpart>:your.server
(can be ran in any room)./alias resolve <alias>
- Resolve<alias>
or#<alias>:your.server
and reply with the room ID.
Raw events
/send <room id> <event type> <content>
- Send a custom event./setstate <room id> <event type> <state key/-> <content>
- Change room state./msend <event type> <content>
- Send a custom event to the current room./msetstate <event type> <state key/-> <content>
- Change room state in the current room./id
- Get the current room ID.
Debugging
/hprof
- Create a heap profile and write it togomuks.heap.prof
in the current directory./cprof <seconds>
- Profile the CPU usage for the given number of seconds and write it togomuks.cpu.prof
./trace <seconds>
- Trace calls for the given number of seconds and write traces togomuks.trace
.
Shortcuts
This page only applies to gomuks legacy.
Keyboard
Ctrl and Alt are interchangeable in most keybindings, but the other one may not work depending on your terminal emulator.
- Switch rooms: Ctrl + ↑, Ctrl + ↓
- Scroll chat (page): PgUp, PgDown
- Jump to room: Ctrl + K, type part of a room's name, then Tab and Enter to navigate and select room
- Plaintext mode: Ctrl + L
- Newline: Alt + Enter
- Autocompletion: Tab (emojis, usernames, room aliases and commands)
Editing messages
↑ and ↓ can be used at the start and end of the input area to jump to edit the previous or next message respectively.
Selecting messages
After using commands that require selecting messages (e.g. /reply
and
/redact
), you can move the selection with ↑ and ↓
confirm with Enter.
Mouse
- Click to select message (for commands such as
/reply
that act on a message) - Ctrl + click on image to open in your default image viewer (
xdg-open
) - Click on a username to insert a mention of that user into the composer
Customizing keybindings
This page only applies to gomuks legacy.
Keybindings can be customized to some extent by creating a file called
keybindings.yaml
in the config directory (see the FAQ for the location of
the config directory).
The file should have the same format as the default keybindings.yaml file, but you only need to specify the bindings you want to override.
For example, to use enter for newline, you'd want something like this. Note that terminals can't detect shift+enter, and usually only either ctrl or alt works.
main:
'Enter': add_newline
'Ctrl+Enter': unbind
'Alt+Enter': unbind
room:
'Enter': unbind
'Ctrl+Enter': send
'Alt+Enter': send
Debugging
This page only applies to gomuks legacy.
If something doesn't work but it doesn't crash, check the
/tmp/gomuks/debug.log
file for any errors. You can override the location of
this file with the DEBUG_DIR
environment variable.
Developing
Set DEBUG=1
to enable partial deadlock detection and to write panics to stdout
instead of a file.
To build and run with race detection, use go install -race
and set
GORACE='history_size=7 log_path=/tmp/gomuks/race.log'
when starting gomuks,
then check /tmp/gomuks/race.log.<pid>
. Note that race detection will use a lot
of extra resources.
Proper debuggers are too fancy, but normal prints won't work in a TUI
application. To write to the debug log mentioned previously, use the
maunium.net/go/gomuks/debug
package:
package foo
import (
"maunium.net/go/gomuks/debug"
)
func Foo() {
debug.Print("WHY ISN'T IT WORKING?!?!?")
debug.PrintStack()
}