Uplink How-To Guide
Everything from installation to tweaks, step by step.
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.
#), 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.
| Platform | Download | How 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 |
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.
~/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.
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.
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.
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.
| Platform | Path |
|---|---|
| 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"
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:
| Network | Host | Port |
|---|---|---|
| LinuxDojo | irc.linuxdojo.org | 6697 |
| Libera.Chat | irc.libera.chat | 6697 |
| OFTC | irc.oftc.net | 6697 |
| EFnet | irc.efnet.org | 6697 |
| IRCnet | open.ircnet.net | 6697 |
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
| Section | Fields |
|---|---|
| Connection | Name (display name in sidebar), Host, Port, SSL checkbox |
| Identity | Nick, Username, Real Name |
| Authentication | Server 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) |
| Channels | Auto-join — comma-separated (e.g. #uplink, #linux). See note below for password-protected channels. |
| Bouncer | Type: None / ZNC / Soju. Network name (soju only). |
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.
| Platform | Backend |
|---|---|
| Linux | Secret Service (GNOME Keyring, KWallet, or any compatible daemon) |
| macOS | macOS Keychain |
| Windows | Windows 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.
qWarning messages from Uplink if authentication is failing unexpectedly.
<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.
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.
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.
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:
| Scenario | What Uplink does |
|---|---|
| Plain connection — server advertises STS | Immediately disconnects and reconnects over TLS on the server-specified port. Stores the policy. |
| TLS connection — server advertises STS | Refreshes the stored policy expiry. No reconnect needed — already encrypted. |
Server sends duration=0 | Deletes the cached policy. Plain connections permitted again. |
| Cached policy is expired | Removed 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.
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
- username — your ZNC login name (set when ZNC was installed)
- network — the name of the IRC network inside ZNC (e.g.
libera,oftc). Check your ZNC web panel or/znc ListNetworksto see the exact names. - password — your ZNC account 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
Setting up ZNC in Manage Servers
6697 for SSL or 6667 for plain). Check Use SSL/TLS if your ZNC has SSL enabled (recommended).username/network:password format. Example: alice/libera:hunter2. Leave all SASL fields blank.#linux, #archlinuxConfig 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:
| Capability | What it does |
|---|---|
znc.in/playback | Requests 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-message | Echoes 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"
/znc ListNetworks in the server buffer. ZNC will reply with the exact names to use in the password.
Troubleshooting
| Symptom | Likely cause |
|---|---|
| Password incorrect / access denied | Wrong 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 join | The 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 connect | znc.in/playback not loaded in ZNC. Enable the playback module in ZNC's web panel under your network's modules. |
| TLS errors | Port 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
6697 SSL. Check Use SSL/TLS.username:password. Example: alice:hunter2. Leave SASL fields blank.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
| Capability | What it does |
|---|---|
soju.im/bouncer-networks | Lists 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/read | Syncs your read position across all connected clients. If you read a message on your phone, Uplink on your desktop already knows. |
chathistory / draft/chathistory | Requests 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"
bouncer_network. soju will list all available networks in the server buffer automatically via soju.im/bouncer-networks.
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 / Bouncer | Cap name advertised | Notes |
|---|---|---|
| Ergo IRCd | draft/chathistory | Requires history: block in ircd.yaml and a server restart (not just rehash) to initialise the history DB. |
| soju | chathistory | Works out of the box — soju stores and replays history natively. |
| ZNC | chathistory | Requires the playback module. Uplink enables it automatically when bouncer = "znc". |
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:
- Displayed at reduced opacity (dimmed).
- Timestamped with their original send time. Messages from a previous day include the date:
06/08 14:32. - Not counted as unread — they do not badge the channel in the sidebar.
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.
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"
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.
- Left side — always shows the
☰hamburger menu and the⚙gear. These are always visible regardless of sidebar state. - Right side — shows the signal bars, current channel name, channel modes, and user count.
☰ 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.
Layout
The chat area restructures automatically as panes are added:
| Panes open | Layout |
|---|---|
| 1 | Full width (normal single-channel view) |
| 2 | Side by side — equal halves |
| 3 | Primary channel full-height on the left; two panes stacked on the right |
| 4 | 2×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:
- A speech bubble icon — click to show or hide the primary channel's topic text independently of the global Preferences setting. The icon is muted when the topic is hidden and accent-colored when visible. It is always present, even in single-window mode with no extra panes open.
- The current channel name in bold.
- A
✕button — only visible when extra panes are open. Collapses the primary column so the panes fill the screen. Click any channel in the sidebar to bring it back.
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
- Maximum 4 panes total (1 primary + 3 extras).
- The same channel cannot appear in both the primary view and a pane simultaneously. If you open a channel that is already shown in the primary, the primary shifts to the server buffer automatically.
- Left-clicking a channel that is open in a pane navigates the primary to it and closes the pane.
- All slash commands work in pane input bars —
/join,/nick,/me, and every other command behave the same as in the primary input bar. - Tab completion works in pane input bars. Pressing Tab completes nicks from that pane's own channel, not the primary channel — so you always get the right suggestions regardless of which input is focused.
- Font sizes set in Preferences → Font Config apply consistently to all panes — chat text, nick list, topic bar, and input label all inherit the same configured sizes whether the pane is opened at launch or mid-session.
- Right-clicking a message timestamp in a pane gives the same context menu as the primary view — Reply, React, Delete (your own messages), and Copy.
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:
| Symbol | Event |
|---|---|
| → | 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:
- Seeing the full hostmask of someone who just joined (to check for a ban match, for example)
- Reading quit and part reasons without /whowas
- Verifying exactly when each event happened when multiple nicks arrive in the same second
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.
- Click any URL to open it in your browser.
- When a URL is posted, Uplink fetches a preview card (title + thumbnail) automatically.
- When someone mentions your nick, it is highlighted in red and bold.
- A "nick is typing…" line appears above the input bar when another user is composing a message and their client supports IRCv3
draft/typing. You never see your own typing indicator — it is only shown to others. - Right-click the timestamp (hh:mm) on any message for a context menu: Reply, React, and Delete (own messages only, when the server supports it). If you have text selected when you right-click the timestamp, a Copy option appears in the same menu. See Reply, Reactions, and Message deletion.
- Right-click selected text anywhere in a message to see a Copy option — and a Reply option for the message you clicked in, so you do not need to aim at the small timestamp.
- Right-click any nick in a message to open the nick context menu — Message, Send File, Whois, Invite, Give Op, Take Op, Give Voice, Take Voice, Version, Ping, Copy Nick, and (for ops) Kick, Ban, Kick & Ban. See Nick right-click menu.
- Hover over a nick in a message to see their NickServ account name as a tooltip (when the server reports it via
account-tagoraccount-notify). - Press Ctrl+F to search the current buffer. See Message search.
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.
| Scenario | What happens |
|---|---|
You start typing in #linux | Other users in #linux see "yournick is typing…" — you do not |
Alice starts typing in #linux | You see "alice is typing…" above your input bar |
| Alice stops typing without sending | The indicator disappears after a few seconds |
| Alice sends her message | The indicator disappears as soon as the message arrives |
| Multiple people typing at once | Each 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
TAGMSG with the +typing=active tag to the channel as you type. If you prefer not to broadcast this, disable the feature in Preferences.
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.
- Click the
⚙gear to collapse or expand the panel. The gear animates a full spin before toggling. - Drag the divider between the chat and the nick panel to resize it — width is saved.
- Nicks are sorted by prefix rank:
~owner,&admin,@op,%halfop,+voice, then alphabetical. - Nicks with
+B(bot mode) show a small icon drawn inline to the right of their name — either a robot or an alien, randomly assigned per nick for the session. The icon is colorized to your active theme's accent color and does not depend on any emoji font. - Hover over any nick to see their NickServ account name as a tooltip (shown as
account: namewhen the server has reported it). - Selected and hovered nicks are highlighted with a pill-shaped background in your theme's accent colour — the same style used in the server/channel sidebar.
- Right-click any nick for a full action menu — see Nick right-click menu below.
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:
- Chat view — hover over a nick link in any message. The tooltip appears after a brief pause showing:
account: alice_libera
- Nick list panel — hover over any nick in the right-side user list. Same tooltip format.
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:
| Source | When it fires | What 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.
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.
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
- Open ☰ → Preferences and scroll to the Profile section at the bottom.
- Enter your Display Name — the friendly name other users see in the tooltip (e.g. Alice Smith). It does not replace your IRC nick.
-
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.
- Web URL (e.g.
- 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.
| Command | Effect |
|---|---|
/displayname Alice Smith | Set display name to "Alice Smith" |
/displayname | Clear your display name |
/avatar https://…/pic.png | Set avatar to a web URL (visible to others) |
/avatar /home/alice/avatar.png | Set avatar to a local file (visible only to you) |
/avatar | Clear 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.
| Appearance | Meaning |
|---|---|
| 4 solid green bars | Connected, latency < 50 ms (excellent) |
| 3 solid green bars | Connected, latency 50–149 ms (good) |
| 2 solid green bars | Connected, latency 150–299 ms (fair) |
| 1 solid green bar | Connected, latency ≥ 300 ms (high lag) |
| Blue flashing | Connecting or reconnecting |
| Red flashing | Disconnected |
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.
- Left-click the tray icon to show or hide the window.
- Right-click for a menu with Show and Quit.
- A green dot on the tray icon means you have an unread mention or PM and the window is not focused. It clears when you focus the window.
- A red dot means there are unread messages in any channel.
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.
| Command | What it does | Example |
|---|---|---|
/join #channel | Join a channel | /join #linux |
/part [reason] | Leave the current channel | /part goodbye |
/leave | Leave the channel — or close a PM/query window | /leave |
/close | Same as /leave — closes a PM window or parts a channel | /close |
/nick newnick | Change your nickname | /nick alice_ |
/me action | CTCP action | /me waves |
/msg nick text | Send a private message | /msg bob hey there |
/topic text | Set the channel topic (requires op) | /topic Welcome! |
/kick nick reason | Kick a user (requires op) | /kick bob bye |
/op nick | Give someone channel op | /op bob |
/voice nick | Give someone voice | /voice carol |
/ban mask | Ban a hostmask | /ban *!*@badhost.net |
/ping nick | Measure round-trip time to a nick — reply appears in the active channel | /ping bob |
/whois nick | Full user info (hostname, channels, idle time, account) — reply appears in the active channel | /whois bob |
/whowas nick | History for a departed nick — last known user@host and realname — reply appears in the active channel | /whowas bob |
/setname realname | Change 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 query | Request server statistics — results appear in the active channel | /stats u |
/time | Query the server's local time | /time |
/version nick | Ask 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 list | Show your current watch list | |
/monitor clear | Clear all watched nicks | |
/monitor status | Request current online/offline status | |
/ignore nick | Suppress all messages from a nick | /ignore spammer |
/unignore nick | Remove a nick from the ignore list | /unignore spammer |
/ignored | List all ignored nicks | |
/ns text | Shortcut for PRIVMSG NickServ | /ns identify pass |
/cs text | Shortcut for PRIVMSG ChanServ | /cs op #uplink |
/away message | Set yourself away | /away at lunch |
/back | Clear your away status | /back |
/clear | Clear the chat buffer | /clear |
/raw line | Send a raw IRC protocol line to the server | /raw MODE #uplink +m |
/quote line | Alias for /raw | /quote INVITE alice #uplink |
/ANYTHING | Any unrecognized command is sent as-is — no prefix needed | /REHASH, /SAMODE #uplink +o alice |
/quit [message] | Disconnect | /quit see ya |
/sysinfo | Collect OS/CPU/RAM/GPU/uptime info and post to channel — confirms before posting; collection runs async with 12s timeout | /sysinfo |
/help | List all commands | /help |
/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 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.
/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)
/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:
| Result | What it indicates |
|---|---|
| 1–50 ms | Same region or same server — very low latency |
| 50–150 ms | Different country or continent — normal for international chat |
| 150–400 ms | High latency — possibly a satellite connection or slow network path |
| No reply | The nick has CTCP PING blocked, or their client does not support it |
# 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:
- Whois — same as
/whois nick - Version — same as
/version nick - Ping — same as
/ping nick
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
- Click any column header (Channel, Users, Topic) to sort by that column. Click again to reverse. User count sorts numerically by default (highest first).
- Type in the filter box at the top to narrow results — it matches against channel name and topic simultaneously.
Joining a channel
- Double-click any row, or select a row and click Join, to join that channel.
- The dialog stays open after you join so you can browse and join more channels.
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.
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.
| Command | What it returns |
|---|---|
/stats u | Server uptime |
/stats o | IRC operator list |
/stats m | Command 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.
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".
/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:
| Command | Sends to | Example |
|---|---|---|
/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.
/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.
/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:
| Code | Effect |
|---|---|
| Ctrl+B (bold marker) | Bold text |
| Ctrl+I | Italic text |
| Ctrl+U | Underline text |
| Ctrl+S | |
| 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.
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.
- Type the first few letters of a nick and press Tab. If there is one match, it fills in immediately. If there are several, pressing Tab again cycles through them in alphabetical order.
- Works for commands too — type
/joand press Tab to get/join. Cycles through all matching commands on repeated presses. - At the start of a line, the completed nick gets a colon appended:
alice:— the standard IRC convention for addressing someone directly. - Tab completion in a channel pane uses the nick list for that pane's channel, not the primary channel. You always get the right nicks regardless of which input is focused.
- Pressing any other key after a completion resets the cycle, so you can start a new completion at any point.
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.
Message search (Ctrl+F)
Press Ctrl+F anywhere in Uplink to open a search bar below the chat area. Start typing and the first match jumps into view immediately with the text highlighted.
| Key | Action |
|---|---|
| Enter | Jump to the next match (wraps around to the top) |
| Shift+Enter | Jump to the previous match |
| Escape | Close the search bar and clear the highlight |
✕ button | Close the search bar |
Ctrl+F works whether you are focused on the chat view or the message input box.
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:
Option B — right-click the timestamp:
hh:mm at the far left of the message).After choosing Reply (either way):
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
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.
Reactions
Uplink supports IRCv3 draft/react — emoji reactions attached to specific messages. Both sending and receiving are supported.
Sending a reaction
hh:mm at the left of the message).: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)
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.
The message is replaced with [message deleted] in grey italic. Other clients that support draft/message-redaction will also hide the message.
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.
| Command | What it does |
|---|---|
/monitor add <nick> | Start watching this nick |
/monitor del <nick> | Stop watching this nick |
/monitor list | Show your current watch list |
/monitor clear | Remove all watched nicks |
/monitor status | Ask 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.
Link previews
Link previews are disabled by default. To enable them, click ☰ → Preferences and check Link Previews, or add the following to config.toml:
[privacy] link_previews = true
When enabled, any message containing a URL causes Uplink to fetch a preview card and append it below the message:
- Web pages — shows the page title (from
og:titleor<title>) and a thumbnail if an Open Graph image is set. - Direct image links —
.png .jpg .jpeg .gif .webpURLs are detected and shown as a thumbnail without any HTML parsing.
Previews are lightweight — HTML is capped at 32 KB, images at 200 KB, results are cached for the session (up to 50 cards; oldest evicted automatically). Private/LAN addresses are never fetched. When multiple URLs arrive at once, preview cards are fetched sequentially (up to 10 queued) so they do not compete with each other.
Interacting with preview cards
- Left-click a preview card → opens the URL in your default browser.
- Right-click a preview card → context menu: Open URL / Hide Preview.
- Right-click the URL text in chat → context menu: Copy URL / Open URL / Hide Preview / Show Preview (if hidden).
- Hover any URL → tooltip shows the domain, then updates to the page title once fetched.
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?
| Mode | When 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)
Sending a file (passive — use behind NAT)
port=0 — a signal that the recipient should open the port.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:
- Maximum file size: 2 GiB. Offers larger than this are rejected before the dialog appears.
- Disk space check. Available space on the destination drive must exceed the advertised file size, or the transfer is rejected with an error.
Timeouts
- Active sender: 60 seconds to receive an incoming connection before the offer is cancelled.
- Active receiver: 30 seconds to connect to the sender before giving up.
- Passive receiver (listening for sender): 60 seconds to receive an incoming connection.
Picking a theme
Uplink ships with 55 built-in color themes. The fastest way is to try them live:
config.toml. Click the theme button again to collapse the list.Or set it directly in the config:
[ui] theme = "catppuccin-mocha"
Popular choices:
| Name | Style |
|---|---|
catppuccin-mocha | Dark, muted purple — the fan favourite |
catppuccin-latte | Light, warm pastels |
nord | Cool blue Arctic palette |
dracula | Dark purple and pink |
gruvbox-dark | Warm retro dark theme |
tokyo-night | Dark Tokyo Night |
solarized-dark | Classic Solarized dark |
one-dark | Atom One Dark |
default | Native OS look (best on Windows) |
.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]:
| Value | How 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:
- Globally — ☰ → Preferences → Show Topic Bar, or set
show_topic = truein config. Applies to the main channel view. - Per pane — each channel pane has a ▸ topic / ▾ topic oval button in its header. Click to show or hide that pane's topic independently. The topic bar appears automatically when a pane first opens if the channel has a topic set.
- Primary column header — when panes are open, the same oval topic button appears in the primary channel's header. It is independent of the global Preferences toggle.
[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:
- Scroll with the mouse wheel or keyboard
- Click or drag the scrollbar track
- Hover over the scrollbar area
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.
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"
| Value | Description |
|---|---|
"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
- Are link previews enabled? They are off by default. Click ☰ → Preferences and check Link Previews, or add
link_previews = trueunder[privacy]inconfig.toml. - The site may block bots — Uplink uses a messaging-app user-agent, but some sites still block.
- The page may have no
og:titleor<title>— nothing to show. - SSL certificate errors block the fetch silently (self-signed or expired certs).
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:
# 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.
config.toml in ~/.config/uplink/uplink.conf (Linux/FreeBSD/macOS) or %APPDATA%\uplink\uplink\uplink.conf (Windows). Deleting it only resets the window layout.