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!
Features
- Threads, spaces, E2EE, and read receipts
- Image previews in terminals that support it (sixels, Kitty, and iTerm2), or using pixelated blocks for those that don’t
- Notifications via terminal bell or desktop environment
- Creating, joining, and leaving rooms
- Sending and accepting room invitations
- Editing, redacting, and reacting to messages
- Custom keybindings
- Multiple profiles
Reading This Documentation
This documentation indicates keybindings using the following conventions:
- Named keys are shown between angle brackets; for example,
<Space>
is the space bar. - Modifiers like the control key or shift are shown with their combining key
between brackets; for example,
<C-W>
is Ctrl-W and<S-Tab>
is Shift+Tab. - Sequences of keys to be pressed are shown in the order to press them; for
example,
<C-W>gf
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:
- #iamb-users:0x.badd.cafe for discussing using iamb
- #iamb-dev:0x.badd.cafe for discussing developing iamb
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
Several community members have taken care of setting up packages for their preferred operating systems and distributions. If you don’t see your system on this page, try checking repology to see whether one exists for your system.
Arch Linux
Using your preferred AUR helper, you can install iamb-git
. For example,
using paru
:
paru iamb-git
FreeBSD
On FreeBSD a package is available from the official repositories. To install it simply run:
pkg install iamb
macOS
On macOS a package is available in Homebrew’s repository. To install it simply run:
brew install iamb
NetBSD / pkgsrc
On NetBSD (or any other system with pkgsrc available), you can
install the iamb
package:
pkgin install iamb
NixOS
There is an iamb
package available in the 23.11 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
).
openSUSE Tumbleweed
On openSUSE Tumbleweed a package is available from the official repositories. To install it simply run:
zypper install iamb
Snap
A snap is available for Linux distributions which support it:
snap install iamb
GitHub Releases
You can find .deb
, .rpm
and binaries built for x86_64
and aarch64
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.10 (2e6376f)
If you would like to build .deb
or .rpm
packages from the repository,
you can do so using cargo-deb and cargo-generate-rpm respectively. For
example:
$ cargo deb
Compiling iamb v0.0.10 (/home/ufsm/src/iamb)
Finished `release` profile [optimized] target(s) in 2m 25s
/home/ufsm/src/iamb/target/debian/iamb_0.0.10-1_amd64.deb
Configuration
iamb is configurable via a TOML 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. An example config can be found in the root of the repo
here.
Profiles
You can configure a Matrix account in your config.toml
by creating a
profiles
subsection with a user_id
field specifying your account:
[profiles.user]
user_id = "@user2:example.com"
When you start iamb for the first time, it will ask you whether you want to
log in with a password (enter p
to select), or SSO (enter s
to select). If
you choose SSO, then a page will open in your browser to go through the SSO
authentication flow.
Multiple Profiles
You can create multiple profiles for different accounts or settings by adding
additional subsections to the profiles
section:
default_profile = "user"
[profiles.admin]
user_id = "@user1:example.com"
[profiles.user]
user_id = "@user2:example.com"
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...
Per-Profile Configuration
Several of the sections that you can place under the global configuration can also be placed within profile configurations to achieve per-profile values:
dirs
layout
macros
settings
Per-profile values will be merged on top of the global values. For example:
[profiles.user.layout]
style = "restore"
[profiles.admin.layout]
style = "new"
Explicit Homeserver URLs
If your homeserver is located on a different domain than the server part of the
user_id
and you don’t have a /.well-known
entry, then
you can explicitly specify the homeserver URL to use:
default_profile = "user"
[profiles.admin]
user_id = "@user1:example.com"
url = "https://example.com"
[profiles.user]
user_id = "@user2:example.com"
url = "https://example.com"
Settings
Name | Default | Description |
---|---|---|
default_room | A default room name or username to open at startup, in place of showing the welcome screen. | |
external_edit_file_suffix | .md | The file suffix to use when creating temporary files with message contents for :edit . (Usually you want the default .md for syntax highlighting.) |
image_preview | (unset) | Configures displaying image attachments for terminals that support previewing images. See Image Previews below. |
log_level | "info" | Configures the minimum log level. Valid values are "trace" , "debug" , "info" , "warn" or "error" . |
message_user_color | false | Whether to color entire messages using the same color used for the sender’s username and display name. |
message_shortcode_display | false | Whether to replace Emojis in message bodies with their shortcodes. |
notifications | (unset) | Whether to generate desktop notifications for messages sent to rooms not currently being viewed. See Notifications |
open_command | Configures a command to use for opening downloads instead of the default. (e.g., ["my-open", "--file"] to run a custom script | |
reaction_display | true | Whether to display message reactions. You can use this or reaction_shortcode_display if your terminal doesn’t show Emojis well. |
reaction_shortcode_display | false | Whether to show the shortcode value instead of the Emoji for reactions. If no shortcode is available, then it won’t be displayed. |
read_receipt_display | true | Whether to display read receipts next to messages in the room scrollback. |
read_receipt_send | true | Whether to send read receipts for viewed rooms. |
request_timeout | 120 | How long to wait in seconds before timing out requests to the homeserver. |
sort | Configures how to sort the lists in different windows like :rooms or :members . See Sorting Lists below. | |
typing_notice_display | true | Whether to display the typing notifications bar. |
typing_notice_send | true | Whether to send notifications to other room members when typing. |
user_gutter_width | 30 | How much space to reserve for displaying the message sender in room history. |
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.toml
:
[settings]
log_level = "debug"
request_timeout = 180
Image Previews
When the settings.image_preview
subsection is present, iamb will
try to detect an appropriate way to show previews of image attachments:
[settings]
image_preview = {}
There are several different supported ways of showing images:
"sixel"
, a method supported by several different terminals (see arewesixelyet.com)"iterm2"
, a method supported by the iTerm2 terminal for macOS"kitty"
, a method supported by the Kitty terminal (requires at least version 0.28.0)"halfblocks"
, a pixelated representation of the image using colored blocks, and used as a fallback
If a method that works for your terminal can’t be autodetected (e.g., when
running on Windows or in a terminal that doesn’t provide pixel information),
you can manually specify how image previews are done using the "protocol"
field:
[settings.image_preview]
protocol.type = "halfblocks"
protocol.font_size = [ 11, 26 ]
The "type"
field is one of the three methods from above, and "font_size"
can be used to specify the width and height of each character cell in pixels.
(Like specifying the "type"
, this is only necessary if the size in pixels
can’t be detected normally using the standard terminal ioctl
calls.)
You can control the maximum amount of columns/rows that the images take up in
the scrollback using the "size"
field:
[settings.image_preview]
size = { height = 10, width = 66 }
Notifications
The settings.notifications
section allows enabling notifications for messages
sent to rooms not currently open. For example, to enable desktop notifications,
you can put the following in your configuration:
[settings.notifications]
enabled = true
See Configuring Room Notifications for how to adjust the per-room notification level.
Notification fields
Name | Default | Description |
---|---|---|
enabled | false | Whether to send notifications |
show_message | true | Whether to include the message body when showing the notification |
via | "desktop" | How to deliver the notification: "desktop" for desktop mechanism, or "bell" for terminal bell. |
Sorting Lists
The settings.sort
section allows you to customize how lists of rooms or users are
sorted in the different iamb windows by specifying which values you want to
sort on. Values are provided as an array of fields, with an optional leading ~
to flip the sort order from ascending to descending.
For example, if you wanted to group users in the :members
list together by their
ascending server name and descending localparts, you could do:
[settings.sort]
members = ["server", "~localpart"]
Sort Fields
Name | Default | Description |
---|---|---|
rooms | ["favorite", "lowpriority", "unread", "name"] | How to sort the :rooms window |
chats | (defaults to rooms value) | How to sort the :chats window |
dms | (defaults to rooms value) | How to sort the :dms window |
spaces | (defaults to rooms value) | How to sort the :spaces window |
members | ["power", "id"] | How to sort the :members window |
Room Fields
Name | Description |
---|---|
"favorite" | Sort rooms with the “Favorite” tag towards the top. |
"lowpriority" | Sort rooms with the “Low Priority” tag towards the bottom. |
"recent" | Sort rooms with recent messages towards the top. |
"unread" | Sort rooms with unread messages towards the top. |
"name" | Sort rooms alphabetically by their room name. |
"alias" | Sort rooms alphabetically by their canonical alias (e.g., #iamb-users:0x.badd.cafe ) |
"id" | Sort rooms alphabetically by their unique room identifier (e.g., !nQTgloqKBScxNjsQzR:0x.badd.cafe ). |
User Fields
Name | Description |
---|---|
"power" | Sort users by decreasing power level. |
"id" | Sort users alphabetically by their username (e.g. @user:example.com ) |
"localpart" | Sort users alphabetically by the localpart of their username (e.g. the @user portion of @user:example.com |
"server" | Sort users alphabetically by the server in their username (e.g. the example.com portion of @user:example.com ) |
Startup Layout
You can configure what windows get shown when iamb starts by adding a
layout
section.
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"
[[layout.tabs]]
split = [
{ window = "#room1:example.org" },
{ window = "#room2:example.org" }
]
[[layout.tabs]]
split = [
{ split = [ { window = "#room3:example.org" }, { window = "#room4:example.org" } ] },
{ window = "@user:example.org" }
]
Custom Keybindings
You can add custom keybindings in macros
subsections, which describes the Vim
modes to map the commands to, the input keys you want to map, and the keys that
you want it to then run. These keybindings behave like macros when a count is
given, and will repeat the target key sequence n times.
For example, you could use the following to map jj
to <Esc>
in Insert mode
and V
to <C-W>m
in Normal and Visual mode:
[macros.insert]
"jj" = "<Esc>"
[macros."normal|visual"]
"V" = "<C-W>m"
You can also use this to trigger commands. For example, to list all chats when you press ‘gc’ in normal mode use:
[macros.normal]
"gc" = ":chats<Enter>"
The available modes are:
normal
/n
for Normal modeinsert
/i
for Insert modevisual
/v
for Visual modecommand
/c
for Command modeselect
for Select modeoperator-pending
for Operator Pending mode
Use |
to specify that something should be mapped in several modes.
If you are unsure how to represent a key, you can you record a macro that use it and then look at its representation in the register. For example, you could do the following to find the value of the left arrow key:
- Type
qa
to start recording to thea
register- Press the left arrow key
- Press
q
to stop recording- Type
"ap
to paste the contents of thea
register, yielding<Left>
Directories
iamb will use the standard directories for your operating system, but you
can override them by placing a "dirs"
field in your config.toml
containing
any of the following fields:
Name | Default | Description |
---|---|---|
cache | ${dirs::cache_dir} /iamb | Directory for iamb data and output that can be safely deleted. |
data | ${dirs::data_dir} /iamb | Directory for iamb data persisted between sessions, like E2EE keys. |
downloads | ${dirs::download_dir} | Output directory for downloaded attachments. |
image_previews | ${cache}/image_preview_downloads | Output directory for caching image displayed when using image_preview |
logs | ${cache}/logs | Output directory for iamb logs. |
User Display
You can override how individual users get displayed in the scrollback using the
settings.users
section.
Name | Default | Description |
---|---|---|
color | Determined per-user | The color to use when showing this user on the screen. |
name | Determined per-user | The name to use when showing this user on the screen. |
Valid values for the color
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" }
End-To-End Encryption
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.
Room Keys
Exporting / Importing Keys
If you want to export your room keys, either to save them as a backup or to import them into another session, you can use:
:keys export /path/to/output.keys passphrase
This will write out the keys encrypted with the given passphrase.
When you have keys that you would like to import into iamb, you can do so with:
:keys import /path/to/input.keys passphrase
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 Rooms And DMs Together
You can switch to a list of both joined rooms and direct messages using the
:chats
command.
Browsing Unreads
You can view a list of rooms and direct messages with unread messages
using the :unreads
command. If you don’t want to visit all of them
to read them each individually, you can mark them all as read with:
:unreads clear
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
Marking Direct Rooms
Matrix keeps a list of direct message rooms in account data on the server. If
you have a room that you want to appear under :dms
and it’s not currently
there, you can add the currently focused room to your account’s list of direct
messages with:
:room dm set
Similarly, if you don’t want it to be a DM:
:room dm 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 oftenm.lowpriority
for rooms that you don’t look at oftenm.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.
Configuring Room Notifications
If you’ve enabled notifications, you may want to reconfigure some rooms to not notify you as much. The different notification levels are:
mute
, which disables notifications for this room.keywords
/mentions
, which only shows notifications for mentions of the user and configured keywords.all
, which shows notifications for every message to this room.
You can update a room with:
:room notify set [mute|keywords|mentions|all]
You can remove the per-room override with:
:room notify unset
And see the currently configured value for the room with:
:room notify show
Administration
If you have the appropriate power level in a room, then you can change room settings and membership as described throughout this page.
Managing Room Membership
Both bot spam and aggressive users are an unfortunately reality, and you may sometimes find yourself needing to get rid of users in a room. You can ban a user with:
:room ban @user:example.com
If you would like to unban someone, you can do:
:room unban @user:example.com
And if you just need to kick them out of the room without banning them (for example, when dealing with a user from a homeserver that no longer exists and is causing perpetual errors in federation), then you can do:
:room kick @user:example.com
If you find yourself managing a large room and needing to often ban users, you may want to look at something like mjolnir to help you manage a ban list.
Setting Room Aliases
You can add a new alias to a room with:
:room alias set #alias:example.com
And remove an alias with:
:room alias unset #alias:example.com
If you want to add a canonical alias or promote an existing one to be canonical, then you can use:
:room canon set #alias:example.com
If there was an existing canonical alias, then it will be demoted to a regular alternative room alias.
If you want a room alias to no longer be canonical, then you can make it an alternative alias with:
:room canon unset #alias:example.com
If you don’t know what the room’s current canonical or alternative aliases are, you can see them with:
:room canon show :room alias show
Setting Room Properties
You can set the description of the currently focused room using its 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 History Visibility
Depending on what your rooms are used for, you may want to configure different visibility settings for the room history. Your options include:
invited
, which configures the room to allow people to see history from the point they were invited onwards.joined
, which configures the room to allow people to see history from the point they actually join the room.shared
, which configures the room to allow people to see all history once they are joined, including messages from before they joined.world
/world_readable
which configures the room to allow anyone to see the room history regardless of whether they are joined and in it.
You can then set it with:
:room history set [invited|joined|shared|world]
You can see the current setting with:
:room history show
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
<C-V><C-J>
. You can also use theO
ando
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 <C-N>
and
<C-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, which is usually set in a GUI application with<C-C>
or by selecting “Copy Image” in a menu dialog."*
contains the PRIMARY selection, which is usually the last selected text in X11 or Wayland.
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
.
If you want to compose a longer message outside of iamb in your preferred text editor, you can use the
:editor
command to launch your configured$EDITOR
.
Message Slash Commands
You can prefix a message with several different slash commands to change the message type or format:
/me
to send an emote message/html
//h
to send an HTML body/plain
//p
to send a plaintext body
These slash commands won’t appear with any special effects in iamb, but do produce effects in other clients:
/confetti
to add confetti effects/fireworks
to add fireworks effects/hearts
to add floating hearts/snowfall
to add snowfall effects/rainfall
to add rainfall effects/spaceinvaders
to add falling Space Invaders
Message Scrollback
You can scroll through messages from the message bar using the following keys:
<C-E>
/<C-Y>
to scroll downwards and upwards respectively a line at a time<C-D>
/<C-U>
to scroll downwards and upwards respectively by half the window height<C-F>
/<C-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 <C-W>m
.
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.
Threads
You can enter or create a thread by selecting the message in the scrollback and
pressing <Enter>
. This will open a thread view that will show you messages
in that thread. If you send a message in this view, it will be sent in-thread.
Entering the thread view puts an entry into the jumplist, so when you are ready
to return to the main room view, you can use ^O
to move backwards through the
jumplist.
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 the argument isn’t the shortcode name of an Emoji, then you will be prompted
for whether you want to react with the literal text. You can force literal text
by adding a !
to the argument. For example, none of these will appear as Emoji:
:react! heart
:react! laughing
:react! "hello world"
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.
Opening Links
Links in messages are each assigned a number (or a letter when there are more
than 10 links), which is shown within brackets (like [0]
). You can use
:open
to view a list of their matching URLs, and pick one to open in a
browser by typing its assigned character.
Screen Navigation
Following Matrix IDs
When your cursor is placed on top of a room, space, or user identifier (or an item for them when when browsing lists of rooms, spaces, or users), you can open a window for it using:
gf
to open in the current window<C-W>f
to open a new window split for the identifier<C-W>gf
to open a new tab for the identifier
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
<C-W>s
and<C-W>v
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:
<C-W>h
will move to the window left of the current one<C-W>j
will move to the window below the current one<C-W>k
will move to the window above the current one<C-W>l
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:
<C-O>
to move backwards through the jumplist<C-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:
<C-W>H
will move the current window to the left side of the screen, and use the full screen height<C-W>J
will move the current window to the bottom of the screen, and use the full screen width<C-W>K
will move the current window to the top of the screen, and use the full screen width<C-W>L
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
<C-W>z
to zoom in and out of a window without changing your current layout - Use
<C-W>T
to extract the window into its own tab
Resizing Windows
You can resize windows using the following keybindings:
<C-W>-
will decrease the current window height by the specified count<C-W>+
will increase the current window height by the specified count<C-W><
will decrease the current window width by the specified count<C-W>>
will increase the current window width by the specified count<C-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
<C-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 <C-W>q
, or close all windows but the current one
using <C-W>o
. 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 <C-W>gf
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
.
Development
Setting Up Your Environment
In order to work on and build iamb locally, you will need:
stable
Rust toolchain withclippy
installednightly
Rust toolchain withrustfmt
installed
You can install the necessary Rust dependencies using rustup:
rustup toolchain install stable --component clippy
rustup toolchain install nightly --component rustfmt
You will also likely want to use rust-analyzer during your development. Refer to its documentation for help on setting it up in your preferred editor.
Programming in Rust
If you are new to Rust, some helpful resources to learn or refer to are:
- The Rust Book (or an alternative version with quizzes and visualizations)
- The Rust Standard Library documentation
- Asynchronous Programming in Rust
- Rust Playground is helpful for trying small examples and learning how things work
You can find more resources on the Rust website.
At some point while working on iamb, you will have to touch one of its dependencies. Some of the libraries whose docs you may need are:
- matrix-sdk
- modalkit
- modalkit-ratatui
- ratatui (see also the ratatui book, which includes small demos and How-Tos)
- tokio (see also the tokio tutorial)
Finding an Issue
You may already have an idea of a feature you want to add or a bug that’s affecting you, but if you’re looking for something to get started learning how to contribute to iamb, you can search for a GitHub issue that interests you, and comment on it when you start working on it!
A couple useful ways to search through the open issues are:
- The
good first issue
label - The Future Release milestone for things that would be useful in iamb, but is currently unplanned/not started.
Building, Formatting and Testing
The commands you will want to run the most are:
cargo check
to run the type checker and borrow checkercargo build
to build a debug binary (outputs totarget/debug/iamb
)cargo test
to run the unit testscargo clippy
to run lints and get suggestions for simplifying codecargo +nightly fmt
to apply the crate’s standard formatting to your changes
Once you have something you’re happy with, you can run cargo build --release
to get a release binary. If you have a machine with plenty of RAM, you can use
cargo build --profile release-lto
to build a smaller, optimized binary using
Link-Time Optimization.
Making a Pull Request
If you are unfamiliar with Git or GitHub, refer to the Git Book or Creating a pull request to get started.
If you want feedback while you’re still working on something, then please open a Draft Pull Request, so that someone can take a look.
Getting Help
There are several different places you can reach out for help:
- #iamb-dev:0x.badd.cafe to discuss in a Matrix room
- File a GitHub issue to discuss your change (or comment on an existing one)
- Open a Draft Pull Request to show and discuss code
Command Reference
iamb commands
Vim commands
Command | Aliases | Help |
---|---|---|
:close | :clo | See Closing Windows |
:horizontal | :hor | See Opening Windows |
:leftabove | :lefta , :aboveleft , :abo | See Opening Windows |
:only | :on | See Closing Windows |
:quitall | :qa , :qall , :quita | See Closing Windows |
:quit | :q | See Closing Windows |
:resize | See Resizing Windows | |
:rightbelow | :rightb , :belowright , :bel | See Opening Windows |
:split | :sp | See Opening Windows |
:tab | See Opening Tabs | |
:tabclose | :tabc | See Closing Tabs |
:tabedit | :tabe , :tabnew | See Opening Tabs |
:tablast | :tabl | See Switching Tabs |
:tabmove | :tabm | See Organizing Tabs |
:tabnext | :tabn | See Switching Tabs |
:tabonly | :tabo | See Closing Tabs |
:tabprevious | :tabp , :tabNext , :tabN | See Switching Tabs |
:tabrewind | :tabr , :tabfirst , :tabfir | See Switching Tabs |
:vertical | :vert | See Opening Windows |
:vsplit | :vs , :vsp | See Opening Windows |
Keybinding Reference
iamb keybindings
Modes | Keybinding | Aliases | Help |
---|---|---|---|
Normal, Visual | <C-W>m | <C-W><C-M> | See Message Scrollback |
Normal, Visual | <C-W>z | <C-W><C-Z> | See 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.
Modes | Keybinding | Aliases | Help |
---|---|---|---|
Normal, Visual | gf | See Following Matrix IDs | |
Normal | gt | <C-PageDown> | See Switching Tabs |
Normal | gT | <C-PageUp> | See Switching Tabs |
Normal | m{a-z} | See Message Scrollback | |
Normal | n | See Message Scrollback | |
Normal | N | See Message Scrollback | |
Normal | o | See Sending | |
Normal | O | See Sending | |
Normal | yy | See Message Scrollback | |
Normal | Y | See Message Scrollback | |
Normal | '{a-z} | See Message Scrollback | |
Normal | / | See Message Scrollback | |
Normal | ? | See Message Scrollback | |
Normal, Visual | <C-B> | <PageUp> | See Message Scrollback |
Normal, Visual | <C-E> | See Message Scrollback | |
Normal, Visual | <C-F> | <PageDown> | See Message Scrollback |
Normal, Visual | <C-D> | See Message Scrollback | |
Normal | <C-I> | <Tab> | See Switching Windows |
Normal | <C-L> | Force the window to redraw | |
Insert | <C-N> | See Sending | |
Normal | <C-O> | See Switching Windows | |
Insert | <C-P> | See Sending | |
Normal, Visual | <C-U> | See Message Scrollback | |
Normal, Visual | <C-W>f | <C-W><C-F> | See Following Matrix IDs |
Normal, Visual | <C-W>gf | See Following Matrix IDs and Opening Tabs | |
Normal, Visual | <C-W>h | <C-W><C-H> | See Switching Windows |
Normal, Visual | <C-W>H | See Organizing Windows | |
Normal, Visual | <C-W>j | <C-W><C-J> | See Switching Windows |
Normal, Visual | <C-W>J | See Organizing Windows | |
Normal, Visual | <C-W>k | <C-W><C-K> | See Switching Windows |
Normal, Visual | <C-W>K | See Organizing Windows | |
Normal, Visual | <C-W>l | <C-W<C-L> | See Switching Windows |
Normal, Visual | <C-W>L | See Organizing Windows | |
Normal, Visual | <C-W>o | <C-W><C-O> | See Closing Windows |
Normal, Visual | <C-W>q | <C-W><C-Q> | See Closing Windows |
Normal, Visual | <C-W>s | <C-W><C-S> | See Opening Windows |
Normal, Visual | <C-W>T | See Organizing Windows | |
Normal, Visual | <C-W>v | <C-W><C-V> | See Opening Windows |
Normal, Visual | <C-W>- | See Resizing Windows | |
Normal, Visual | <C-W>+ | See Resizing Windows | |
Normal, Visual | <C-W>< | See Resizing Windows | |
Normal, Visual | <C-W>> | See Resizing Windows | |
Normal, Visual | <C-W>= | See Resizing Windows | |
Normal, Visual | <C-Y> | See Message Scrollback |
Terminal Comparisons
While you should be able to use iamb in any terminal with reasonable UTF-8
support, if you want to be able to see images in room history or use keypresses
like <S-Enter>
, you might find this table useful:
Terminal | Operating Systems | Images | Extended Keypresses |
---|---|---|---|
alacritty | FreeBSD, Linux, macOS, NetBSD, OpenBSD, Windows | N | Y1 |
ConEmu | Windows | N2 | Y3 |
foot | FreeBSD, Linux, OpenBSD | Y4 | Y1 |
gnome-terminal | FreeBSD, Linux, NetBSD, OpenBSD | N | N5 |
iTerm2 | macOS | Y6 | N |
kitty | FreeBSD, Linux, macOS, NetBSD, OpenBSD | Y7 | Y1 |
konsole | FreeBSD, Linux, NetBSD, OpenBSD | Y4 | N8 |
mlterm | FreeBSD, Linux, NetBSD, OpenBSD | Y4 | N |
rio | FreeBSD, Linux, macOS, Windows | Y6 | Y1 |
wezterm | FreeBSD, Linux, macOS, Windows | Y6 | Y1 |
Windows Terminal | Windows | Y4 | Y3 |
Uses Kitty enhanced keyboard protocol
Uses Windows APIs
Uses sixel image protocol
Uses iTerm2 inlines images protocol
Uses the new Kitty image protocol