Copperline is a modern terminal IRC client and native SSH relay/bouncer written in Go. It is built for people who still love IRC, but do not want to give up a fast native application, modern IRCv3 features, rich terminal UI, scripting, notifications, persistent sessions, or strong customization.
Copperline is not a toy IRC example and it is not just a thin wrapper around an IRC library. It is an everyday multi-network client with its own buffer model, responsive TUI, persistent logging, DCC, Gotify notifications, Lua scripting, configurable keyboard and mouse controls, true-color themes, IRCv3 support, and an embedded SSH relay system that can keep your IRC sessions alive when your local client is gone.
One Copperline installation can connect directly to IRC, run headlessly as a persistent relay, or act as a local TUI attached to a remote Copperline relay. The relay transport is built directly into Copperline using Go's SSH libraries: no system ssh, no sshd, no web service, no TLS certificate, and no certificate authority are required.



Copperline deliberately combines the things people expect from a traditional IRC client with features that are usually split across a client, a bouncer, shell tools, and notification services.
/raw, and the familiar slash-command workflow all live together.Copperline is designed so the IRC connection, UI, logging, scripting, notifications, relay transport, and DCC code remain separate pieces rather than collapsing into one giant main.go.
Copperline can be its own IRC bouncer.
Run one Copperline instance in relay-server mode on an always-on machine. It maintains the real IRC connections, retains bounded in-memory conversation history, tracks channel state, and accepts Copperline clients over its embedded SSH server.
A relay client runs the normal Copperline TUI locally while the remote relay stays connected to IRC. Closing the local client does not make the relay leave your networks and channels.
Relay mode includes:
authorized_keys file;352, 353, and 354 from the relay transport;The embedded SSH endpoint is intentionally narrow. It does not provide a shell, PTY, SFTP, remote command execution, or SSH port forwarding. It accepts Copperline's private relay channel only.
See RELAY.md for complete setup instructions.
Copperline requests a broad modern capability set while still behaving like a recognizable IRC client. Depending on what the IRC network supports, Copperline can use:
+typing client tags;The negotiated capability set is visible with /caps, and /raw remains available for network-specific features and experiments.
Copperline's interface is designed for long-running everyday use rather than a minimal demo.
F6;Up / Down per-buffer message and command history;Copperline embeds Lua for client-side extension and automation. Scripts can:
Use /lua reload to reload scripts. Copperline performs a physical terminal resync after script reloads to keep the TUI clean.
See SCRIPTING.md for the complete scripting API and scripts/ for examples.
Copperline also includes features that are often missing from smaller terminal IRC clients:
/whois, /me, /notice, /raw, and familiar slash commandsF6 direct jumping, and configurable next/previous shortcutsCopperline requires Go 1.26 or newer. Relay mode uses the September 2026 SSH security fixes in golang.org/x/crypto v0.56.0.
go mod tidy
go build -o Copperline ./cmd/copperline
Check the version with:
./Copperline -version
For the complete TOML reference, defaults, theme options, DCC, SASL, IRCv3 capability settings, keybindings, logging, and relay settings, see CONFIGURATION.md.
For Lua scripts, custom commands, event hooks, and the complete scripting API, see SCRIPTING.md.
For the native SSH relay/bouncer mode, including server/client TOML examples and key setup, see RELAY.md.
Copperline defaults to:
~/.config/copperline/config.toml
or $XDG_CONFIG_HOME/copperline/config.toml when XDG_CONFIG_HOME is set.
Start with config.example.toml:
mkdir -p ~/.config/copperline
cp config.example.toml ~/.config/copperline/config.toml
A different configuration file can be selected with:
./Copperline -config=./my-config.toml
For passwords and tokens, environment variables are preferable to storing secrets directly in TOML. Copperline reads the variable named by password_env, token_env, or the relevant secret setting.
For example, a Libera SASL configuration can use:
[[server]]
name = "libera"
host = "irc.libera.chat"
tls = true
[server.sasl]
mechanism = "plain"
username = "myNick"
password_env = "LIBERA_IRC_PASSWORD"
With fish:
read -s -P 'Libera IRC password: ' LIBERA_IRC_PASSWORD
set -x LIBERA_IRC_PASSWORD $LIBERA_IRC_PASSWORD
./Copperline
For bash or zsh:
export LIBERA_IRC_PASSWORD='your-password-here'
./Copperline
Select the Copperline role in TOML:
[relay]
mode = "direct" # direct, server, or client
A relay server contains the normal [[server]] IRC definitions. A relay client may omit them completely because it receives IRC network and channel state from the relay.
Relay-client mode has a dedicated always-visible reconnect control. By default:
[keybindings]
relay_reconnect = "Alt+R"
Force reconnect tears down only the client's Copperline SSH attachment. It does not tell the relay to disconnect from IRC.
See RELAY.md for host-key fingerprint setup, generated client keys, authorized_keys, server/client configuration, retained history, and security notes.
Logging is enabled by default. Copperline can show a small persisted conversation preview from before the current process/session while keeping current-session messages in normal live styling.
Disable all on-disk IRC logs while keeping normal in-memory scrollback with:
[general]
logging = false
The default log location is:
~/.local/state/copperline/logs/<server>/<buffer>.log
Log files are created with mode 0600; directories use 0700.
Copperline can push incoming mentions and private messages to Gotify. Gotify delivery is asynchronous so a slow or unavailable notification service does not freeze IRC or the TUI.
[gotify]
enabled = true
url = "https://push.example.com"
token_env = "COPPERLINE_GOTIFY_TOKEN"
mentions = true
private_messages = true
priority = 5
timeout_seconds = 5
Test it from Copperline with:
/gotify test
Copperline ships with a dark navy/copper/aqua theme, but the entire TUI palette can be overridden with [theme].
[theme]
background = "#090d16"
panel = "#101827"
foreground = "#d8dee9"
muted = "#77839a"
border = "#36506b"
title = "#64d8cb"
selected_fg = "#071018"
selected_bg = "#d99058"
timestamp = "#77839a"
server = "#64d8cb"
channel = "#8bd49c"
query = "#d9a7ff"
unread = "#f6c177"
mention = "#ff9ecb"
notice = "#f6c177"
action = "#d9a7ff"
system = "#72c7ef"
error = "#ff6b81"
dcc = "#8bd49c"
topic = "#f2cc8f"
input = "#eef1f6"
cursor_fg = "#071018"
cursor_bg = "#64d8cb"
status_fg = "#071018"
status_bg = "#64d8cb"
nick_colors = ["#ff7b72", "#f6c177", "#8bd49c", "#64d8cb", "#72c7ef", "#d9a7ff"]
Nick colors are chosen deterministically from nick_colors, so the same nickname keeps the same color.
Copperline embeds Lua for client-side automation and customization. Scripts load from ~/.config/copperline/scripts/*.lua by default and can register slash commands, hook IRC events, send messages/notices, write to buffers, and use raw IRC.
Use:
/lua reload
to reload scripts without restarting Copperline.
The complete API lives in SCRIPTING.md, and the source tree includes ready-to-copy examples in scripts/.
The left panel contains servers and channel/query buffers. Every visible buffer is numbered. The middle panel contains the current conversation. Wide terminals also get a nick list on the right. The topic sits above the transcript, and the message input and status/control area sit at the bottom.
All action bindings are configurable under [keybindings]. Default controls include:
Ctrl-N: next bufferCtrl-P: previous bufferAlt-N: scroll the right-hand user list downAlt-P: scroll the right-hand user list upF6, number, Enter: jump directly to a numbered bufferEscape: cancel buffer jumpTab: nickname completion; repeated Tab cycles matchesUp / Down: older/newer input history for the current bufferPageUp / PageDown: transcript by pageAlt-K / Alt-J: transcript by one lineAlt-L: bare/copy mode for terminal text selectionEnd: return to/follow newest messagesAlt-R: force reconnect to a Copperline relay while in relay-client modeCtrl-U: clear inputCtrl-C: quitFor example:
[keybindings]
user_list_down = "Ctrl+Y"
user_list_up = "Ctrl+U"
history_previous = "Up"
history_next = "Down"
relay_reconnect = "Alt+R"
If you reassign a binding such as Ctrl+U, move any conflicting action to another key. Copperline validates configurable action keys so invalid or conflicting bindings fail clearly instead of silently doing something unexpected.
Input history is session-only and separate for each buffer. It stores both ordinary messages and slash commands. The default is 10 entries per buffer and is configurable with:
[general]
input_history_limit = 10
Set it to 0 to disable input history.
Press Alt-L for bare/copy mode. Copperline temporarily hides the normal UI chrome and disables terminal mouse reporting so the terminal can perform normal text selection. IRC, logging, Gotify, DCC, scripting, and incoming message state continue in the background.
/help
/buffer number
/server [name]
/connect [server]
/disconnect [server] [reason]
/join #channel [key]
/part [#channel] [reason]
/query nick
/msg nick message
/me action
/notice target message
/ctcp nick command [text]
/nick newnick
/topic new topic
/whois nick
/raw IRC COMMAND HERE
/history [count]
/markread
/caps
/dcc list
/dcc accept nick
/dcc send nick /path/to/file
/gotify status
/gotify test
/lua list
/lua reload
/lua eval <code>
/close
/quit [reason]
CTCP examples:
/ctcp Alice VERSION
/ctcp Alice TIME
/ctcp Alice PING 123456789
Capabilities currently requested by default include:
account-notify
account-tag
away-notify
batch
cap-notify
chghost
echo-message
extended-join
invite-notify
labeled-response
message-tags
multi-prefix
server-time
setname
standard-replies
userhost-in-names
draft/chathistory
draft/event-playback
draft/extended-monitor
draft/message-redaction
draft/multiline
draft/no-implicit-names
draft/read-marker
Not every requested draft capability has a dedicated UI action yet. /raw remains available for experimenting with network-specific IRCv3 commands and extensions.
Traditional DCC establishes a direct TCP connection between IRC users. It is not protected by the TLS connection to the IRC server and can reveal IP addresses.
For outgoing DCC SEND, configure dcc.advertise_ip to an address the other user can reach. NAT/router port forwarding may be necessary. Incoming filenames are reduced to their basename, downloads use exclusive file creation, and existing files are not overwritten.
Copperline currently implements normal active DCC SEND and incoming DCC CHAT. Passive/reverse DCC SEND (port 0) and DCC RESUME are possible future additions.
cmd/copperline/ program entry point
internal/config/ TOML configuration
internal/model/ buffers and messages
internal/irc/ direct multi-server IRC + IRCv3 backend
internal/relay/ embedded SSH relay server/client and protocol
internal/logging/ persistent logs and pre-session backlog
internal/gotify/ Gotify notification client
internal/dcc/ DCC parsing and transfers
internal/scripting/ embedded Lua runtime and scripting API
scripts/ example Lua scripts
internal/tui/ gotui interface, navigation, input, and commands
Copperline highlights incoming messages and /me actions that mention your current nickname. The mention color is configurable with theme.mention. Your own outgoing messages are never highlighted as mentions.
Copperline is licensed under the GNU General Public License version 3 or later (GPL-3.0-or-later). See LICENSE.
16 commits
Go
95.4%
Lua
4.6%
Copperline is a modern terminal IRC client and native SSH relay/bouncer written in Go. It is built for people who still love IRC, but do not want to give up a fast native application, modern IRCv3 features, rich terminal UI, scripting, notifications, persistent sessions, or strong customization.
Copperline is not a toy IRC example and it is not just a thin wrapper around an IRC library. It is an everyday multi-network client with its own buffer model, responsive TUI, persistent logging, DCC, Gotify notifications, Lua scripting, configurable keyboard and mouse controls, true-color themes, IRCv3 support, and an embedded SSH relay system that can keep your IRC sessions alive when your local client is gone.
One Copperline installation can connect directly to IRC, run headlessly as a persistent relay, or act as a local TUI attached to a remote Copperline relay. The relay transport is built directly into Copperline using Go's SSH libraries: no system ssh, no sshd, no web service, no TLS certificate, and no certificate authority are required.



Copperline deliberately combines the things people expect from a traditional IRC client with features that are usually split across a client, a bouncer, shell tools, and notification services.
/raw, and the familiar slash-command workflow all live together.Copperline is designed so the IRC connection, UI, logging, scripting, notifications, relay transport, and DCC code remain separate pieces rather than collapsing into one giant main.go.
Copperline can be its own IRC bouncer.
Run one Copperline instance in relay-server mode on an always-on machine. It maintains the real IRC connections, retains bounded in-memory conversation history, tracks channel state, and accepts Copperline clients over its embedded SSH server.
A relay client runs the normal Copperline TUI locally while the remote relay stays connected to IRC. Closing the local client does not make the relay leave your networks and channels.
Relay mode includes:
authorized_keys file;352, 353, and 354 from the relay transport;The embedded SSH endpoint is intentionally narrow. It does not provide a shell, PTY, SFTP, remote command execution, or SSH port forwarding. It accepts Copperline's private relay channel only.
See RELAY.md for complete setup instructions.
Copperline requests a broad modern capability set while still behaving like a recognizable IRC client. Depending on what the IRC network supports, Copperline can use:
+typing client tags;The negotiated capability set is visible with /caps, and /raw remains available for network-specific features and experiments.
Copperline's interface is designed for long-running everyday use rather than a minimal demo.
F6;Up / Down per-buffer message and command history;Copperline embeds Lua for client-side extension and automation. Scripts can:
Use /lua reload to reload scripts. Copperline performs a physical terminal resync after script reloads to keep the TUI clean.
See SCRIPTING.md for the complete scripting API and scripts/ for examples.
Copperline also includes features that are often missing from smaller terminal IRC clients:
/whois, /me, /notice, /raw, and familiar slash commandsF6 direct jumping, and configurable next/previous shortcutsCopperline requires Go 1.26 or newer. Relay mode uses the September 2026 SSH security fixes in golang.org/x/crypto v0.56.0.
go mod tidy
go build -o Copperline ./cmd/copperline
Check the version with:
./Copperline -version
For the complete TOML reference, defaults, theme options, DCC, SASL, IRCv3 capability settings, keybindings, logging, and relay settings, see CONFIGURATION.md.
For Lua scripts, custom commands, event hooks, and the complete scripting API, see SCRIPTING.md.
For the native SSH relay/bouncer mode, including server/client TOML examples and key setup, see RELAY.md.
Copperline defaults to:
~/.config/copperline/config.toml
or $XDG_CONFIG_HOME/copperline/config.toml when XDG_CONFIG_HOME is set.
Start with config.example.toml:
mkdir -p ~/.config/copperline
cp config.example.toml ~/.config/copperline/config.toml
A different configuration file can be selected with:
./Copperline -config=./my-config.toml
For passwords and tokens, environment variables are preferable to storing secrets directly in TOML. Copperline reads the variable named by password_env, token_env, or the relevant secret setting.
For example, a Libera SASL configuration can use:
[[server]]
name = "libera"
host = "irc.libera.chat"
tls = true
[server.sasl]
mechanism = "plain"
username = "myNick"
password_env = "LIBERA_IRC_PASSWORD"
With fish:
read -s -P 'Libera IRC password: ' LIBERA_IRC_PASSWORD
set -x LIBERA_IRC_PASSWORD $LIBERA_IRC_PASSWORD
./Copperline
For bash or zsh:
export LIBERA_IRC_PASSWORD='your-password-here'
./Copperline
Select the Copperline role in TOML:
[relay]
mode = "direct" # direct, server, or client
A relay server contains the normal [[server]] IRC definitions. A relay client may omit them completely because it receives IRC network and channel state from the relay.
Relay-client mode has a dedicated always-visible reconnect control. By default:
[keybindings]
relay_reconnect = "Alt+R"
Force reconnect tears down only the client's Copperline SSH attachment. It does not tell the relay to disconnect from IRC.
See RELAY.md for host-key fingerprint setup, generated client keys, authorized_keys, server/client configuration, retained history, and security notes.
Logging is enabled by default. Copperline can show a small persisted conversation preview from before the current process/session while keeping current-session messages in normal live styling.
Disable all on-disk IRC logs while keeping normal in-memory scrollback with:
[general]
logging = false
The default log location is:
~/.local/state/copperline/logs/<server>/<buffer>.log
Log files are created with mode 0600; directories use 0700.
Copperline can push incoming mentions and private messages to Gotify. Gotify delivery is asynchronous so a slow or unavailable notification service does not freeze IRC or the TUI.
[gotify]
enabled = true
url = "https://push.example.com"
token_env = "COPPERLINE_GOTIFY_TOKEN"
mentions = true
private_messages = true
priority = 5
timeout_seconds = 5
Test it from Copperline with:
/gotify test
Copperline ships with a dark navy/copper/aqua theme, but the entire TUI palette can be overridden with [theme].
[theme]
background = "#090d16"
panel = "#101827"
foreground = "#d8dee9"
muted = "#77839a"
border = "#36506b"
title = "#64d8cb"
selected_fg = "#071018"
selected_bg = "#d99058"
timestamp = "#77839a"
server = "#64d8cb"
channel = "#8bd49c"
query = "#d9a7ff"
unread = "#f6c177"
mention = "#ff9ecb"
notice = "#f6c177"
action = "#d9a7ff"
system = "#72c7ef"
error = "#ff6b81"
dcc = "#8bd49c"
topic = "#f2cc8f"
input = "#eef1f6"
cursor_fg = "#071018"
cursor_bg = "#64d8cb"
status_fg = "#071018"
status_bg = "#64d8cb"
nick_colors = ["#ff7b72", "#f6c177", "#8bd49c", "#64d8cb", "#72c7ef", "#d9a7ff"]
Nick colors are chosen deterministically from nick_colors, so the same nickname keeps the same color.
Copperline embeds Lua for client-side automation and customization. Scripts load from ~/.config/copperline/scripts/*.lua by default and can register slash commands, hook IRC events, send messages/notices, write to buffers, and use raw IRC.
Use:
/lua reload
to reload scripts without restarting Copperline.
The complete API lives in SCRIPTING.md, and the source tree includes ready-to-copy examples in scripts/.
The left panel contains servers and channel/query buffers. Every visible buffer is numbered. The middle panel contains the current conversation. Wide terminals also get a nick list on the right. The topic sits above the transcript, and the message input and status/control area sit at the bottom.
All action bindings are configurable under [keybindings]. Default controls include:
Ctrl-N: next bufferCtrl-P: previous bufferAlt-N: scroll the right-hand user list downAlt-P: scroll the right-hand user list upF6, number, Enter: jump directly to a numbered bufferEscape: cancel buffer jumpTab: nickname completion; repeated Tab cycles matchesUp / Down: older/newer input history for the current bufferPageUp / PageDown: transcript by pageAlt-K / Alt-J: transcript by one lineAlt-L: bare/copy mode for terminal text selectionEnd: return to/follow newest messagesAlt-R: force reconnect to a Copperline relay while in relay-client modeCtrl-U: clear inputCtrl-C: quitFor example:
[keybindings]
user_list_down = "Ctrl+Y"
user_list_up = "Ctrl+U"
history_previous = "Up"
history_next = "Down"
relay_reconnect = "Alt+R"
If you reassign a binding such as Ctrl+U, move any conflicting action to another key. Copperline validates configurable action keys so invalid or conflicting bindings fail clearly instead of silently doing something unexpected.
Input history is session-only and separate for each buffer. It stores both ordinary messages and slash commands. The default is 10 entries per buffer and is configurable with:
[general]
input_history_limit = 10
Set it to 0 to disable input history.
Press Alt-L for bare/copy mode. Copperline temporarily hides the normal UI chrome and disables terminal mouse reporting so the terminal can perform normal text selection. IRC, logging, Gotify, DCC, scripting, and incoming message state continue in the background.
/help
/buffer number
/server [name]
/connect [server]
/disconnect [server] [reason]
/join #channel [key]
/part [#channel] [reason]
/query nick
/msg nick message
/me action
/notice target message
/ctcp nick command [text]
/nick newnick
/topic new topic
/whois nick
/raw IRC COMMAND HERE
/history [count]
/markread
/caps
/dcc list
/dcc accept nick
/dcc send nick /path/to/file
/gotify status
/gotify test
/lua list
/lua reload
/lua eval <code>
/close
/quit [reason]
CTCP examples:
/ctcp Alice VERSION
/ctcp Alice TIME
/ctcp Alice PING 123456789
Capabilities currently requested by default include:
account-notify
account-tag
away-notify
batch
cap-notify
chghost
echo-message
extended-join
invite-notify
labeled-response
message-tags
multi-prefix
server-time
setname
standard-replies
userhost-in-names
draft/chathistory
draft/event-playback
draft/extended-monitor
draft/message-redaction
draft/multiline
draft/no-implicit-names
draft/read-marker
Not every requested draft capability has a dedicated UI action yet. /raw remains available for experimenting with network-specific IRCv3 commands and extensions.
Traditional DCC establishes a direct TCP connection between IRC users. It is not protected by the TLS connection to the IRC server and can reveal IP addresses.
For outgoing DCC SEND, configure dcc.advertise_ip to an address the other user can reach. NAT/router port forwarding may be necessary. Incoming filenames are reduced to their basename, downloads use exclusive file creation, and existing files are not overwritten.
Copperline currently implements normal active DCC SEND and incoming DCC CHAT. Passive/reverse DCC SEND (port 0) and DCC RESUME are possible future additions.
cmd/copperline/ program entry point
internal/config/ TOML configuration
internal/model/ buffers and messages
internal/irc/ direct multi-server IRC + IRCv3 backend
internal/relay/ embedded SSH relay server/client and protocol
internal/logging/ persistent logs and pre-session backlog
internal/gotify/ Gotify notification client
internal/dcc/ DCC parsing and transfers
internal/scripting/ embedded Lua runtime and scripting API
scripts/ example Lua scripts
internal/tui/ gotui interface, navigation, input, and commands
Copperline highlights incoming messages and /me actions that mention your current nickname. The mention color is configurable with theme.mention. Your own outgoing messages are never highlighted as mentions.
Copperline is licensed under the GNU General Public License version 3 or later (GPL-3.0-or-later). See LICENSE.
16 commits
Go
95.4%
Lua
4.6%