Introduction

iamb is a terminal-based client for Matrix for the Vim addict. You can edit messages, navigate windows and manage tabs in the same ways that your fingers are used to from your favorite text editor!

Example Usage

Reading This Documentation

This documentation indicates keybindings using the following conventions:

  • The control key is shown with a leading caret; for example, ^W is Ctrl-W.
  • Named keys are shown between angle brackets; for example, <Space> is the space bar.
  • Sequences of keys to be pressed are shown in the order to press them; for example, ^Wgf indicates that you should type Ctrl-W, then g, and finally f.

Contributing

iamb is free and open source. You can find the source code, report bugs and request features on GitHub.

If you find a mistake in this documentation, you can report it or submit a pull request at the iamb.chat GitHub repository.

Most of the Vim emulation in iamb comes from the modalkit crate. If you find a bug in text editing, window management, or need a Vim keybinding added, you can file an issue there.

Join us on Matrix!

Please feel free to join us in:

Both of these are in the #iamb:0x.badd.cafe space.

License

iamb and its documentation are released under the Apache License, Version 2.0.

Installation

From a package manager

Arch Linux

Using your preferred AUR helper, you can install iamb-git. For example, using paru:

paru iamb-git

NetBSD

pkgin install iamb

NixOS

There is an iamb package available in the 23.05 channel, or, if you have enabled flakes in Nix, you can install iamb from the Git repository via:

nix profile install "github:ulyssa/iamb/latest"

You can replace latest with a branch or specific version tag name if you want to install something besides the most recent release (e.g. main or v0.0.8).

GitHub Releases

You can find binaries built for x86_64 Linux from the Releases page on GitHub.

From crates.io

You can install the most recently published version of iamb from crates.io using cargo:

$ cargo install --locked iamb

This will install the iamb binary to ~/.cargo/bin/, which you should then place in your $PATH.

From Git Repository

If you are working on iamb or need a change that has not yet been published, you can clone the source from GitHub and build from that:

$ git clone https://github.com/ulyssa/iamb.git
$ cd iamb
$ cargo build --release
$ ./target/release/iamb --version
iamb 0.0.8 (89bb107)

Configuration

iamb is configurable via a JSON configuration file located in the configuration directory. By default, the configuration directory is determined by dirs::config_dir, but you can override it at startup with the -C command-line flag.

Profiles

You can configure a Matrix account in your config.json by adding a new field to the "profiles" object. For example, if you had two different accounts on your homeserver:

{
    "profiles": {
        "admin": {
            "user_id": "@user1:example.com",
            "url": "https://example.com"
        },
        "user": {
            "user_id": "@user2:example.com",
            "url": "https://example.com"
        }
    },
    "default_profile": "user"
}

With the "default_profile" field set, iamb will default to using the user profile at startup. You can manually specify what you want via the -P flag. For example:

$ iamb -P admin
Logging in for @user1:example.com...

Several of the fields that you can place under the global configuration can also be placed within profile configurations to achieve per-profile values:

  • "settings"
  • "dirs"
  • "layout"

Settings

NameDefaultDescription
default_roomA default room name or username to open at startup, in place of showing the welcome screen.
log_level"info"Configures the minimum log level. Valid values are "trace", "debug", "info", "warn" or "error".
open_commandConfigures a command to use for opening downloads instead of the default. (e.g., ["my-open", "--file"] to run a custom script
request_timeout120How long to wait in seconds before timing out requests to the homeserver.
reaction_displaytrueWhether to display message reactions. You can use this or reaction_shortcode_display if your terminal doesn’t show Emojis well.
reaction_shortcode_displayfalseWhether to show the shortcode value instead of the Emoji for reactions. If no shortcode is available, then it won’t be displayed.
read_receipt_sendtrueWhether to send read receipts for viewed rooms.
read_receipt_displaytrueWhether to display read receipts next to messages in the room scrollback.
typing_notice_sendtrueWhether to send notifications to other room members when typing.
typing_notice_displaytrueWhether to display the typing notifications bar.
users{}Configure how other users get displayed in the client. See User Display.
username_display"username"Configure what name is shown for senders. Valid values are "username" (e.g., @user:example.org), "localpart" (e.g., user), or "displayname" (e.g., User Name)

For example, if you wanted to raise the timeout to accommodate a long initial sync, and show more log messages, you could put the following into your config.json:

{
    "settings": {
        "log_level": "debug",
        "request_timeout": 180
    }
}

Startup Layout

You can configure what windows get shown when iamb starts by adding a "layout" object.

Restore Previous Layout

By default, the client will try to restore all of the tabs and windows from the last time it was run. You can explicitly configure this behaviour with:

{
    "layout": { "style": "restore" }
}

New Window

If you want to see a single new window each time you start up, you can set:

{
    "layout": { "style": "new" }
}

This will show the :welcome window by default, but you can set "default_room" to change it to something else.

Configured Layout

If you want to start up with the same layout every time regardless of the state at last exit, you can specify an array of tabs and the window tree in each one:

{
    "layout": {
        "style": "config",
        "tabs": [
            {
                "split": [
                    { "window": "#room1:example.org" },
                    { "window": "#room2:example.org" }
                ]
            },
            {
                "split": [
                    {
                        "split": [
                            { "window": "#room3:example.org" },
                            { "window": "#room4:example.org" }
                        ]
                    },
                    { "window": "@user:example.org" }
                ]
            }
        ]
    }
}

Directories

iamb will use the standard directories for your operating system, but you can override them by placing a "dirs" field in your config.json containing any of the following fields:

NameDefaultDescription
cachedirs::cache_dirDirectory for iamb data and output that can be safely deleted.
logs${cache}/logsOutput directory for iamb logs.
downloadsdirs::download_dirOutput directory for downloaded attachments.

User Display

You can override how individual users get displayed in the scrollback using the "users" field of the "settings" object.

NameDefaultDescription
colorDetermined per-userThe color to use when showing this user on the screen.
nameDetermined per-userThe name to use when showing this user on the screen.

Valid values for the "colors" field are:

  • "black"
  • "blue"
  • "cyan"
  • "dark-gray"
  • "gray"
  • "green"
  • "light-blue"
  • "light-cyan"
  • "light-green"
  • "light-magenta"
  • "light-red"
  • "light-yellow"
  • "magenta"
  • "none"
  • "red"
  • "white"
  • "yellow"

For example, if you wanted to override how a bot in a room gets displayed:

{
    "settings": {
        "users": {
            "@jenkins:example.com": {
                "name": "jenkins (CI BOT)",
                "color": "light-red"
            }
        }
    }
}

Verification

Incoming Verifications

If another user or one of your other devices has sent you a verification request, then it will appear in the Verifications list, accessible via running :verify with no arguments.

Requesting Verifications

If you’d like to verify another user, you can do so by running :verify request USERID. Once they accept, you can check the Emojis and confirm that they match in the same way as shown above for incoming verifications.

Rooms

Joining And Leaving Rooms

You can join a new room or space using the :join command. For example, to join the Matrix community space, you can run:

:join #community:matrix.org

You can similarly start a new direct message:

:join @user:example.com

You can leave the currently focused room via the :leave command. This will prompt for confirmation by default, but you can override it by appending !:

:leave!

Browsing

Browsing Rooms

You can switch to a list of joined rooms using the :rooms command.

Browsing Direct Messages

You can switch to a list of direct messages using the :dms command.

Browsing Spaces

You can switch to a list of joined spaces using the :spaces command.

Members

Viewing Room/Space Members

When viewing a room or a space, you can use the :members command to open a new window displaying the active members.

Management

Room Creation

You can create new rooms and spaces using the :create command. By default, the room is private and unencrypted, but you can use the following flags to configure how it is initially created:

  • ++space to make it a space
  • ++public to make the room publicly joinable
  • ++enc/++encrypted to make it an encrypted room
  • ++alias=__localpart__ to set a canonical alias

For example, you could use the following to create a new public space #community:example.com:

:create ++space ++alias=community ++public

Room Invitations

Private Matrix rooms require someone to be let in by a current member with a high enough power level. You can invite someone to join a room through the :invite send command:

:invite send @user:example.com

The user will receive an invitation that they can then choose to accept or reject. If you’ve received an invitation to a room, space, or direct message, you can open it up, focus the window and run:

  • :invite accept to accept the invitation and join the room
  • :invite reject to reject the invitation

Setting Room Properties

You can set the description of the currently focused room using the :set command:

:room topic set "This is the new room topic"

Similarly, if you need to change the room’s name:

:room name set "Watercooler Discussion"

If you want to remove the topic or name, you can use :room topic unset or :room name unset.

Setting Room Tags

Matrix rooms can be tagged to help with sorting them. Several special tags that Matrix defines are:

  • m.favourite for favorite rooms that you look at often
  • m.lowpriority for rooms that you don’t look at often
  • m.server_notice for rooms where homeserver announcements are made

In iamb, you can modify the tags of an open room using:

:room tag set m.favourite

You can use :room tag set fav as a shorthand for m.favourite, and :room tag set low as a shorthand for m.lowpriority.

If you want to unset a tag, you can do:

:room tag unset fav

Matrix also allows users to apply their own tags that start with u.. For example, if you wanted to mark rooms that are bridged to an IRC channel, you could do:

:room tag set u.irc

Note that user tags are not shown by all clients, so while they will appear in iamb, you won’t necessarily see them elsewhere.

Messages

Sending

While the message bar of a room is selected, you can type a message that you wish to send. When it’s complete, you can send it by pressing the <Enter> key from either Normal or Insert mode.

If you need to type a multiline message, you can start a line by typing ^V^J. You can also use the O and o keys to insert a blank line before or after the current line respectively.

From within the message bar, you can complete Matrix usernames, room aliases and identifiers, and Emoji shortcodes (e.g., :heart:) by using ^N and ^P to start cycling forwards or backwards through the list of possible completions.

The :upload command allows you to specify a file to send to the currently focused room:

:upload "/home/user/Documents/Shared Document.pdf"

Clipboard images can be uploaded by pasting with p or P from the "+ and "* registers, and following the confirmation dialog. On macOS and Windows they contain the same contents, but they differ on Linux and other *nix systems running X11 or Wayland, where:

  • "+ contains the CLIPBOARD selection, usually set with ^C or by selecting “Copy Image” in a menu dialog.
  • "* contains the PRIMARY selection, usually contains last selected text) on X11.

So, for example, if you had copied an image from a web browser on Linux (placing it into the CLIPBOARD selection), you could paste it into iamb with "+p. Or, if you instead selected some text with your cursor (placing it into the PRIMARY selection), then you could paste it with "*p.

Message Scrollback

You can scroll through messages from the message bar using the following keys:

  • ^E/^Y to scroll downwards and upwards respectively a line at a time
  • ^D/^U to scroll downwards and upwards respectively by half the window height
  • ^F/^B to scroll downwards and upwards respectively by the window height

If you want to use movement keys to select individual messages, you can toggle focus between the message bar and the scrollback by pressing ^Wm.

The plaintext content of messages can be copied to registers using yank keybindings like yy or Y, and marked with m{a-z}. Marked messages can then be returned to via '{a-z}.

You can search the plaintext content of messages using ? and / for reverse and forward search respectively. The n and N keys can be used to jump between results.

Replying To A Message

If you select a message in the scrollback, you can reply to it using the :reply command. This will refocus the message bar, where you can type out your reply. You can then send it the same way that you would a normal message.

If you change your mind, or select the wrong message to reply to, you can use :cancel to undo your :reply.

Editing Messages

Once a message has been sent, you might find that you need to amend it, to fix typos or correct information. You can select the message and run the :edit command. This will update the text box to include the message’s original body for you to edit.

Once you’ve finished correcting the message, you can send it just like other messages to update the original.

Reacting To A Message

If you want to react to a message with an Emoji, you can select it in the scrollback, and then use the :react command. For example:

:react ❤️

As a convenience, you can use the GitHub Emoji shortcodes to refer to them instead. For example, we could have also written the above as:

:react heart

If you want to remove a reaction, you can do so with the :unreact command. By default, this will remove all your reactions from the specified message, but you can give a name if you’ve made any that you want to keep:

:unreact heart

Redacting A Message

If you need to remove a message from a room, you can do so using the :redact command on the message. This command optionally takes a single argument giving the reason for removing it. For example:

:redact "Message violates room rules" 

If you’re removing a message because it contains secrets (e.g. passwords, authentication tokens, etc.), make sure to rotate them: redacting a message prevents people from seeing it in the future, but users in the room at the time it was originally sent may have already seen it, and it may still live in the room logs of some clients or bots.

Downloading Attachments

If you select an attachment in the scrollback, you can download it using the :download command:

  • When given no arguments, iamb will download the attachment to the configured downloads directory
  • When given a directory as an argument, the file will be saved there
  • Otherwise, the file file will be saved to the given path

If there is already a file of the same name, iamb will not overwrite it. You can use :download! to replace the file.

To open the file after downloading the file, use the :open command instead.

Screen Navigation

Window Management

Opening Windows

You can use :split (or its vertical variant :vsplit) to split the current window. You can optionally provide a room or user to open that room instead. For example:

:vsplit #alias:example.com

Will vertically split the current window and open #alias:example.com in the new window.

If you only need to duplicate the window without changing its content, you can use ^Ws and ^Wv to horizontally and vertically split the current window.

By default, the split commands will open the new window so that it is visually before the current one, but you can alter this using :belowright (as opposed to the default :aboveleft behaviour). Similarly, you can also change the axis of a split using the :vertical and :horizontal commands.

Several of the commands within iamb change the displayed content in the current window. You can force them to instead open a new window using the above commands. For example, to open the list of rooms below the current window:

:bel rooms

Or, to show a room’s members to the left side of the room instead of the right:

:abo hor members

Switching Windows

You can switch between between neighboring windows using the following keybindings:

  • ^Wh will move to the window left of the current one
  • ^Wj will move to the window below the current one
  • ^Wk will move to the window above the current one
  • ^Wl will move to the window right of the current one

If you want to move to previous content in the window, you can navigate through the jumplist using:

  • ^O to move backwards through the jumplist
  • ^I to move forward through the jumplist

You can provide a count to all of the above keybindings to repeat them multiple times.

Organizing Windows

You can reposition open windows using the following keybindings:

  • ^WH will move the current window to the left side of the screen, and use the full screen height
  • ^WJ will move the current window to the bottom of the screen, and use the full screen width
  • ^WK will move the current window to the top of the screen, and use the full screen width
  • ^WL will move the current window to the right side of the screen, and use the full screen height

Sometimes, you may find yourself wanting to make a window occupy the whole screen without closing any of the other windows. You can:

  • Use ^Wz to zoom in and out of a window without changing your current layout
  • Use ^WT to extract the window into its own tab

Resizing Windows

You can resize windows using the following keybindings:

  • ^W- will decrease the current window height by the specified count
  • ^W+ will increase the current window height by the specified count
  • ^W< will decrease the current window width by the specified count
  • ^W> will increase the current window width by the specified count
  • ^W= will attempt to resize all windows in the same row or column to have equal height and width

If your window manager or terminal is capturing ^W, you can use the :resize command to change window height. For example, :resize -10 will decrease the height by ten, and :resize +5 will increase it by 5.

To change the window width, use :vertical resize instead.

Closing Windows

You can close a window using ^Wq, or close all windows but the current one using ^Wo. When provided with a count, these keybindings will operate against that window position instead of the currently focused one.

If you prefer using commands, you can use :quit to close the current window, or :only to close all windows but the current one.

Tab Management

Opening Tabs

You can use the :tab command to modify a command that switches the window content or opens a new window to instead open a new tab. For example:

:tab rooms

The above command will open the list of joined rooms in a new tab. Similarly, if you already know what room you want to open:

:tab join #watercooler:example.com

The above command is equivalent to running:

:tabedit #watercooler:example.com`

You can also press ^Wf while navigating a list of rooms and users to open it in a new tab instead.

Switching Tabs

You can move forwards or backwards through the open tabs using gt or gT respectively. If you know want to go to a specific tab, you can prefix gt with the tab number you want to focus on.

If you prefer using commands, you can use :tabn and :tabp to move between tabs instead of the keybindings.

You can also move to the first or last tab using :tabfirst and :tablast.

Organizing Tabs

You can rearrange your tabs using the :tabmove command, like you would in Vim:

  • :tabmove with no arguments moves the current tab to the end of the tab list
  • :0tabmove will move the current tab to the beginning of the tab list
  • :-tabmove will move the current tab left in the tab list
  • :+tabmove will move the current tab right in the tab list

Closing Tabs

You can close a tab using :tabclose. This will close the current tab with no arguments, but you can specify a position to close:

  • :tabclose 3 will close the third tab
  • :tabclose $ will close the last tab

If you want to close all tabs but the current one, use :tabonly.

Command Reference

iamb commands

CommandAliasesHelp
:createSee Room Creation
:dmsSee Browsing Direct Messages
:downloadSee Downloading Attachments
:editSee Editing Messages
:invite acceptSee Room Invitations
:invite rejectSee Room Invitations
:invite sendSee Room Invitations
:joinSee Joining And Leaving Rooms
:leaveSee Joining And Leaving Rooms
:membersSee Viewing Room/Space Members
:openSee Downloading Attachments
:reactSee Reacting To A Message
:redactSee Redacting A Message
:replySee Replying To A Message
:roomsSee Browsing Rooms
:room name setSee Setting Room Properties
:room name unsetSee Setting Room Properties
:room tag setSee Setting Room Tags
:room tag unsetSee Setting Room Tags
:room topic setSee Setting Room Properties
:room topic unsetSee Setting Room Properties
:spacesSee Browsing Spaces
:unreactSee Reacting To A Message
:uploadSee Sending
:verifySee Verification
:welcomeShows the startup Welcome window

Vim commands

CommandAliasesHelp
:close:cloSee Closing Windows
:horizontal:horSee Opening Windows
:leftabove:lefta, :aboveleft, :aboSee Opening Windows
:only:onSee Closing Windows
:quitall:qa, :qall, :quitaSee Closing Windows
:quit:qSee Closing Windows
:resizeSee Resizing Windows
:rightbelow:rightb, :belowright, :belSee Opening Windows
:split:spSee Opening Windows
:tabSee Opening Tabs
:tabclose:tabcSee Closing Tabs
:tabedit:tabe, :tabnewSee Opening Tabs
:tablast:tablSee Switching Tabs
:tabmove:tabmSee Organizing Tabs
:tabnext:tabnSee Switching Tabs
:tabonly:taboSee Closing Tabs
:tabprevious:tabp, :tabNext, :tabNSee Switching Tabs
:tabrewind:tabr, :tabfirst, :tabfirSee Switching Tabs
:vertical:vertSee Opening Windows
:vsplit:vs, :vspSee Opening Windows

Keybinding Reference

iamb keybindings

ModesKeybindingAliasesHelp
Normal, Visual^Wm^W^MSee Message Scrollback
Normal, Visual^Wz^W^ZSee Organizing Windows

Vim keybindings

Note that this is not a complete list of all Vim keybindings available within iamb, but just some of those referenced and explained throughout this documentation.

ModesKeybindingAliasesHelp
Normalgt<C-PageDown>See Switching Tabs
NormalgT<C-PageUp>See Switching Tabs
Normalm{a-z}See Message Scrollback
NormalnSee Message Scrollback
NormalNSee Message Scrollback
NormaloSee Sending
NormalOSee Sending
NormalyySee Message Scrollback
NormalYSee Message Scrollback
Normal'{a-z}See Message Scrollback
Normal/See Message Scrollback
Normal?See Message Scrollback
Normal, Visual^B<PageUp>See Message Scrollback
Normal, Visual^ESee Message Scrollback
Normal, Visual^F<PageDown>See Message Scrollback
Normal, Visual^DSee Message Scrollback
Normal^I<Tab>See Switching Windows
Insert^NSee Sending
Normal^OSee Switching Windows
Insert^PSee Sending
Normal, Visual^USee Message Scrollback
Normal, Visual^Wf^W^FSee Opening Tabs
Normal, Visual^Wh^W^HSee Switching Windows
Normal, Visual^WHSee Organizing Windows
Normal, Visual^Wj^W^JSee Switching Windows
Normal, Visual^WJSee Organizing Windows
Normal, Visual^Wk^W^KSee Switching Windows
Normal, Visual^WKSee Organizing Windows
Normal, Visual^Wl^W^LSee Switching Windows
Normal, Visual^WLSee Organizing Windows
Normal, Visual^Wo^W^OSee Closing Windows
Normal, Visual^Wq^W^QSee Closing Windows
Normal, Visual^Ws^W^SSee Opening Windows
Normal, Visual^WTSee Organizing Windows
Normal, Visual^Wv^W^VSee Opening Windows
Normal, Visual^W-See Resizing Windows
Normal, Visual^W+See Resizing Windows
Normal, Visual^W<See Resizing Windows
Normal, Visual^W>See Resizing Windows
Normal, Visual^W=See Resizing Windows
Normal, Visual^YSee Message Scrollback