Uplink How-To Guide Everything from installation to tweaks, step by step. Uplink logo

What is Uplink?

Uplink is a fast, secure IRC chat client built with Qt6 and C++17. It connects over TLS (encrypted) by default, supports IRCv3 features like chat history, typing indicators, and SASL authentication, and ships with 55 built-in color themes. The default server is irc.linuxdojo.org:6697, channel #uplink.

It runs on Linux, macOS, Windows, and FreeBSD.

New to IRC? IRC is a real-time chat protocol that has been running since 1988. You connect to a server, join channels (chat rooms that start with #), and chat with other people. Uplink handles all the protocol details — you just type.

Download (pre-built binaries)

The easiest way to get started is to download a pre-built release. No compiler needed.

PlatformDownloadHow to run
Linux x86_64 (AppImage) Latest release ↗ chmod +x Uplink-*.AppImage && ./Uplink-*.AppImage
Linux x86_64 (tar.gz) Latest release ↗ Extract the .tar.gz, run ./Uplink
Windows x64 Latest release ↗ Extract the .zip, double-click Uplink.exe
macOS arm64 Latest release ↗ Open the .dmg, drag Uplink to Applications
FreeBSD Build from source (see below) ./Uplink
Linux users: the AppImage is the recommended download — it is self-contained and runs on any modern x86_64 Linux without installing Qt. See the AppImage section for update instructions.

AppImage — run anywhere, update in-place

The AppImage bundles Uplink and its Qt libraries into a single executable file. It runs on any modern x86_64 Linux with glibc 2.35+ — no package manager, no Qt install needed.

Run it

chmod +x Uplink-*.AppImage
./Uplink-*.AppImage

Update in-place (zsync)

The AppImage embeds zsync metadata pointing to the latest release. Install appimageupdatetool, then:

appimageupdatetool ./Uplink-*.AppImage

Only the changed blocks are downloaded — much faster than a full re-download.

Optional: place the AppImage in ~/bin/ or ~/.local/bin/ and it will appear in your application launcher if your desktop environment supports AppImage integration (most do with libappindicator installed).

Install dependencies

If you're building from source, install these packages first. If you downloaded a pre-built binary, skip this section.

Arch Linux
Ubuntu / Debian
Fedora
FreeBSD
macOS
Windows
sudo pacman -S qt6-base qt6-svg cmake tomlplusplus
sudo apt install cmake qt6-base-dev libqt6svg6-dev libtomlplusplus-dev
sudo dnf install cmake qt6-qtbase-devel qt6-qtsvg-devel tomlplusplus-devel
sudo pkg install cmake qt6-base qt6-svg tomlplusplus
brew install cmake qt tomlplusplus

Then set Qt in your PATH: export PATH="$(brew --prefix qt)/bin:$PATH"

Install Qt 6 via the Qt Online Installer (select Qt 6.x → MSVC 2022 x64 or MinGW). Install CMake from cmake.org. tomlplusplus is fetched automatically by CMake if not found.

Build from source

Three commands. CMake downloads tomlplusplus automatically if your package manager doesn't have it.

git clone https://github.com/noderelay/UplinkIRC.git
cd Uplink
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build

The binary is at build/Uplink (or build\Uplink.exe on Windows). Run it directly — on first launch Uplink creates ~/.config/uplink/themes/ and seeds it with all bundled themes automatically.

macOS: after building, run cmake --install build to produce a proper .app bundle, or launch build/Uplink.app/Contents/MacOS/Uplink directly.

First launch

On the very first run, Uplink creates your config file and may show a nick dialog asking for your nickname. Type the name you want to use on IRC and click OK.

The app then connects to irc.linuxdojo.org and joins #uplink automatically. You'll see the server list on the left, the chat area in the middle, and the user list on the right.

To open the hamburger menu (the button in the top-left), click it to reach Preferences, Documentation, and other settings.

Nothing appeared? The config file might still have the placeholder nick yournick. Click ☰ → Open Config, set nick = "yournick" to your actual nick, save, and click ☰ → Reload Config — Uplink will restart and connect.

Config file location

All settings live in a single config.toml file. Uplink creates it automatically on first launch.

PlatformPath
Linux / FreeBSD~/.config/uplink/config.toml
macOS~/.config/uplink/config.toml
Windows%USERPROFILE%\.config\uplink\config.toml

Edit the file in any text editor. To apply changes, click ☰ → Reload Config — Uplink restarts automatically and picks up all changes. You can also click ☰ → Open Config to open the file in your system editor directly from Uplink.

Set your nickname

Open config.toml and change the nick field in your server block:

[[server]]
name = "LinuxDojo"
host = "irc.linuxdojo.org"
port = 6697
ssl  = true
nick = "alice"       # ← change this to your nick
user = "uplink"
realname = "Uplink User"
channels = "#uplink"

Save, then click ☰ → Reload Config — Uplink restarts and reconnects with the new nick. To change your nick while already connected without restarting, type /nick yournewnick in the input box.

Connect to LinuxDojo

LinuxDojo is the default server. You only need to set your nickname — everything else is already configured.

[[server]]
name     = "LinuxDojo"
host     = "irc.linuxdojo.org"
port     = 6697
ssl      = true
nick     = "alice"
user     = "uplink"
realname = "Uplink User"
channels = "#uplink"

Click ☰ → Reload Config — Uplink restarts and the server appears in the sidebar and connects automatically.

Connect to any IRC server

Add a [[server]] block for every server you want to connect to. The double brackets ([[]]) mean "add another entry to the list" — this is standard TOML array-of-tables syntax.

[[server]]
name     = "Libera.Chat"
host     = "irc.libera.chat"
port     = 6697
ssl      = true
nick     = "alice"
user     = "uplink"
realname = "Uplink User"
channels = "#linux, #archlinux"
Always set ssl = true. Uplink also supports STS (Strict Transport Security) — if the server advertises it, TLS is enforced automatically and the policy is cached for future connections, even if ssl is missing from your config.

Common IRC networks and their TLS hostnames:

NetworkHostPort
LinuxDojoirc.linuxdojo.org6697
Libera.Chatirc.libera.chat6697
OFTCirc.oftc.net6697
EFnetirc.efnet.org6697
IRCnetopen.ircnet.net6697

Auto-join channels

Set the channels key in a server block to a comma-separated list. Uplink joins them all automatically on connect.

[[server]]
name     = "Libera.Chat"
host     = "irc.libera.chat"
port     = 6697
ssl      = true
nick     = "alice"
user     = "uplink"
realname = "Uplink User"
channels = "#linux, #archlinux, #python"   # join all three on connect

You can also set channels from the GUI: click ☰ → Preferences → Manage Servers → Edit and fill in the Auto-join field.

To join a channel while connected without editing the config, type /join #channelname in the input box.


Manage Servers dialog

Click ☰ → Manage Servers... to add, edit, or remove servers from the UI — no need to edit config.toml by hand for most settings. Changes take effect immediately.

Adding a server

1
Click ☰ → Manage Servers...
2
Click Add to open the server form.
3
Fill in the fields (see table below) and click OK.
4
The server is added to the sidebar and begins connecting immediately.
SectionFields
ConnectionName (display name in sidebar), Host, Port, SSL checkbox
IdentityNick, Username, Real Name
AuthenticationServer Password (bouncers / password-protected servers); SASL User + SASL Password (SASL PLAIN); SASL EXTERNAL checkbox + Client Cert + Client Key — each has a Browse button to pick the file; NickServ password (auto-identifies on connect)
ChannelsAuto-join — comma-separated (e.g. #uplink, #linux). See note below for password-protected channels.
BouncerType: None / ZNC / Soju. Network name (soju only).
Password-protected channels: the Auto-join field does not support channel keys. To join a keyed channel, edit config.toml directly using the [[server.channel]] format — the dialog shows a reminder with the exact format to use.

Editing a server

Select the server in the list, click Edit, make your changes, and click OK. The server disconnects and reconnects with the updated settings immediately.

Removing a server

Select the server in the list and click Remove. The server disconnects, is removed from the sidebar, and is deleted from config.toml.


Password storage — OS keychain

Uplink stores all passwords in your OS keychain, not as plaintext in config.toml.

PlatformBackend
LinuxSecret Service (GNOME Keyring, KWallet, or any compatible daemon)
macOSmacOS Keychain
WindowsWindows Credential Manager

After saving, your config file will show "<keychain>" as a sentinel in place of the actual secret:

nickserv_password = "<keychain>"   # actual value is in the OS keychain

When you open Edit Server for a server with a keychain-stored password, the password field shows a placeholder — Stored in keychain — type to change, clear to remove — rather than the sentinel as masked dots. This makes it clear a password exists. Leaving the field unchanged and saving preserves the keychain entry. Typing a new password overwrites it. Explicitly clearing the field removes the entry.

All password fields have a 👁 show/hide toggle — click the eye icon on the right edge of any password field to reveal the value, and click again to re-mask it.

Upgrading from an older version? Any plaintext password already in your config is migrated to the keychain automatically the next time you save your server settings. No manual steps needed.
Headless / no keychain daemon? If the OS keychain is unavailable (e.g. a server without a running secret service), the password field will read back as empty. Enter your password in the server dialog when a keychain becomes available and it will be stored then. Check your terminal output for qWarning messages from Uplink if authentication is failing unexpectedly.
Seeing a red "Keychain: no password stored for…" error in the server buffer? This means your config file has <keychain> as a sentinel, but no matching entry exists in the OS keychain — the password was never written there (or the entry was cleared). Fix: open Edit Server, type your password in the affected field, and save. Uplink will write it to the keychain and authenticate normally from that point on.
KDE wallet keeps prompting when changing preferences (font, theme, toggles)? This was a bug fixed in v0.24.3. Every config save was attempting a keychain write even for unrelated changes. Update to v0.24.3 or later to resolve it. If you cannot update immediately, keeping the wallet unlocked for your session will suppress the prompts.

NickServ auto-identify

If you have a registered nick on a server, add nickserv_password. Uplink sends PRIVMSG NickServ :IDENTIFY yourpassword automatically after connecting.

[[server]]
name              = "LinuxDojo"
host              = "irc.linuxdojo.org"
port              = 6697
ssl               = true
nick              = "alice"
user              = "uplink"
realname          = "Uplink User"
channels          = "#uplink"
nickserv_password = "mysecretpassword"   # ← add this

The server buffer shows Sent NickServ IDENTIFY when it fires. For networks that support SASL, use that instead (below) — SASL identifies you before you even appear on the network.

SASL PLAIN authentication

SASL is the preferred way to authenticate on Libera.Chat, OFTC, and other modern IRC networks. It logs you in during the connection handshake, before you appear to other users.

[[server]]
name          = "Libera.Chat"
host          = "irc.libera.chat"
port          = 6697
ssl           = true
nick          = "alice"
user          = "uplink"
realname      = "Uplink User"
channels      = "#linux"
sasl_user     = "alice"            # ← your registered nick
sasl_password = "mysecretpassword" # ← your NickServ password

The server buffer shows SASL authentication successful on connect. If it fails, the connection continues — you'll just appear without services authentication.

SASL or NickServ? Use SASL if the server supports it (Libera, OFTC). Use nickserv_password for servers that don't (LinuxDojo, older networks).

SASL EXTERNAL (certificate authentication)

SASL EXTERNAL authenticates you by your TLS client certificate instead of a password. The server derives your identity from the certificate's fingerprint — nothing is ever typed or transmitted. Supported on Libera.Chat, OFTC, and most modern IRC servers.

1. Generate a client certificate

# RSA (most compatible)
openssl req -newkey rsa:4096 -nodes -x509 -days 3650 \
  -keyout ~/.irc/client.key -out ~/.irc/client.crt \
  -subj "/CN=yournick"

# EC (smaller, equally secure)
openssl req -newkey ec -pkeyopt ec_paramgen_curve:P-384 -nodes -x509 -days 3650 \
  -keyout ~/.irc/client.key -out ~/.irc/client.crt \
  -subj "/CN=yournick"

2. Register the fingerprint with NickServ

Connect once with your password, then add the certificate fingerprint:

/msg NickServ cert add

The server extracts the fingerprint automatically from your certificate.

3. Configure Uplink

[[server]]
name          = "Libera.Chat"
host          = "irc.libera.chat"
port          = 6697
ssl           = true
nick          = "alice"
user          = "uplink"
realname      = "Uplink User"
channels      = "#linux"
sasl_external = true
client_cert   = "/home/alice/.irc/client.crt"
client_key    = "/home/alice/.irc/client.key"

Uplink loads the certificate before the TLS handshake, negotiates AUTHENTICATE EXTERNAL, and sends an empty response. Both RSA and EC (ECDSA) PEM keys are supported.

You can also set the cert and key paths from the Server dialog: ☰ → Preferences → Manage Servers → Edit, then tick SASL EXTERNAL and browse to your files.

Do not set sasl_user / sasl_password alongside sasl_external — only one SASL mechanism is used per connection.

STS — Strict Transport Security

STS is an IRCv3 security feature that prevents your IRC client from ever being silently downgraded to a plain-text connection. It works exactly like HSTS in web browsers — once a server tells Uplink "always connect over TLS," that instruction is remembered and enforced automatically on every future connection.

How it works

During the initial CAP handshake, a server that supports STS sends a policy containing a TLS port and a duration (how long to enforce it). Uplink handles everything automatically from there:

ScenarioWhat Uplink does
Plain connection — server advertises STSImmediately disconnects and reconnects over TLS on the server-specified port. Stores the policy.
TLS connection — server advertises STSRefreshes the stored policy expiry. No reconnect needed — already encrypted.
Server sends duration=0Deletes the cached policy. Plain connections permitted again.
Cached policy is expiredRemoved automatically on the next connection attempt.

What you'll see

The first time STS triggers an upgrade from plain to TLS, a line appears in the server buffer:

STS: upgrading to TLS on port 6697

After that the connection continues normally — you're now on TLS. On all future connections the stored policy is applied silently before the socket is even opened, so you won't see the message again.

Where the policy is stored

~/.config/uplink/sts.ini

Each entry records the host, TLS port, and an expiry timestamp. Uplink checks this file before dialing any server. If a valid policy exists for the host, TLS is used regardless of what ssl is set to in config.toml.

Nothing to configure. STS is fully automatic. Set ssl = true in your config as usual — STS provides an additional layer that protects you even if that setting is ever wrong or missing. Most modern networks already support it: Libera.Chat, OFTC, and LinuxDojo all advertise STS policies.

Two servers at the same time

Add one [[server]] block per server. Uplink connects to all of them on launch and shows each one in the sidebar independently.

[ui]
theme = "catppuccin-mocha"

[[server]]
name     = "LinuxDojo"
host     = "irc.linuxdojo.org"
port     = 6697
ssl      = true
nick     = "alice"
user     = "uplink"
realname = "Uplink User"
channels = "#uplink"

[[server]]
name          = "Libera.Chat"
host          = "irc.libera.chat"
port          = 6697
ssl           = true
nick          = "alice"
user          = "uplink"
realname      = "Uplink User"
channels      = "#linux, #archlinux"
sasl_user     = "alice"
sasl_password = "mysecretpassword"

Each server's channels appear under its heading in the sidebar. Click any channel to switch to it.

ZNC bouncer

A bouncer is a program that sits between you and IRC. It stays connected 24/7 so you never miss messages — when you open Uplink it replays everything that arrived while you were away. ZNC is the most widely used bouncer.

How ZNC authentication works

ZNC does not use SASL. Instead it identifies you through the Server Password field, using a specific format:

username/network:password

So if your ZNC username is alice, your network is named libera, and your password is hunter2, the Server Password field should contain:

alice/libera:hunter2
Leave SASL blank. ZNC uses the Server Password field for authentication — do not fill in SASL User or SASL Password. Those fields are for connecting directly to IRC servers that support SASL, not for ZNC.

Setting up ZNC in Manage Servers

1
Open ☰ → Preferences, then click Manage Servers and click Add.
2
Fill in Connection: set Host to your ZNC server's hostname or IP, and Port to the port ZNC listens on (commonly 6697 for SSL or 6667 for plain). Check Use SSL/TLS if your ZNC has SSL enabled (recommended).
3
Fill in Identity: set Nick, Username, and Real Name to whatever you normally use on IRC. These are sent to the IRC network through ZNC.
4
Under Authentication → Server Password, enter your ZNC password in username/network:password format. Example: alice/libera:hunter2. Leave all SASL fields blank.
5
Under Channels → Auto-join, list the channels you want to join: #linux, #archlinux
6
Under Bouncer → Type, select ZNC. The Network field disappears — it is not used for ZNC. Click OK, then OK again in Manage Servers.

Config file equivalent

The Manage Servers dialog writes this to config.toml for you, but you can also edit it directly:

[[server]]
name     = "ZNC → Libera"
host     = "znc.example.com"
port     = 6697
ssl      = true
nick     = "alice"
user     = "alice"
realname = "Alice Smith"
password = "alice/libera:hunter2"   # ZNC: username/network:password
bouncer  = "znc"
channels = "#linux, #archlinux"

What ZNC mode enables

Setting bouncer = "znc" (or selecting ZNC in the dialog) tells Uplink to negotiate two ZNC-specific IRCv3 capabilities:

CapabilityWhat it does
znc.in/playbackRequests all messages that arrived since your last disconnect. Uplink asks for them automatically on connect — you see your missed messages instantly at reduced opacity.
znc.in/self-messageEchoes messages you sent from other IRC clients (phone, another PC) back into Uplink so your conversation history stays complete.

Multiple networks on one ZNC

ZNC can carry several IRC networks simultaneously. Add a separate Uplink server entry for each one — same host and port, different network name in the password:

[[server]]
name     = "ZNC → Libera"
host     = "znc.example.com"
port     = 6697
ssl      = true
nick     = "alice"
user     = "alice"
realname = "Alice Smith"
password = "alice/libera:hunter2"
bouncer  = "znc"
channels = "#linux"

[[server]]
name     = "ZNC → OFTC"
host     = "znc.example.com"
port     = 6697
ssl      = true
nick     = "alice"
user     = "alice"
realname = "Alice Smith"
password = "alice/oftc:hunter2"   # same password, different network name
bouncer  = "znc"
channels = "#debian"
Not sure what your network is named in ZNC? Connect once without setting the bouncer type, then type /znc ListNetworks in the server buffer. ZNC will reply with the exact names to use in the password.

Troubleshooting

SymptomLikely cause
Password incorrect / access deniedWrong format — double-check username/network:password. The network name must match exactly what ZNC has (case-sensitive on some ZNC versions).
Connected but no channels joinThe channels in Auto-join don't exist on that ZNC network, or ZNC is set to manage joins itself. Check ZNC's channel settings in its web panel.
No message history on connectznc.in/playback not loaded in ZNC. Enable the playback module in ZNC's web panel under your network's modules.
TLS errorsPort mismatch — ZNC's SSL port is usually different from the plain port. Check the ZNC web panel under Global Settings → Listeners.

soju bouncer

soju is a modern IRC bouncer with deep IRCv3 support. It is simpler to configure than ZNC and handles multiple networks cleanly. If you are running your own bouncer, soju is worth considering.

How soju authentication works

soju uses SASL PLAIN for authentication — but Uplink handles this transparently when you select the soju bouncer type. You just put your credentials in the Server Password field in the simpler username:password format (no network name needed here):

alice:hunter2

Setting up soju in Manage Servers

1
Open ☰ → Preferences → Manage Servers → Add.
2
Host: your soju server hostname. Port: typically 6697 SSL. Check Use SSL/TLS.
3
Identity: fill in Nick, Username, and Real Name as usual.
4
Server Password: enter username:password. Example: alice:hunter2. Leave SASL fields blank.
5
Auto-join: list your channels.
6
Bouncer → Type: select Soju. If your soju manages multiple IRC networks, fill in the Network field with the network name (e.g. libera). If soju only has one network, leave it blank.

Config file equivalent

[[server]]
name            = "soju → Libera"
host            = "soju.example.com"
port            = 6697
ssl             = true
nick            = "alice"
user            = "alice"
realname        = "Alice Smith"
password        = "alice:hunter2"   # soju: username:password
bouncer         = "soju"
bouncer_network = "libera"          # omit if soju only manages one network
channels        = "#linux"

What soju mode enables

CapabilityWhat it does
soju.im/bouncer-networksLists all IRC networks your soju manages in the server buffer on connect as a formatted summary — network name and connection state for each.
soju.im/readSyncs your read position across all connected clients. If you read a message on your phone, Uplink on your desktop already knows.
chathistory / draft/chathistoryRequests missed messages on each channel join — supported by soju, ZNC, and Ergo IRCd. History arrives with original timestamps.

Multiple networks on one soju

Add one Uplink server entry per IRC network. The password is the same — only bouncer_network changes:

[[server]]
name            = "soju → Libera"
host            = "soju.example.com"
port            = 6697
ssl             = true
nick            = "alice"
user            = "alice"
realname        = "Alice Smith"
password        = "alice:hunter2"
bouncer         = "soju"
bouncer_network = "libera"
channels        = "#linux"

[[server]]
name            = "soju → OFTC"
host            = "soju.example.com"
port            = 6697
ssl             = true
nick            = "alice"
user            = "alice"
realname        = "Alice Smith"
password        = "alice:hunter2"
bouncer         = "soju"
bouncer_network = "oftc"
channels        = "#debian"
Not sure what your network names are? Connect once without setting bouncer_network. soju will list all available networks in the server buffer automatically via soju.im/bouncer-networks.
Chat history replay is automatic on ZNC, soju, and Ergo IRCd (and any server supporting the chathistory or draft/chathistory CAP). Uplink requests the last 100 messages for each channel on join. History messages appear dimmed in gray with their original timestamps so you can tell them apart from live messages.

Chat history replay

When you join a channel, Uplink automatically requests the last 100 messages from the server using the IRCv3 chathistory capability. The messages appear at the top of the chat window, dimmed slightly and stamped with their original timestamps, so you can catch up on what you missed without doing anything extra.

This works on any server or bouncer that supports the chathistory or draft/chathistory IRCv3 capability — no config change needed. Uplink requests both cap names automatically.

Servers that support chat history

Server / BouncerCap name advertisedNotes
Ergo IRCddraft/chathistoryRequires history: block in ircd.yaml and a server restart (not just rehash) to initialise the history DB.
sojuchathistoryWorks out of the box — soju stores and replays history natively.
ZNCchathistoryRequires the playback module. Uplink enables it automatically when bouncer = "znc".
Libera, EFnet, IRCnet, and most large networks do not support chat history. Their IRC daemons (Solanum, Charybdis, etc.) do not implement the chathistory cap. The feature simply does not activate — you will not see an error.

What history messages look like

History messages are visually distinct from live messages:

Connecting to an Ergo server with history

No special config is needed on the client side. A normal SSL server entry works:

[[server]]
name     = "LinuxDojo"
host     = "irc.linuxdojo.org"
port     = 6697
ssl      = true
nick     = "yournick"
user     = "uplink"
realname = "Uplink User"
channels = "#uplink, #linux"

On connect, Uplink negotiates draft/chathistory with Ergo. After you join each channel, it sends:

CHATHISTORY LATEST #uplink * 100

Ergo replies with a batch of up to 100 recent messages and Uplink renders them into the chat window automatically.

Ergo history requires server-side config. If history is not showing, ask your server admin to check that the history: block is enabled in ircd.yaml and that Ergo was fully restarted (not just rehashed) after enabling it. A rehash alone is not enough to initialise the history database.

How many messages are replayed?

Uplink always requests the last 100 messages per channel. The server may return fewer if the channel has less history stored. There is currently no config option to change this limit.

WebSocket transport

Most IRC servers accept plain TCP connections (port 6667) or TLS connections (port 6697). Some modern servers and bouncers — particularly web-based ones like The Lounge — are only reachable over WebSocket (ws:// / wss://). Uplink supports both transports.

To use WebSocket, add websocket = true to the server block. When ssl = true is also set, Uplink connects with wss:// (encrypted). When ssl = false, it uses ws:// (plain).

[[server]]
name      = "The Lounge"
host      = "lounge.example.com"
port      = 9000
ssl       = true
websocket = true
nick      = "alice"
user      = "uplink"
realname  = "Uplink User"
channels  = "#uplink"
Everything works the same. SASL, IRCv3 CAP negotiation, STS, SOCKS5 proxy, reconnect, and the ping watchdog all function identically over WebSocket.

You can also enable WebSocket from the GUI: ☰ → Preferences → Manage Servers → Edit and tick the Use WebSocket checkbox.


The topic bar

The bar across the very top of the window is the topic bar. It spans the full window width.

☰ Hamburger — opens a menu with: About Uplink, Check for Updates (fetches the latest release from GitHub and shows whether a newer version is available), Documentation, Preferences, Open Config, Reload Config, and Exit.

⚙ Gear (left) — collapses or expands the server/channel sidebar below it. The gear and hamburger stay pinned — only the list underneath disappears.

Channel panes — view multiple channels at once

Uplink can display up to four channels side by side in the chat area. Each pane is fully self-contained — it has its own chat history, nick list, topic bar, and input bar.

Opening a pane

Right-click any #channel in the sidebar and choose Open in Pane. The channel opens as a new column next to the current view. You can continue typing in either pane independently.

Note: Right-clicking does not navigate away from the channel you are currently viewing — only a left-click does that.

Layout

The chat area restructures automatically as panes are added:

Panes openLayout
1Full width (normal single-channel view)
2Side by side — equal halves
3Primary channel full-height on the left; two panes stacked on the right
42×2 grid — two columns, each with two rows

The splitter handles between panes are draggable so you can resize any column or row to suit your screen.

Rearranging panes

Click and drag any pane's header bar to swap it with another pane. Drop it on the header of any other pane — or on the primary channel area — to swap their positions. The layout rebuilds instantly without losing any content.

Per-pane topic bar

Each pane has a header bar showing the channel name. Click the small speech bubble icon on the left of the header to show or hide the channel topic below it. The topic updates live whenever it changes on the server. The icon is muted (grey) when the topic is hidden and turns accent-colored when the topic is visible — so you can read the state at a glance without clicking.

Closing a pane

Click the button on the right of any pane header to close that pane. The remaining panes expand to fill the freed space and the layout restructures automatically. Closing a pane does not leave the channel — it just removes the split view for it.

You can also right-click the channel in the sidebar and choose Close Pane.

Primary column header

The primary channel always has a header bar at the top containing:

Pane layout persistence

Uplink saves the pane layout automatically when you quit — which channels are open in which pane slots, and the position of the primary column. On the next launch everything is restored exactly as you left it. No configuration required.

Limits and notes

Event condensation

In busy channels, individual join, part, quit, nick-change, and kick lines would otherwise flood the chat view. Uplink automatically collapses consecutive server events into a single compact line:

21:03  ▸  → halloy2109 sumeetj_ bustacheeze  ← CrystalDotGay AJ_Z0

The symbols mean:

SymbolEvent
Nick joined the channel
Nick parted or quit
~Nick rename — shown as oldNick→newNick
Nick was kicked

Expanding a group to see details

Every condensed group has a expand indicator at the left edge. Click it to expand the group in-place and see every event as a full line, with hostmasks and quit/part reasons:

21:03  ▾
21:03  ← CrystalDotGay (~crystal@2600:1700:...) has quit (Ping timeout: 252 seconds)
21:03  ← AJ_Z0 (~AJ@user/aj-z0) has quit (Remote host closed the connection)
21:03  → halloy2109 (~halloy210@208.59.60.21) has joined #uplink
21:03  → sumeetj_ (~sumeet@103.145.17.55) has joined #uplink
21:03  → bustacheeze (~bust@user/bustacheeze) has joined #uplink

Click to collapse the group back to the compact view. Expanded state persists when you switch channels and come back.

This is particularly useful for:

How grouping works

Events are grouped purely by position in the message stream — no timer is involved. Any run of consecutive condensable events with no chat message between them is rendered as a single line. As soon as a regular message appears, the group seals and the next event starts a new group. Switching to a different channel and back always shows the correctly grouped history.

Net-change filter

If the same nick joins and parts within the same group (e.g., a brief reconnect), both events cancel out and neither is shown in the compact view. The expanded view shows every individual event, including the ones that cancel out, so you can see the full sequence of what actually happened.

Overflow

Up to 10 nicks are shown on one condensed line. If more events arrived before a chat message broke the group, the line ends with … X more. Expanding the group always shows all events regardless of the 10-nick limit.

Self-join / self-part

Your own "You joined #channel" and part messages always appear as full lines — they are never condensed, since they mark a meaningful context boundary for you.

Chat area

The large center panel is the chat area. Messages appear in reverse-chronological order (newest at the bottom). History messages replayed by your bouncer or server appear dimmed at the top with their original timestamps.

Typing indicator

When someone in a channel starts typing a reply, a small line appears above the input bar:

alice is typing…

When they stop typing (or send their message), the line disappears automatically.

Requirements

Both sides need to support IRCv3 draft/typing. Uplink negotiates this cap automatically on connect — if the server supports it, typing notifications are sent and received with no configuration needed. If the server does not advertise the cap, the feature is silently inactive.

What you see vs. what others see

You never see your own typing indicator. The indicator is only shown to other users in the channel — you see theirs, they see yours. This is by design: seeing your own "is typing…" would be distracting and confusing.

ScenarioWhat happens
You start typing in #linuxOther users in #linux see "yournick is typing…" — you do not
Alice starts typing in #linuxYou see "alice is typing…" above your input bar
Alice stops typing without sendingThe indicator disappears after a few seconds
Alice sends her messageThe indicator disappears as soon as the message arrives
Multiple people typing at onceEach indicator appears as a separate line above the input bar

Enabling / disabling

The typing indicator can be toggled from ☰ → Preferences → Show typing indicator, or in config:

[ui]
typing_indicator = true   # set to false to disable completely
Privacy note: when enabled, Uplink sends a TAGMSG with the +typing=active tag to the channel as you type. If you prefer not to broadcast this, disable the feature in Preferences.
Compatibility: Uplink only sends typing TAGMSG when the server has negotiated the draft/typing capability. On older networks (Undernet, EFnet, IRCnet) that do not support this extension, the typing indicator is automatically silenced — no errors, no spam.

Nick list panel

The user list sits in a panel on the right side of the chat. The header shows a gear and the user count.

Nick right-click menu

Right-clicking any nick — whether in the user list on the right or directly in the chat view — opens the same context menu. The menu title shows the nick in bold.

ActionWhat it does
MessageOpens a private message buffer for that nick in the sidebar. Equivalent to /msg nick.
Send FileOpens a file picker and sends the file via active DCC — Uplink opens a port and the recipient connects in. Works when you have a reachable IP.
Send File (Passive)Sends via passive DCC — the recipient opens the port and Uplink connects out to them. Use this when you are behind a home router or VPN.
WhoisSends a WHOIS request. The full response (hostname, channels, idle time, account, TLS status) appears in the active channel — right where you are chatting. See Looking up users.
InviteOpens a dialog pre-filled with the current channel. Edit if needed and click OK to send INVITE nick #channel.
Give OpSets +o on the nick in the current channel. Requires op.
Take OpRemoves -o from the nick in the current channel. Requires op.
Give VoiceSets +v on the nick in the current channel. Requires op or half-op.
Take VoiceRemoves -v from the nick in the current channel. Requires op or half-op.
VersionSends a CTCP VERSION request. The reply (client name and version) appears in the active channel. See Looking up users.
PingSends a CTCP PING with a millisecond timestamp. The round-trip time appears in the active channel as Ping reply from nick: Xms. See Looking up users.
Copy NickCopies the nickname to the system clipboard — paste it into the input bar or anywhere else.
Ignore / UnignoreSuppress all messages (PRIVMSG, NOTICE, ACTION) from this nick. The label changes to Unignore if they are already on your ignore list. Persists in config.
KickPrompts for an optional reason, then sends KICK #channel nick :reason. Requires op.
BanSets MODE #channel +b nick!*@* — bans the nick by name. Requires op.
Kick & BanBans first, then kicks. Prompts for an optional reason. Requires op. Both actions are sent in the correct order.

The same menu appears whether you right-click in the nick list panel on the right or on a nick link in the chat view (nicks in messages are clickable anchors).

Account tracking

Uplink tracks each user's NickServ account name in real time. This lets you see who is actually behind a nickname — even if someone changes their nick — as long as they're authenticated with services.

Where to see it

Account names appear as tooltips in two places. Simply hover over any nick:

If the tooltip is absent, the user is either not authenticated with services or the server does not report account names for that nick.

How it stays current

Uplink pulls account data from four sources so the information is always up to date without any manual queries:

SourceWhen it firesWhat it provides
account-tag On every message the user sends Account name attached directly to the message — no separate event needed. Updates on every single message in real time.
account-notify When a nick logs in or out of services An ACCOUNT command is sent to all clients in shared channels the moment authentication status changes.
extended-join When a user joins a channel The account name is included directly in the JOIN message — no extra query needed on join.
WHOX scan After you join a channel Uplink sends WHO #channel %cnfa,42 to bulk-populate all accounts for everyone already in the channel.

All four are negotiated and handled automatically — no configuration needed.

Tip: account names survive nick changes. If alice changes her nick to alice_away and you hover over the new nick, the tooltip still shows account: alice_libera — because it's tied to the account, not the display name.

User metadata — display names & avatars

On servers that support the IRCv3 draft/metadata-2 capability, every user can publish a display name and an avatar image that other clients automatically receive and display. Think of it as a lightweight profile attached to your IRC nick, stored on the server and synced in real time.

Server support required. draft/metadata-2 is an in-development IRCv3 extension. Ergo and soju support it. Most traditional networks (Libera, OFTC) do not. Uplink silently skips metadata if the server does not advertise the capability — no errors, it just does nothing.

Where it displays

Hover over any nick in the right-side nick list panel. A tooltip appears showing that user's profile. If they have set an avatar, the image appears inline on the left:

[avatar image]  Name: Alice Smith
                Account: alice

Uplink fetches the avatar image in the background as soon as the metadata arrives. Images are displayed at their native size, capped at 32×32 — no upscaling, so small icons like favicons stay crisp. The image is cached for the session; subsequent hovers are instant.

Metadata follows a nick across all channels on the same server. If Alice sets her display name, you will see it in #general, #linux, and every other channel you share with her.

Setting your own display name and avatar

There are two ways to set your profile — via the Preferences dialog or via slash commands. Both save the values to your config so they are re-published automatically every time you connect to a supporting server.

Via Preferences

  1. Open ☰ → Preferences and scroll to the Profile section at the bottom.
  2. Enter your Display Name — the friendly name other users see in the tooltip (e.g. Alice Smith). It does not replace your IRC nick.
  3. Enter your Avatar URL — a full https:// link to an image file. Or click Browse... to pick a local image from your computer.
    • Web URL (e.g. https://example.com/avatar.png) — broadcast to the server; other users see it when they hover your nick.
    • Local file path (e.g. /home/alice/avatar.png) — displayed only in your own client; never sent to the server, so other users will not see it.
  4. Click Apply to connected servers. Uplink saves the values, sends them to every currently-connected server that supports draft/metadata-2, and updates your own nick tooltip immediately — no reconnect needed.

From then on, Uplink automatically publishes your profile each time you connect — no need to re-enter anything.

Via commands

You can set your display name and avatar directly from the input box:

/displayname Alice Smith
/avatar https://example.com/avatar.png
/avatar /home/alice/avatar.png

To clear a value (remove it from the server), run the command with no argument:

/displayname
/avatar

Both commands print a confirmation in the current buffer. If the server does not support draft/metadata-2, the command tells you instead of silently failing.

CommandEffect
/displayname Alice SmithSet display name to "Alice Smith"
/displaynameClear your display name
/avatar https://…/pic.pngSet avatar to a web URL (visible to others)
/avatar /home/alice/avatar.pngSet avatar to a local file (visible only to you)
/avatarClear your avatar

Config file

You can also set your profile directly in ~/.config/uplink/config.toml:

[profile]
display_name = "Alice Smith"
avatar_url   = "https://example.com/avatar.png"

Values are loaded on startup and published on each connect to a supporting server.

How it works under the hood

When Uplink connects to a server that advertises draft/metadata-2, the capability is negotiated during the normal CAP handshake. The server then pushes METADATA notifications whenever a user's display-name or avatar key changes — no polling needed.

Setting your profile sends a METADATA * SET command to the server:

METADATA * SET display-name :Alice Smith
METADATA * SET avatar :https://example.com/avatar.png

The server stores those values and immediately broadcasts them to other connected clients. When Uplink receives an avatar URL for a nick, it fires a background HTTP request to fetch the image, caches it in memory, and updates the tooltip. The first hover before the fetch completes shows the name and account only; subsequent hovers show the image.

Local file paths (starting with / or file://) are loaded from disk directly — no network request. They are never sent to the server, so other users see no avatar for you unless you also have a web URL configured.

Signal bars (lag / latency indicator)

Four stair-step bars appear in the topic bar showing your connection quality — latency, lag, and connection state — to the current server.

AppearanceMeaning
4 solid green barsConnected, latency < 50 ms (excellent)
3 solid green barsConnected, latency 50–149 ms (good)
2 solid green barsConnected, latency 150–299 ms (fair)
1 solid green barConnected, latency ≥ 300 ms (high lag)
Blue flashingConnecting or reconnecting
Red flashingDisconnected

Uplink sends a PING every 30 seconds and measures the round-trip time (RTT). The bar count updates automatically after each ping reply.

System tray

Closing the window minimizes Uplink to the system tray — it keeps running in the background.

To control the notification dot, go to ☰ → Preferences → Tray Notifications, or set in config:

notifications = true   # green dot on tray for mentions/PMs

Sending messages

Click on a channel in the sidebar to make it active. Type your message in the input box at the bottom and press Enter to send.

To perform an action (like * alice waves), use /me:

/me waves at everyone

Slash commands

Type a / to start a command. Tab-completion works on command names too — type /p and press Tab to cycle through /part, /ping, etc.

CommandWhat it doesExample
/join #channelJoin a channel/join #linux
/part [reason]Leave the current channel/part goodbye
/leaveLeave the channel — or close a PM/query window/leave
/closeSame as /leave — closes a PM window or parts a channel/close
/nick newnickChange your nickname/nick alice_
/me actionCTCP action/me waves
/msg nick textSend a private message/msg bob hey there
/topic textSet the channel topic (requires op)/topic Welcome!
/kick nick reasonKick a user (requires op)/kick bob bye
/op nickGive someone channel op/op bob
/voice nickGive someone voice/voice carol
/ban maskBan a hostmask/ban *!*@badhost.net
/ping nickMeasure round-trip time to a nick — reply appears in the active channel/ping bob
/whois nickFull user info (hostname, channels, idle time, account) — reply appears in the active channel/whois bob
/whowas nickHistory for a departed nick — last known user@host and realname — reply appears in the active channel/whowas bob
/setname realnameChange your realname (GECOS) on the fly without reconnecting (IRCv3 setname)/setname Alice Smith
/list [filter]List all channels on the server — results appear in the server buffer/list, /list #linux
/stats queryRequest server statistics — results appear in the active channel/stats u
/timeQuery the server's local time/time
/version nickAsk what IRC client a nick is running — reply appears in the active channel/version bob
/monitor add <nick>Watch for a nick coming online/monitor add alice
/monitor del <nick>Stop watching a nick/monitor del alice
/monitor listShow your current watch list
/monitor clearClear all watched nicks
/monitor statusRequest current online/offline status
/ignore nickSuppress all messages from a nick/ignore spammer
/unignore nickRemove a nick from the ignore list/unignore spammer
/ignoredList all ignored nicks
/ns textShortcut for PRIVMSG NickServ/ns identify pass
/cs textShortcut for PRIVMSG ChanServ/cs op #uplink
/away messageSet yourself away/away at lunch
/backClear your away status/back
/clearClear the chat buffer/clear
/raw lineSend a raw IRC protocol line to the server/raw MODE #uplink +m
/quote lineAlias for /raw/quote INVITE alice #uplink
/ANYTHINGAny unrecognized command is sent as-is — no prefix needed/REHASH, /SAMODE #uplink +o alice
/quit [message]Disconnect/quit see ya
/sysinfoCollect OS/CPU/RAM/GPU/uptime info and post to channel — confirms before posting; collection runs async with 12s timeout/sysinfo
/helpList all commands/help
Tip: oper and server-specific commands work directly. If a command is not in the list above, just type it — Uplink passes it straight to the server. This means IRC operator commands like /REHASH, /SAMODE, /GLOBOPS, /OPER, and any other server-specific command work without needing a /raw prefix. Uplink does not need to know about every command your server supports.
/whois, /version, and /ping replies appear in your active channel — not the server buffer. If you run /whois alice while in #linux, the full WHOIS response lands in #linux. Run it from alice's PM window and it lands there instead. See Looking up users for full examples.

Looking up users — /whois, /version, /ping

Three commands let you inspect another user in detail. All three post their results in the active channel or PM window — wherever you have focus when the reply arrives. You do not need to switch to the server buffer to see them.

/whois — full user profile

Returns everything the server knows about a nick: hostname, real name, which channels they are in, which server they are connected to, idle time, NickServ account, and whether they are on a secure (TLS) connection.

/whois alice

Example — running /whois alice while in #linux. The entire block appears in #linux:

alice is alice@host.example (Alice Smith)
alice is in channels: #linux #uplink #general
alice is on irc.linuxdojo.org (LinuxDojo IRC)
alice is identified as account: alice
alice has been idle 2 minutes, signed on 14:30:01
alice is using a secure TLS connection

You can also trigger it from the user list or chat view — right-click any nick → Whois. No need to type the command if you can see the nick.

Want to whois yourself? /whois yournick yournick (nick twice) forces the server to return your own idle time and away status — useful for debugging whether your away message is set.

/version nick — what client are they running?

Sends a CTCP VERSION request to the nick. Their client automatically replies with its name and version string. The reply appears in your active channel.

/version alice

Example output in the active channel:

VERSION reply from alice: Uplink 0.25.0 / Qt 6.7.2 / Linux x86_64

Common replies from other clients:

VERSION reply from bob:   HexChat 2.16.2 Linux [x86_64]
VERSION reply from carol: Irssi v1.4.5 - https://irssi.org
VERSION reply from dave:  WeeChat 4.3.1 (compiled Apr 2 2024)
VERSION reply from bot:   (no reply — most bots block CTCP)
No reply? The nick may have CTCP replies disabled, be using a client that does not respond, or be a bot. That is normal — just means no version info is available.

/ping nick — measure round-trip latency

Sends a CTCP PING with a high-resolution timestamp. When the reply arrives, Uplink calculates the round-trip time and posts it to the active channel.

/ping alice

Example output:

Ping reply from alice: 23ms

What the numbers mean:

ResultWhat it indicates
1–50 msSame region or same server — very low latency
50–150 msDifferent country or continent — normal for international chat
150–400 msHigh latency — possibly a satellite connection or slow network path
No replyThe nick has CTCP PING blocked, or their client does not support it
All three commands route to your active window. The rule is simple: whatever channel or PM you are looking at when the reply arrives — that is where it appears. This means you can look up multiple people in sequence from the same channel and all responses stack up there, together.
# You are in #linux, talking to alice and bob:
/whois alice     →  full WHOIS block appears in #linux
/ping alice      →  "Ping reply from alice: 23ms" in #linux
/version alice   →  "VERSION reply from alice: Uplink 0.25.0" in #linux
/whois bob       →  full WHOIS block appears in #linux (below alice's)

Using right-click instead of commands

All three are also in the nick right-click menu — right-click any nick in the user list or directly in the chat view, then choose:

The reply appears in the active channel regardless of whether you used the command or the menu.

Listing channels — /list

To browse all channels on the current server, type:

/list

A Channel Browser dialog opens. Results stream in as the server sends them — you don't have to wait for the full list before you can start filtering.

Sorting and filtering

Joining a channel

Refreshing

Click Refresh to re-request the channel list from the server. Useful if the server's list has changed since you opened the dialog.

Large networks: On networks like Libera.Chat with thousands of channels, the dialog populates progressively — rows appear as the server sends them. Use the filter box to narrow down immediately without waiting for the full list.

Server queries — /stats, /time, /whowas

/stats — server statistics

The /stats command asks the server for operational information. The result appears in the active channel buffer.

CommandWhat it returns
/stats uServer uptime
/stats oIRC operator list
/stats mCommand usage counts

Other letters may be supported depending on your IRC server. On Ergo, /stats u is the most useful.

/time — server local time

Run /time with no arguments to query the server's local time:

/time

The result appears in the active channel buffer. To query another user's local time via CTCP, use /time nick instead.

/whowas — history for departed nicks

If a nick has left the network, /whowas shows their last known connection details:

/whowas alice

The reply shows the user's last user@host and realname, and appears in the active channel buffer alongside WHOIS output.

WHOWAS history is server-dependent. Most servers keep a short rolling history. If the nick left too long ago the server may return "No such nick".

Changing your realname — /setname

Your realname (also called GECOS) is the longer description shown in WHOIS output. Normally it is set in your config and only applied when you connect. With the IRCv3 setname extension, you can change it on the fly without reconnecting:

/setname Alice Smith

The change takes effect immediately on servers that support setname (Ergo does). Other users in channels you share will see a status line: alice changed their realname to "Alice Smith".

Persisting the change: /setname only lasts for the current connection. To make it permanent, update the realname field in your config file and save.

Private messages

Use /msg nick message to send a PM. A new buffer for that person appears in the sidebar. Incoming PMs also open their own buffer automatically.

You can also right-click a nick in the user list or directly in the chat view and choose Message to open the buffer without typing a command.

/msg bob hey, are you around?

Messaging IRC services (NickServ, ChanServ…)

Services like NickServ and ChanServ are bots that live on the server and respond via private message. Uplink has shortcut commands for the most common ones:

CommandSends toExample
/ns <text>NickServ/ns help
/cs <text>ChanServ/cs help
/bs <text>BotServ/bs botlist
/ms <text>MemoServ/ms list

Or use the full form: /msg NickServ help, /msg ChanServ op #uplink, etc.

Where do the replies appear? When you send a message to a service, Uplink opens a PM tab for that service in the sidebar (e.g. a NickServ tab or ChanServ tab). Replies from that service — including help output, error messages, and confirmations — arrive in that same tab. If you have not messaged the service yet, their replies go to the server buffer instead.

Password commands are safe to type. When you use /ns identify mypassword or /msg NickServ identify mypassword, Uplink shows IDENTIFY <redacted> in the NickServ tab — your actual password is never displayed in the chat view. The command still goes to the server correctly. This redaction covers IDENTIFY, REGISTER, GHOST, RECOVER, and other password-taking commands.
Example: Typing /msg ChanServ help opens a ChanServ tab and sends the request. ChanServ's help reply arrives in that same ChanServ tab — not in the server buffer or the channel you were looking at.

IRC colors and formatting

Uplink renders all standard IRC formatting codes in received messages:

CodeEffect
Ctrl+B (bold marker)Bold text
Ctrl+IItalic text
Ctrl+UUnderline text
Ctrl+SStrikethrough
IRC color codes (03xx)16 foreground + background colors

Most IRC clients let you insert formatting codes by pressing the key combinations above in the input box. Uplink displays whatever formatting codes come through from the server.

Emoji and shortcodes

There are three ways to use emoji in Uplink:

1. Type a shortcode — inline autocomplete

Start typing : followed by the emoji name. A completion list pops up:

:fire    →  shows completion list: 🔥 fire, ...
:thumbs  →  shows: 👍 thumbsup, 👎 thumbsdown, ...

Navigate with / , select with Enter or Tab, dismiss with Escape.

2. Type a full shortcode — instant substitution

Type the opening colon, the name, and the closing colon. The emoji replaces it instantly:

:trident:   →  🔱  (substituted as you type the closing colon)
:joy:       →  😂
:100:       →  💯

3. Emoji picker button

Enable the button in config or Preferences, then click 😊 to open a searchable grid of ~400 emoji. The search box accepts plain words or shortcode style — poop and :poop both work. Press Enter to commit the first match without clicking.

[ui]
show_emoji_button = true

Emoji size

Emoji in chat are rendered at their own independent font size so they stay readable even if you use a small chat font. The default is 16 pt. Change it in Preferences → Font Config… → Chat Emoji, or set it directly in config:

font_emoji = 16   # pt, independent of font_chat

Multi-line messages

The message input box supports multiple lines — useful for pastes, code snippets, or structured replies.

Composing

Press Shift+Enter to insert a line break. The box grows automatically from 1 to 4 lines as you type. Press Enter (without Shift) to send the whole message.

How it reaches the server

When the server supports IRCv3 draft/multiline, Uplink sends the message as a proper multi-line batch — all lines arrive as a single logical message. On servers without the capability, each line is sent as a separate PRIVMSG in sequence — no content is lost, though recipients without multi-line support see individual lines.

Receiving multi-line messages

Incoming draft/multiline batches are assembled and displayed as a single message with line breaks in the chat view.

Tip: to paste multi-line content, paste directly into the input box — line breaks are preserved and the box resizes to show all lines before you send.

Tab completion

Press Tab to complete nicknames and slash commands. Completion works in every input bar — the primary channel input and any open channel pane inputs.

al[Tab]        →  alice:           (start of line — colon appended)
thanks al[Tab] →  thanks alice     (mid-line — no colon)
/p[Tab]        →  /part
/p[Tab][Tab]   →  /ping
/p[Tab][Tab][Tab] →  /privmsg

Input history

Press in the input box to scroll back through messages you've sent in this session. Press to go forward again. The history is per-session and is not saved to disk.

Reply to a message

Uplink supports IRCv3 draft/reply — replies that reference a specific message by its unique ID. The server must have negotiated message-tags (all modern IRC servers do).

Sending a reply

There are two ways to trigger a reply — both work equally well:

Option A — right-click anywhere in the message:

1
Click and drag to select some text in the message (or just right-click anywhere in it).
2
Right-click — the menu shows Copy (if text is selected) and Reply. Click Reply.

Option B — right-click the timestamp:

1
Right-click the timestamp (the hh:mm at the far left of the message).
2
Click Reply from the menu.

After choosing Reply (either way):

3
A reply bar appears above the input box showing ↩ nick. Press Escape or click to cancel without sending.
4
Type your reply and press Enter. The message is sent referencing the original.

Viewing replies you receive

When someone replies to a message using a client that supports draft/reply, a small ↩ origNick indicator appears before their nick in the chat — showing whose message they are replying to.

14:30 alice: what's everyone using for backups these days?
14:31 ↩ alice  bob: rsync + rclone to Backblaze, works great
Compatibility: clients that do not understand draft/reply simply see your message as normal — the reply tag is invisible to them. No special server setup is needed beyond standard IRCv3 message-tags.
Switching channels automatically cancels any pending reply. The reply bar clears when you navigate to a different buffer.

Reactions

Uplink supports IRCv3 draft/react — emoji reactions attached to specific messages. Both sending and receiving are supported.

Sending a reaction

1
Right-click the timestamp (the hh:mm at the left of the message).
2
Choose React from the context menu.
3
The emoji picker opens. Search by name (you can type :thumbs or just thumbs), then click the emoji you want.

Alternatively, after right-clicking a timestamp and choosing Reply (which sets the message target), you can use:

/react 👍

Viewing reactions

Received reactions appear inline below the original message as emoji(count), for example:

14:22 <alice> anyone tried the new soju release?
👍(2) ❤️(1)
Server support required: the server must advertise the draft/react capability. On servers that do not support it, reactions are not sent and will not be received.

Message deletion

Uplink supports IRCv3 draft/message-redaction — you can delete your own sent messages from the chat history.

1
Right-click the timestamp on one of your own messages.
2
Choose Delete from the context menu.

The message is replaced with [message deleted] in grey italic. Other clients that support draft/message-redaction will also hide the message.

Server support required: the Delete option only appears when the server has acknowledged the draft/message-redaction capability during the CAP handshake. You can only delete your own messages.

Ignore list

The ignore list suppresses all PRIVMSG, NOTICE, and ACTION messages from specific nicks — client-side. The ignored user does not know they are being ignored.

Ignoring a nick

Right-click their nick in the user list or chat view and choose Ignore. Or type:

/ignore spammer

Unignoring a nick

Right-click their nick — the menu shows Unignore when they are already on your list. Or type:

/unignore spammer

Listing ignored nicks

/ignored

The ignore list is saved in config.toml under [ignore] nicks = [...] and is restored automatically on the next launch.

Monitor — online/offline watching

The IRCv3 MONITOR system lets you watch for specific nicks coming online or going offline. When a watched nick connects or disconnects, a status line appears in the server buffer: Now online: alice / Now offline: alice.

CommandWhat it does
/monitor add <nick>Start watching this nick
/monitor del <nick>Stop watching this nick
/monitor listShow your current watch list
/monitor clearRemove all watched nicks
/monitor statusAsk the server for current online/offline status of all watched nicks

Example — watch for a friend:

/monitor add alice

The watch list is saved to config.toml under [monitor] nicks = [...] and is re-sent on every reconnect. You can also edit it directly:

[monitor]
nicks = ["alice", "bob"]

Message logging

Uplink writes all messages to plain-text log files on disk — one file per channel and per PM conversation.

Log file location

~/.config/uplink/logs/<server>/<channel>.log

For example: ~/.config/uplink/logs/irc.linuxdojo.org/#uplink.log

Log format

[2026-05-31 15:04:22] <nick> message text
[2026-05-31 15:04:22] * nick action text
[2026-05-31 15:04:22] -- system message (join, part, etc.)

History replay messages (from bouncers or chathistory) are not logged — only live messages.

Turning logging on or off

Click ☰ → Preferences and check or uncheck Log Messages to Disk. Or set it in config:

[ui]
log_messages = true    # off by default — opt-in

Logging is off by default. Enable it in Preferences or by setting log_messages = true in config.

DCC file transfer

DCC (Direct Client-to-Client) lets you send files directly to another user without going through the IRC server. Uplink supports two modes — choose based on your network situation.

Which mode should I use?

ModeWhen to use
Send File (active)You have a reachable IP — direct broadband, a VPS, or port forwarding configured on your router. Uplink opens a port and the recipient connects in.
Send File (Passive)You are behind a home router or VPN and cannot accept incoming connections. The recipient opens the port; Uplink connects out to them. Use this if active DCC never starts.

Quick guide: try Send File first. If the progress dialog sits at zero with no activity, cancel and try Send File (Passive) instead.

Sending a file (active)

1
Right-click the recipient's nick in the user list.
2
Choose Send File.
3
Pick a file in the file picker. Uplink opens a TCP port and sends the DCC SEND offer.
4
A progress dialog appears. Transfer begins once the recipient accepts.

Sending a file (passive — use behind NAT)

1
Right-click the recipient's nick in the user list.
2
Choose Send File (Passive).
3
Pick a file. Uplink sends the offer with port=0 — a signal that the recipient should open the port.
4
The recipient's client opens a port and replies with its address. Uplink connects out automatically and the transfer begins.

Receiving a file

When someone sends you a file (either mode), an accept/reject dialog appears showing the filename and size. Click Yes, choose where to save it, and a live progress dialog tracks the download. Either side can click Cancel to abort at any time.

The file is saved to a .part file during the transfer and renamed to the final filename only when the download completes successfully. If the transfer fails or is cancelled, the partial file is deleted automatically.

Receive limits are enforced before any data is written:

Timeouts

If both sides are behind NAT, neither mode will work — there is no reachable port on either machine. Share the file through another service (Matrix, email, a file host) in that case.

Picking a theme

Uplink ships with 55 built-in color themes. The fastest way is to try them live:

1
Click ☰ → Preferences.
2
Click the theme button (shows your current theme name) to expand the list.
3
Use / to browse, then press Enter or click a theme to apply it. The list stays open so you can keep trying themes.
4
The choice is saved automatically to config.toml. Click the theme button again to collapse the list.

Or set it directly in the config:

[ui]
theme = "catppuccin-mocha"

Popular choices:

NameStyle
catppuccin-mochaDark, muted purple — the fan favourite
catppuccin-latteLight, warm pastels
nordCool blue Arctic palette
draculaDark purple and pink
gruvbox-darkWarm retro dark theme
tokyo-nightDark Tokyo Night
solarized-darkClassic Solarized dark
one-darkAtom One Dark
defaultNative OS look (best on Windows)
Custom themes: drop a .toml file into ~/.config/uplink/themes/ and it appears in the list on next launch. The format matches the shipped themes in the themes/ folder.

Font sizes

Every part of the UI has its own independent font size. Go to ☰ → Preferences → Font Config... and drag the sliders, or set them in config:

[ui]
font_family   = "IBM Plex Mono"   # any installed monospace font

# Each zone is independently sized (all in points)
font_chat     = 11   # message area
font_sidebar  = 10   # server/channel list
font_nick_list= 10   # user list on the right
font_input    = 11   # message input box
font_topic_bar= 10   # topic bar at the top
font_typing   = 9    # "nick is typing..." indicator

Changes from the Font Config dialog are applied and saved immediately — no restart needed.

Nick brackets

The characters that wrap nicks in chat messages are configurable. Set nick_brackets in [ui]:

ValueHow nicks look
"<>"<alice> hello (default)
"[]"[alice] hello
"()"(alice) hello
"{}"{alice} hello
"::::"::alice:: hello
""alice hello (no brackets)
[ui]
nick_brackets = "[]"   # square brackets

You can also change this live from ☰ → Preferences → Nick Brackets.

Show and hide panels

Sidebar (server/channel list)

Click the gear at the top-left of the topic bar. The sidebar collapses; the hamburger and gear stay pinned. Click again to restore. When the sidebar is closed, the chat panel gains equal padding on both sides so the layout stays balanced.

Drag the divider between the sidebar and the chat to resize it. Width is saved on quit.

Nick list (user list)

Click the gear in the header above the user list. The gear spins, then the list collapses. The header and user count stay visible. Click again to expand.

Drag the divider between the chat and the nick panel to resize it. Width is saved on quit.

Topic display

A text bar showing the full channel topic drops below the info bar. Toggle it three ways:

[ui]
show_topic = true   # global default — applies to primary channel view on launch

Nick label in input box

[ui]
show_nick_prefix = false   # hides "alice ▸" next to the input

Fade scrollbars

Scrollbars on the chat view, nick list, sidebar, and channel panes are hidden at rest. They appear when you:

After 3.5 seconds of inactivity, the scrollbar fades out over 300 ms. This keeps the interface clean without hiding the scrollbar when you need it.

Can't find the scrollbar? Move your mouse to the right edge of the chat area or nick list. The scrollbar will appear immediately on hover.

Hanging indent (word wrap alignment)

By default, when a long message wraps to the next line the wrapped text aligns under the message text rather than back at the left edge under the timestamp. This keeps the timestamp and nick visually separate from the message body.

Toggle from ☰ → Preferences → Hanging Indent (wrap under message), or in config:

[ui]
hanging_indent = true   # default on

Turn it off if you prefer the classic flush-left wrap style.

App icon variant

Uplink has two icon variants. Switch at runtime from ☰ → Preferences → App Icon, or set in config:

[ui]
app_icon = "dark"   # "dark" | "light"
ValueDescription
"dark"Dark icon (default)
"light"Light icon, recommended for light OS themes

Tray notifications

When your nick is mentioned or you receive a PM while the window is not focused, a green dot appears on the tray icon. It clears the moment you focus the window.

Toggle from ☰ → Preferences → Tray Notifications, or in config:

[ui]
notifications = true

Troubleshooting — Build errors

CMake can't find Qt6

If Qt is installed but CMake can't find it, pass its location explicitly:

cmake -DCMAKE_PREFIX_PATH=/path/to/Qt6 -B build

On Homebrew macOS:

cmake -DCMAKE_PREFIX_PATH=$(brew --prefix qt) -B build

tomlplusplus not found

Install the package for your platform, or let CMake fetch it automatically (it will on the first run if not found):

# Arch
sudo pacman -S tomlplusplus

# Ubuntu
sudo apt install libtomlplusplus-dev

# Fedora
sudo dnf install tomlplusplus-devel

# FreeBSD
sudo pkg install tomlplusplus

# macOS
brew install tomlplusplus

Linker errors on Linux

Make sure qt6-base, qt6-svg, and the Network module are all installed and that you're linking against Qt6, not Qt5.

Troubleshooting — Config problems

TOML parse error on startup

All string values in TOML must be in double quotes. The # character starts a comment if it appears outside a string.

# Wrong — causes a parse error
name = LinuxDojo

# Correct
name = "LinuxDojo"

Using single brackets for servers

# Wrong — defines a single table, not an array
[server]
name = "LinuxDojo"

# Correct — double brackets = array entry
[[server]]
name = "LinuxDojo"

My config change isn't taking effect

Click ☰ → Reload Config — Uplink restarts and applies all changes, including server list, channels, theme, and font settings.

Troubleshooting — Nick in use

If your nick is taken, Uplink appends _ and tries again (e.g. alice_). The new nick is shown next to the input box. Once the original becomes available, type:

/nick alice

If you have NickServ authentication set up, services may ghost the old connection:

/msg NickServ GHOST alice yourpassword

Troubleshooting — Theme not loading

Uplink stores themes in ~/.config/uplink/themes/ and seeds that folder with all bundled themes on first launch. If themes are missing, delete the folder and restart — it will be recreated and repopulated automatically.

Theme names are case-sensitive and must match the .toml filename exactly (without the extension):

[ui]
theme = "catppuccin-mocha"   # ✓ matches catppuccin-mocha.toml
theme = "Catppuccin-Mocha"   # ✗ won't load — wrong case

To restore a theme you deleted, copy it back from the release tarball's themes/ directory, or from a fresh install.

Troubleshooting — Link previews

Preview didn't appear

Previews disappeared when I switched channels

Preview cards are stored per-channel and reinjected when you switch back. If a card is missing after switching back, the fetch may still be in progress — wait a moment and it will appear.

Troubleshooting — Window too wide to resize

The window opens wider than my screen and I can't make it smaller

This happens when the saved window geometry is wider than the available screen area — common on FreeBSD or after moving to a smaller display. Uplink v0.25.1 fixes this by clamping the window to the screen after it is shown.

If you are already on v0.25.1 and still see the issue, delete the saved layout file so geometry starts fresh:

Linux / FreeBSD
Windows
# Remove any leftover file from older builds
rm -f ~/.config/LinuxDojo/Uplink.conf

# Remove the current layout file (geometry resets to defaults)
rm -f ~/.config/uplink/uplink.conf
del "%APPDATA%\uplink\uplink\uplink.conf"

Relaunch — the window will fit the screen. Your server config and preferences in config.toml are unaffected.

Note: Window geometry, sidebar width, and pane layout are stored separately from config.toml in ~/.config/uplink/uplink.conf (Linux/FreeBSD/macOS) or %APPDATA%\uplink\uplink\uplink.conf (Windows). Deleting it only resets the window layout.