Halloy

halloy

Halloy is an open-source IRC client written in Rust, with the iced GUI library. It aims to provide a simple and fast client for Mac, Windows, and Linux platforms.

Contributing

Halloy is free and open source. You can find the source code as well as report issues and feature requests on GitHub.

Installing Halloy

💡 To get the latest nightly version of Halloy, you can build from source.

Pre-built binaries

Download pre-built binaries from GitHub page.

Packaging status

Packaging status

macOS

The following third party repositories are available for macOS

Homebrew

brew install --cask halloy 

MacPorts

sudo port install halloy

Linux

The following third party repositories are available for Linux

Flatpak

https://flathub.org/apps/org.squidowl.halloy

Snapcraft

https://snapcraft.io/halloy

Windows

Winget

winget install squidowl.halloy

Build from source

Clone the Halloy GitHub repository into a directory of your choice and build with cargo.

Requirements:

# Clone the repository
git clone https://github.com/squidowl/halloy.git

cd halloy

# Build and run
cargo build --release
cargo run --release

Getting started

To get started with Halloy, you need to connect to at least one IRC server. The template config file has been set up with the Libera server. However, there are many other servers available: OFTC, Undernet, EFnet, QuakeNet and many more. Halloy can connect to multiple servers at the same time.

Once connected to a server, you can join channels. This can be done automatically from the config file or manually using the join command: /join #channel1. To find channels, you can either use the list command: /list, or browse for channels online.

💡 Configuration in Halloy happens through a config.toml file. See Configuration.

Here are a few useful IRC commands for a new user2

CommandExampleDescription
/join/join #halloyJoin a new channel
/part/part #halloyPart a channel
/nick/nick halloyisgreatChange your nickname
/whois nickname/whois halloyisgreatDisplays information of nickname requested
/list *keyword*/list *linux*List channels. Keyword is optional
1

Channel names always start with a # symbol and do not contain spaces.

2

Find more commands here.

Get in touch

Join #halloy on libera.chat (link) if you have questions, looking for help or just want to say hello. For feature requests or reporting issues, please open a ticket on GitHub.

Maintainers

Connect with Soju

To connect with a soju bouncer, the configuration below can be used as a template. Simply change so it fits your credentials.

[servers.libera]
nickname = "casperstorm"
username = "<your-username>/irc.libera.chat@desktop"
server = "irc.squidowl.org"
port = 6697
password = "<your-password>"
chathistory = true

Connect with ZNC

To connect with a ZNC bouncer, the configuration below can be used as a template. Simply change so it fits your credentials.

[servers.libera]
nickname = "<znc-user>/<znc-network>"
server = "znc.example.com"
password = "<your-password>"

# Depending on your ZNC setup you may need to apply these extra settings:

# Does your znc use a self-signed or expired certificate? See: 
# https://halloy.squidowl.org/configuration/servers.html#dangerously_accept_invalid_certs

# Does your znc listen on a different port? See: 
# https://halloy.squidowl.org/configuration/servers.html#port

Portable mode

To enable portable mode for Halloy, simply place the config.toml file in the same directory as the running executable.

.
├── Halloy.app
└── config.toml

Multiple servers

Creating multiple [servers] sections lets you connect to multiple servers.
All configuration options can be found here.

[servers.liberachat]
nickname = "halloy-user"
server = "irc.libera.chat"
channels = ["#halloy"]

[servers.oftc]
nickname = "halloy-user"
server = "irc.oftc.net"
channels = ["#asahi-dev"]

Storing passwords in a File

If you need to commit your configuration file to a public repository, you can keep your passwords in a separate file for security. Below is an example of using a file for nickname password for NICKSERV.

💡 Avoid adding extra lines in the password file, as they will be treated as part of the password.

💡 Shell expansions (e.g. "~/""/home/user/") are not supported in path strings.

💡 Windows path strings should usually be specified as literal strings (e.g. 'C:\Users\Default\'), otherwise directory separators will need to be escaped (e.g. "C:\\Users\\Default\\").

[servers.liberachat]
nickname = "foobar"
nick_password_file = "/home/user/config/halloy/password"
server = "irc.libera.chat"
channels = ["#halloy"]

Text Formatting

Text can be formatted in Halloy by using the /format (or /f) command.

Attributes

Below is a table with the supported text attributes.

ActionMarkdownToken
Italics_italic text_$iitalic text$i
Bold__bold text__$bbold text$b
Italic and Bold___italic and bold___$b$iitalic and bold$i$b
Strikethrough~~strikethrough~~$sstrikethrough$s
Underline-$uunderline$u
Code`code`$mcode$m
Spoiler||spoiler||-

Example

/format __this is bold__ $iand this is italic$i

Will render the following:

this is bold and this is italic

Color

ActionToken
Text color (fg)$c0
Text and background (fg & bg)$c0,1
End color$c

The number next to the $c token indicates the color. For a comprehensive list of all numbers, see the following ircdocs.horse documentation. Below, the first 00 to 15 colors are defined and have been assigned aliases for convenience.

Colors

- 00 - white
- 01 - black
- 02 - blue
- 03 - green
- 04 - red
- 05 - brown
- 06 - magenta
- 07 - orange
- 08 - yellow
- 09 - lightgreen
- 10 - cyan
- 11 - lightcyan
- 12 - lightblue
- 13 - pink
- 14 - grey
- 15 - lightgrey

Example

/format $cred,lightgreenfoobar$c
/format $c04,09foobar$c

Will both render the following:

foobar

Configuration

By default, Halloy will only format text when using the /format command. This, however, can be changed with the auto_format configuration option:

[buffer.text_input]
auto_format = "disabled" | "markdown" | "all"

Monitor users

Halloy has monitor support if the server has the IRCv3 Monitor extension.

💡 A protocol for notification of when clients become online/offline

To use the feature you need to add the user(s) you wish to monitor. This can be done in two ways:

  • You can add a list of user directly to the configuration file. See configuration option.
  • You can add users through /monitor directly in Halloy.

Examples with the /monitor command:

/monitor + casperstorm # Add user to list being monitored
/monitor - casperstorm # Remove user from list being monitored
/monitor c # Clear the list of users being monitored
/monitor l # Get list of users being monitored
/monitor s # For each user in the list being monitored, get their current status

Migrating from YAML

Halloy switched configuration file format from YAML to TOML (PR-278) This page will help you migrate your old config.yaml to a new config.toml file.

The basic structure of a TOML file consists of key-value pairs, where keys are strings. There are no nested indentations like YAML, which makes it easier to read and write. Consider the following old YAML config with of two servers in Halloy:

servers:
  libera:
    nickname: foobar
    server: irc.libera.chat
  quakenet:
    nickname: barbaz
    server: underworld2.no.quakenet.org
    port: 6667
    use_tls: true

This now looks the following in TOML

[servers.libera]
nickname = "foobar"
server = "irc.libera.chat"

[servers.quakenet]
nickname = "barbaz"
server = "underworld2.no.quakenet.org"
port = 6667
use_tls = true

💡 You can convert YAML to TOML using a converter tool like this one. Just note that a few keys and values have be renamed during the conversion process.

To migrate, and ensure everything is working, make sure to read through the Configuration section of this book. Here, every configuration option is documented using TOML.

Configuration

To edit configuration parameters, create a config.toml file located in your configuration directory:

  • Windows: %AppData%\halloy
  • Mac: ~/Library/Application Support/halloy or $HOME/.config/halloy
  • Linux: $XDG_CONFIG_HOME/halloy or $HOME/.config/halloy

💡 You can easily open the config file directory from command bar in Halloy

The specification for the configuration file format (TOML) can be found at https://toml.io/.

Example config for connecting to Libera:

[servers.liberachat]
nickname = "halloy-user"
server = "irc.libera.chat"
channels = ["#halloy"]

[buffer.channel.topic]
enabled = true

[buffer]

Buffer settings for Halloy.

  1. Away - Controls the appearance of away nicknames
  2. Channel - Channel specific settings
    1. Message - Message settings within a channel buffer
    2. Nicklist - Nicklist settings within a channel buffer
    3. Topic - Topic settings within a channel buffer
  3. Chathistory - IRCv3 Chat History extension settings
  4. Commands - Commands settings
  5. Date Separators - Customize how date separators are displayed within a buffer
  6. Emojis - Emojis settings
  7. Internal Messages - Internal messages are messages sent from Halloy itself
  8. Nickname - Customize how nicknames are displayed within a buffer
  9. Server Messages - Server messages are messages sent from a irc server.
  10. Status Message Prefix - Status message prefix settings
  11. Text Input - Customize the text input for in buffers
  12. Timestamp - Customize how timestamps are displayed within a buffer

[buffer.away]

Controls the appearance of away nicknames.

appearance

Controls the appearance of away nicknames in buffers.

# Type: string
# Values: "dimmed", "solid"
# Default: "dimmed"

[buffer.away]
appearance = "dimmed"

[buffer.channel]

Channel specific settings

[buffer.channel.message]

Message settings within a channel buffer.

nickname_color

Nickname colors in the message. "unique" generates colors by randomizing the hue, while keeping the saturation and lightness from the theme's nickname color.

# Type: string
# Values: "solid", "unique"
# Default: "unique"

[buffer.channel.message]
nickname_color = "unique"

[buffer.channel.nicklist]

Nicklist settings within a channel buffer.

alignment

Horizontal alignment of nicknames.

# Type: string
# Values: "left", "right"
# Default: "left"

[buffer.channel.nicklist]
alignment = "left"

color

Nickname colors in the nicklist. "unique" generates colors by randomizing the hue, while keeping the saturation and lightness from the theme's nickname color.

# Type: string
# Values: "solid", "unique"
# Default: "unique"

[buffer.channel.nicklist]
color = "unique"

enabled

Control if nicklist should be shown or not by default.

# Type: boolean
# Values: true, false
# Default: true

[buffer.channel.nicklist]
enabled = true

position

Nicklist position in the pane.

# Type: string
# Values: "left", "right"
# Default: "left"

[buffer.channel.nicklist]
position = "right"

show_access_levels

Show access levels in front of nicknames (@, +, ~, etc.).

# Type: boolean
# Values: true, false
# Default: true

[buffer.channel.nicklist]
show_access_levels = true

width

Overwrite nicklist width in pixels.

# Type: integer
# Values: any positive integer
# Default: not set

[buffer.channel.nicklist]
width = 150

[buffer.channel.topic]

Topic settings within a channel buffer.

enabled

Control if topic should be shown or not by default.

# Type: boolean
# Values: true, false
# Default: true

[buffer.channel.topic]
enabled = true

max_lines

Amount of visible lines before you have to scroll in topic banner.

# Type: integer
# Values: any positive integer
# Default: 2z

[buffer.channel.topic]
max_lines = 2

[buffer.chathistory]

IRCv3 Chat History extension settings

infinite_scroll

Automatically request older history when scrolling to the top of a channel/query buffer

# Type: boolean
# Values: true, false
# Default: true

[buffer.chathistory]
infinite_scroll = true

[buffer.commands]

Commands settings.

[buffer.commands]
show_description = false

show_description

Show or hide the description for a command

# Type: boolean
# Values: true, false
# Default: true

[buffer.commands]
show_description = true

[buffer.date_separators]

Customize how date separators are displayed within a buffer

format

Controls the date format. The expected format is strftime.
NOTE: The application will panic if a invalid format is provided.

# Type: string
# Values: any valid strftime string
# Default: "%A, %B %-d"

[buffer.date_separators]
format = "%A, %B %-d"

show

Show date separators.

# Type: boolean
# Values: true, false
# Default: true

[buffer.date_separators]
show = true

[buffer.emojis]

Emojis settings.

[buffer.emojis]
show_picker = true
skin_tone = "default"
auto_replace = true

show_picker

Show the emoji picker when typing :shortcode: in text input.

# Type: boolean
# Values: true, false
# Default: true

[buffer.emojis]
show_picker = true

skin_tone

Skin tone selected when picking an emoji.

# Type: string
# Values: "default", "light", "medium-light", "medium", "medium-dark", "dark"
# Default: "default"

[buffer.emojis]
skin_tone = "default"

auto_replace

Automatically replace :shortcode: in text input with the corresponding emoji.

# Type: boolean
# Values: true, false
# Default: true

[buffer.emojis]
auto_replace = true

[buffer.internal_messages]

Internal messages are messages sent from Halloy itself.

[buffer.internal_messages.success]

A internal messages which is considered a "success" such as when a connection was restored, or when connected succesfully to a server.

enabled

Control if internal message type is enabled.

# Type: boolean
# Values: true, false
# Default: true

[buffer.internal_messages.success]
enabled = true

smart

Only show internal message if received within the given time duration (seconds).

# Type: integer
# Values: any positive integer
# Default: not set

[buffer.internal_messages.success]
smart = 180

[buffer.internal_messages.error]

A internal messages which is considered a "error" such as when a connection was lost, or when connection to server failed.

enabled

Control if internal message type is enabled.

# Type: boolean
# Values: true, false
# Default: true

[buffer.internal_messages.error]
enabled = true

smart

Only show internal message if received within the given time duration (seconds).

# Type: integer
# Values: any positive integer
# Default: not set

[buffer.internal_messages.error]
smart = 180

[buffer.nickname]

Customize how nicknames are displayed within a buffer.

alignment

Horizontal alignment of nicknames.

# Type: string
# Values: "left", "right", "top"
# Default: "left"

[buffer.nickname]
alignment = "right"

brackets

Brackets around nicknames.

# Type: string
# Values: { left = "<any string>", right = "<any string>" }
# Default: { left = "", right = "" }

[buffer.nickname]
brackets = { left = "<", right = ">" }

color

Nickname colors in a channel buffer. "unique" generates colors by randomizing the hue, while keeping the saturation and lightness from the theme's nickname color.

# Type: string
# Values: "solid", "unique"
# Default: "unique"

[buffer.nickname]
color = "unique"

show_access_levels

Show access levels in front of nicknames (@, +, ~, etc.).

# Type: boolean
# Values: true, false
# Default: true

[buffer.nickname]
show_access_levels = true

[buffer.server_messages]

Server messages are messages sent from a irc server.

  • change_host - Message is sent when a user changes host
  • join - Message is sent when a user joins a channel
  • monitored_offline - Message is sent when a monitored user goes offline
  • monitored_online - Message is sent when a monitored user goes online
  • part - Message is sent when a user leaves a channel
  • quit - Message is sent when a user closes the connection to a channel or server
  • standard_reply_fail - Message is sent when a command/function fails or an error with the session
  • standard_reply_note - Message is sent when there is information about a command/function or session
  • standard_reply_warn - Message is sent when there is feedback about a command/function or session
  • topic - Message is sent when a user changes channel topic

Example

# Hide all join messages except for `#halloy` channel:

[buffer.server_messages.join]
exclude = ["*"]
include = ["#halloy"]

# Disable all part messages

[buffer.server_messages.part]
enable = false

enabled

Control if internal message type is enabled.

# Type: boolean
# Values: true, false
# Default: true

[buffer.server_messages.<server_message>]
enabled = true

smart

Only show server message if the user has sent a message in the given time interval (seconds) prior to the server message.

# Type: integer
# Values: any positive integer
# Default: not set

[buffer.server_messages.<server_message>]
smart = 180

exclude

Exclude channels from receiving the server messag. If you pass ["#halloy"], the channel #halloy will not receive the server message. You can also exclude all channels by using a wildcard: ["*"].

# Type: array of strings
# Values: array of any strings
# Default: []

[buffer.server_messages.<server_message>]
exclude = ["*"]

include

Include channels to receive the server message. If you pass ["#halloy"], the channel #halloy will receive the server message. The include rule takes priority over exclude, so you can use both together. For example, you can exclude all channels with ["*"] and then only include a few specific channels.

# Type: array of strings
# Values: array of any strings
# Default: []

[buffer.server_messages.<server_message>]
include = ["#halloy"]

username_format

Adjust the amount of information displayed for a username in server messages. If you choose "short", only the nickname will be shown. If you choose "full", the nickname, username, and hostname (if available) will be displayed.

Note: Not all server messages uses this setting.

# Type: string
# Values: "full", "short
# Default: "full"

[buffer.server_messages.<server_message>]
username_format = "full"

[buffer.status_message_prefix]

Status message prefix settings.

brackets

Brackets around status message prefix.

# Type: string
# Values: { left = "<any string>", right = "<any string>" }
# Default: { left = "", right = "" }

[buffer.status_message_prefix]
brackets = { left = "<", right = ">" }

[buffer.text_input]

Customize the text input for in buffers.

visibility

Text input visibility. When set to "focused" it will only be visible when the buffer is focused.

# Type: string
# Values: "always", "focused"
# Default: "always"

[buffer.text_input]
visibility = "always"

auto_format

Control if the text input should auto format the input. By default text is only formatted when using the /format command.

# Type: string
# Values: "disabled", "markdown", "all"
# Default: "disabled"

[buffer.text_input]
auto_format = "markdown"

💡 Read more about text formatting.

[buffer.text_input.autocomplete]

Customize autocomplete.

sort_direction

Sort direction when autocompleting.

# Type: string
# Values: "asc", "desc"
# Default: "asc"

[buffer.text_input.autocomplete]
sort_direction = "asc"

completion_suffixes

Sets what suffix is added after autocompleting. The first option is for when a nickname is autocompleted at the beginning of a sentence. The second is for when it's autocompleted in the middle of a sentence.

# Type: array of 2 strings
# Values: array of 2 strings
# Default: [": ", " "]

[buffer.text_input.autocomplete]
completion_suffixes = [": ", " "]

[buffer.timestamp]

Customize how timestamps are displayed within a buffer.

format

Controls the timestamp format. The expected format is strftime.

# Type: string
# Values: any valid strftime string
# Default: "%R"

[buffer.timestamp]
format = "%R"

brackets

Brackets around timestamps.

# Type: string
# Values: { left = "<any string>", right = "<any string>" }
# Default: { left = "", right = "" }

[buffer.timestamp]
brackets = { left = "[", right = "]" }

[file_transfer]

File transfer configuration options.

save_directory

Default directory to open when prompted to save a file.

# Type: string
# Values: any string
# Default: "$HOME/Downloads"

[file_transfer]
save_directory = "$HOME/Downloads"

passive

If true, act as the "client" for the transfer. Requires the remote user act as the server.

# Type: boolean
# Values: true, false
# Default: true

[file_transfer]
passive = true

timeout

Time (in seconds) to wait before timing out a transfer waiting to be accepted.

# Type: integer
# Values: any positive integer
# Default: 300

[file_transfer]
timeout = 300

[file_transfer.server]

This section is required if passive = false. One side of the file transfer must operate as the "server", who the other user connects with to establish a connection.

public_address

Address advertised to the remote user to connect to.

# Type: string
# Values: any string
# Default: not set

[file_transfer.server]
public_address = "<some ip>"

bind_address

Address to bind to when accepting connections.

# Type: string
# Values: any string
# Default: not set

[file_transfer.server]
bind_address = "<some ip>"

bind_port_first

First port in port range to bind to.

# Type: integer
# Values: any positive integer
# Default: not set

[file_transfer.server]
bind_port_first = "1024"

bind_port_last

Last port in port range to bind to.

# Type: integer
# Values: any positive integer
# Default: not set

[file_transfer.server]
bind_port_last = "5000"

[font]

Application wide font settings.

⚠️ Changes to font settings require an application restart to take effect.

family

Monospaced font family to use.

# Type: string
# Values: any string
# Default: not set
#
# Note: Iosevka Term is provided by the application, and used by default.

[font]
family = "Comic Mono"

size

Font size.

# Type: integer
# Values: any positive integer
# Default: 13

[font]
size = 13

[keyboard]

Customize keyboard shortcuts. Below is a list of all actions which can be mapped.

Example

[keyboard]
move_up = "alt+k"
move_down = "alt+j"
move_left = "alt+h"
move_right = "alt+l"
KeyDescriptionDefault MacOSDefault Other
move_upMoves focus up + + ctrl + alt +
move_downMoves focus down + + ctrl + alt +
move_leftMoves focus left + + ctrl + alt +
move_rightMoves focus right + + ctrl + alt +
close_bufferClose focused buffer + wctrl + w
maximize_bufferMaximize focused buffer + ctrl +
restore_bufferRestore focused buffer + ctrl +
cycle_next_bufferCycle to next bufferctrl + tabctrl + tab
cycle_previous_bufferCycle to previous bufferctrl + shift + tabctrl + shift + tab
leave_bufferLeave channel or close query + shift + wctrl + shift + w
toggle_nick_listToggle nick list + + mctrl + alt + m
toggle_topicToggle topic + + tctrl + alt + t
toggle_sidebarToggle sidebar + + bctrl + alt + b
toggle_fullscreenToggle fullscreenctrl + + fctrl + shift + f
command_barToggle command bar + kctrl + k
reload_configurationRefresh configuration file + rctrl + r
file_transfersToggle File Transfers Buffer + jctrl + j
logsToggle Logs Buffer + lctrl + l
theme_editorToggle Theme Editor Window + tctrl + t

[notifications]

Customize and enable notifications.

Example

[notifications]
direct_message = { sound = "peck", show_toast = true }

[notifications.highlight]
sound = "dong"
exclude = ["NickServ", "#halloy"]

Following notifications are available:

NameDescription
connectedTriggered when a server is connected
direct_messageTriggered when a direct message is received
disconnectedTriggered when a server disconnects
file_transfer_requestTriggered when a file transfer request is received
highlightTriggered when you were highlighted in a buffer
monitored_onlineTriggered when a user you're monitoring is online
monitored_offlineTriggered when a user you're monitoring is offline
reconnectedTriggered when a server reconnects

sound

Notification sound. Supports both built-in sounds, and external sound files (mp3, ogg, flac or wav placed inside the sounds folder within the configuration directory).

# Type: string
# Values: "dong", "peck", "ring", "squeak", "whistle", "bonk", "sing" or external sound.
# Default: not set

[notifications.<notification>]
sound = "dong"

show_toast

Notification should trigger a OS toast.

# Type: boolean
# Values: true, false
# Default: false

[notifications.<notification>]
show_toast = true

delay

Delay in milliseconds before triggering the next notification.

# Type: integer
# Values: any positive integer
# Default: 500

[notifications.<notification>]
delay = 250

exclude

Exclude notifications for nicks (and/or channels in highlight's case).

Only available for direct_message, highlight and file_transfer_request notifications.

You can also exclude all nicks/channels by using a wildcard: ["*"] or ["all"].

# Type: array of strings
# Values: array of strings
# Default: []

[notifications.<direct_mesage|file_transfer_request>]
exclude = ["HalloyUser1"]

[notifications.highlight]
exclude = ["HalloyUser1", "#halloy"]

include

Include notifications for nicks (and/or channels in highlight's case).

Only available for direct_message, highlight and file_transfer_request notifications.

The include rule takes priority over exclude, so you can use both together. For example, you can exclude all nicks with ["*"] for direct_message and then only include a few specific nicks to receive direct_message notifications from.

# Type: array of strings
# Values: array of strings
# Default: []

[notifications.<direct_mesage|file_transfer_request>]
include = ["HalloyUser1"]

[notifications.highlight]
include = ["HalloyUser1", "#halloy"]

[proxy]

Proxy settings for Halloy.

  1. http
  2. socks5
  3. tor

[proxy.http]

Http proxy settings.

host

Proxy host to connect to.

# Type: string
# Values: any string
# Default: not set

# Required

[proxy.http]
host = "192.168.1.100"

port

Proxy port to connect on.

# Type: integer
# Values: any positive integer
# Default: not set

# Required

[proxy.http]
port = "1080"

username

Proxy username.

# Type: string
# Values: any string
# Default: not set

# Optional

[proxy.http]
username = "username"

password

Proxy password.

# Type: string
# Values: any string
# Default: not set

# Optional

[proxy.http]
password = "password"

Example

[proxy.http]
host = "192.168.1.100"
port = "1080"
username = "username"
password = "password"

[proxy.socks5]

Socks5 proxy settings.

host

Proxy host to connect to.

# Type: string
# Values: any string
# Default: not set

# Required

[proxy.socks5]
host = "192.168.1.100"

port

Proxy port to connect on.

# Type: integer
# Values: any positive integer
# Default: not set

# Required

[proxy.socks5]
port = "1080"

username

Proxy username.

# Type: string
# Values: any string
# Default: not set

# Optional

[proxy.socks5]
username = "username"

password

Proxy password.

# Type: string
# Values: any string
# Default: not set

# Optional

[proxy.socks5]
password = "password"

Example

[proxy.socks5]
host = "192.168.1.100"
port = "1080"
username = "username"
password = "password"

[proxy.tor]

Tor proxy settings. Utilizes the arti to integrate Tor natively. It accepts no further configuration.

Example

[proxy.tor]

[preview]

URL preview settings for Halloy.

enabled

Enable or disable previews globally

# Type: boolean
# Values: true, false
# Default: true

[preview]
enabled = true

request

Request settings for previews.

user_agent

Some servers will only send opengraph metadata to browser-like user agents. We default to WhatsApp/2 for wide compatability.

# Type: string
# Values: any string
# Default: "WhatsApp/2"

[preview.request]
user_agent = "WhatsApp/2"

timeout_ms

Request timeout in millisceonds. Defaults is 10s.

# Type: integer
# Values: any positive integer
# Default: 10000

[preview.request]
timeout_ms = 10000

max_image_size

Max image size in bytes. This prevents downloading responses that are too big. Default is 10mb.

# Type: integer
# Values: any positive integer
# Default: 10485760

[preview.request]
max_image_size = 10485760

max_scrape_size

Max bytes streamed when scraping for opengraph metadata before cancelling the request. This prevents downloading responses that are too big. Default is 500kb.

# Type: integer
# Values: any positive integer
# Default: 512000

[preview.request]
max_scrape_size = 512000

concurrency

Number of allowed concurrent requests for fetching previews. Reduce this to prevent rate-limiting.

# Type: integer
# Values: any positive integer
# Default: 4

[preview.request]
concurrency = 4

delay_ms

Numer of milliseconds to wait before requesting another preview when number of requested previews > concurrency.

# Type: integer
# Values: any positive integer
# Default: 500

[preview.request]
delay_ms = 500

image

Specific image preview settings.

include

Include image previews from channels. If you pass ["#halloy"], the channel #halloy will show image previews. The include rule takes priority over exclude, so you can use both together. For example, you can exclude all channels with ["*"] and then only include a few specific channels.

# Type: array of strings
# Values: array of any strings
# Default: []

[preview.image]
include = []

exclude

Exclude image previews from channels. If you pass ["#halloy"], the channel #halloy will not show image previews. You can also exclude all channels by using a wildcard: ["*"].

# Type: array of strings
# Values: array of any strings
# Default: []

[preview.image]
exclude = []

Example

[preview.image]
exclude = ["*"] # hide image previews in all channels
include = ["#halloy"] # show image previews in #halloy

card

Specific card preview settings.

show_image

Show image for card previews.

# Type: boolean
# Values: true, false
# Default: true

[preview.card]
show_image = true

include

Include card previews from channels. If you pass ["#halloy"], the channel #halloy will show image previews. The include rule takes priority over exclude, so you can use both together. For example, you can exclude all channels with ["*"] and then only include a few specific channels.

# Type: array of strings
# Values: array of any strings
# Default: []

[preview.card]
include = []

exclude

Exclude card previews from channels. If you pass ["#halloy"], the channel #halloy will not show image previews. You can also exclude all channels by using a wildcard: ["*"].

# Type: array of strings
# Values: array of any strings
# Default: []

[preview.card]
exclude = []

Example

[preview.card]
exclude = ["*"] # hide card previews in all channels
include = ["#halloy"] # show card previews in #halloy

[scale_factor]

Application wide scale factor.
Note: scale_factor is a root key, so it must be placed before any section.

# Type: float
# Values: 0.1 .. 3.0
# Default: 1.0

scale_factor = 1.0

[servers]

You can define multiple server sections in the configuration file. Each server section must have a unique name, which is used as the identifier in the [servers.<name>] format.

Eg:

[servers.quakenet]
# ...

💡 For a multiple server example see here

nickname

The client's nickname.

# Type: string
# Values: any string
# Default: not set

[servers.<name>]
nickname = ""

nick_password

The client's NICKSERV password.

# Type: string
# Values: any string
# Default: not set

[servers.<name>]
nick_password = ""

nick_password_file

Read nick_password from the file at the given path.1 2

# Type: string
# Values: any string
# Default: not set

[servers.<name>]
nick_password_file = ""

nick_password_command

Executes the command with sh (or equivalent) and reads nick_password as the output.

# Type: string
# Values: any string
# Default: not set

[servers.<name>]
nick_password_command = ""

nick_identify_syntax

The server's NICKSERV IDENTIFY syntax.

# Type: string
# Values: "nick-password", "password-nick"
# Default: not set

[servers.<name>]
nick_identify_syntax = ""

alt_nicks

Alternative nicknames for the client, if the default is taken.

# Type: array of strings
# Values: array of any strings
# Default: not set

[servers.<name>]
alt_nicks = ["Foo", "Bar"]

username

The client's username.

# Type: string
# Values: any string
# Default: not set

[servers.<name>]
username = ""

realname

The client's real name.

# Type: string
# Values: any string
# Default: not set

[servers.<name>]
realname = ""

server

The server to connect to.

# Type: string
# Values: any string
# Default: not set

[servers.<name>]
server = "irc.libera.chat"

port

The port to connect on.

# Type: integer
# Values: any positive integer
# Default: 6697

[servers.<name>]
port = 6697

password

The password to connect to the server.

# Type: string
# Values: any string
# Default: not set

[servers.<name>]
password = ""

password_file

Read password from the file at the given path.1 2

# Type: string
# Values: any string
# Default: not set

[servers.<name>]
password_file = ""

password_command

Executes the command with sh (or equivalent) and reads password as the output.

# Type: string
# Values: any string
# Default: not set

[servers.<name>]
password_command = ""

channels

A list of channels to join on connection.

# Type: array of strings
# Values: array of any strings
# Default: not set

[servers.<name>]
channels = ["#foo", "#bar"]

channel_keys

A mapping of channel names to keys for join-on-connect.

# Type: map
# Values: map with string key value
# Default: {}

[servers.<name>]
channel_keys = { channel1 = "key1" }

ping_time

The amount of inactivity in seconds before the client will ping the server.

# Type: integer
# Values: any positive integer
# Default: 180

[servers.<name>]
ping_time = 180

ping_timeout

The amount of time in seconds for a client to reconnect due to no ping response.

# Type: integer
# Values: any positive integer
# Default: 20

[servers.<name>]
ping_timeout = 20

reconnect_delay

The amount of time in seconds before attempting to reconnect to the server when disconnected.

# Type: integer
# Values: any positive integer
# Default: 10

[servers.<name>]
reconnect_delay = 10

should_ghost

Whether the client should use NickServ GHOST to reclaim its primary nickname if it is in use.

# Type: boolean
# Values: true, false
# Default: false

[servers.<name>]
should_ghost = false

ghost_sequence

The command(s) that should be sent to NickServ to recover a nickname.

# Type: array of strings
# Values: array of any strings
# Default: ["REGAIN"]

[servers.<name>]
ghost_sequence = ["REGAIN"]

umodes

User modestring to set on connect.

# Type: string
# Values: any string
# Default: not set

[servers.<name>]
umodes = "+RB-x"

use_tls

Whether or not to use TLS. Clients will automatically panic if this is enabled without TLS support.

# Type: boolean
# Values: true, false
# Default: false

[servers.<name>]
use_tls = false

dangerously_accept_invalid_certs

When true, all certificate validations are skipped.

# Type: boolean
# Values: true, false
# Default: false

[servers.<name>]
dangerously_accept_invalid_certs = false

root_cert_path

The path to the root TLS certificate for this server in PEM format.1 2

# Type: string
# Values: any string
# Default: not set

[servers.<name>]
root_cert_path = ""

on_connect

Commands which are executed once connected.

# Type: array of string
# Values: array of any strings
# Default: not set

[servers.<name>]
on_connect = ["/msg NickServ IDENTIFY foo bar"]

who_poll_enabled

Whether or not to WHO polling is enabled.

# Type: boolean
# Values: true, false
# Default: true

[servers.<name>]
who_poll_enabled = true

who_poll_interval

WHO poll interval (in seconds) for servers without away-notify. Specifically, the time between individual WHO requests. Will be increased automatically if the server sends a rate-limiting message.

# Type: integer
# Values: 1 .. 3600
# Default: 2

[servers.<name>]
who_poll_interval = 2

monitor

A list of nicknames to monitor (if IRCv3 Monitor is supported by the server).

💡 Read more about monitoring users.

# Type: array of string
# Values: array of any strings
# Default: not set

[servers.<name>]
monitor = ["Foo", "Bar"]

chathistory

Whether or not to enable IRCv3 Chat History (if it is supported by the server).

# Type: boolean
# Values: true, false
# Default: true

[servers.<name>]
chathistory = true

sasl.plain

Plain SASL auth using a username and password

username

The account name used for authentication.

# Type: string
# Values: any string
# Default: not set

[servers.<name>.sasl.plain]
username = "username"

password

The password associated with the account used for authentication.

# Type: string
# Values: any string
# Default: not set

[servers.<name>.sasl.plain]
password = "password"

password_file

Read password from the file at the given path.1 2

# Type: string
# Values: any string
# Default: not set

[servers.<name>.sasl.plain]
password_file = ""

password_command

Executes the command with sh (or equivalent) and reads password as the output.

# Type: string
# Values: any string
# Default: not set

[servers.<name>.sasl.plain]
password_command = ""

sasl.external

External SASL auth uses a PEM encoded X509 certificate. Reference.

cert

The path to PEM encoded X509 user certificate for external auth.1 2

# Type: string
# Values: any string
# Default: not set

[servers.<name>.sasl.external]
cert = "/path/to/your/certificate.pem"

key

The path to PEM encoded PKCS#8 private key for external auth (optional).1 2

# Type: string
# Values: any string
# Default: not set

[servers.<name>.sasl.external]
key = "/path/to/your/private_key.pem"
1

Shell expansions (e.g. "~/""/home/user/") are not supported in path strings.

2

Windows path strings should usually be specified as literal strings (e.g. 'C:\Users\Default\'), otherwise directory separators will need to be escaped (e.g. "C:\\Users\\Default\\").

[sidebar]

Sidebar settings for Halloy.

buffer_action

Action when pressing buffers in the sidebar. "new-pane" opens a new pane each time. "replace-pane" replaces the focused pane with the pressed buffer. "new-window" opens a new window each time.

# Type: string
# Values: "new-pane", "replace-pane", "new-window"
# Default: "new-pane"

[sidebar]
buffer_action = "replace-pane"

buffer_focused_action

Action when pressing a focused buffer in the sidebar. "close-pane" will close the focused pane.

# Type: string
# Values: "close-pane"
# Default: not set

[sidebar]
buffer_focused_action = "close-pane"

unread_indicator

Unread buffer indicator style.

# Type: string
# Values: "dot", "title", "none"
# Default: "dot"

[sidebar]
unread_indicator = "dot"

position

Sidebar position within the application window.

# Type: string
# Values: "left", "top", "right", "bottom"
# Default: "left"

[sidebar]
position = "left"

width

Specify sidebar width in pixels. Only used if position is "left" or "right".

# Type: integer
# Values: any positive integer
# Default: 120

[sidebar]
width = 120

show_menu_button

Show or hide the user menu button in the sidemenu.

# Type: bool
# Values: true, false
# Default: true

[sidebar]
show_menu_button = true

Themes

Example

# Static
theme = "ferra"

# Dynamic
theme = { light = "ferra-light", dark = "ferra" }

Note: theme is a root key, so it must be placed before any section.

theme

Specify the theme name(s) to use. The theme must correspond to a file located in the themes folder, which can be found in the Halloy configuration directory. The default theme in Halloy is Ferra.

When a dynamic theme is used, Halloy will match the appearance of the OS.

  • type: string or object
  • values: "<string>", { light = "<string>", dark = "<string>" }
  • default: "ferra"

💡 See all community created themes here and base16 themes here.

Custom themes

To create a custom theme for Halloy, simply place a theme file (with a .toml extension) inside the themes folder within the configuration directory.

# Consider we have a theme called "foobar.toml" inside the themes folder.
# Theme is a root key, so it has to be placed before any sections in your config file.

theme = "foobar"
# .. rest of the configuration file.

💡 Halloy has a built in theme editor which makes theme creation easier

Each "<string>" is expected to be a valid hex color. If invalid, or if the key is removed, the color will fallback to transparent. A custom theme is structured as follows:

[general]
background = "<string>"
border = "<string>"
horizontal_rule = "<string>"
unread_indicator = "<string>"

[text]
primary = "<string>"
secondary = "<string>"
tertiary = "<string>"
success = "<string>"
error = "<string>"

[buttons.primary]
background = "<string>"
background_hover = "<string>"
background_selected = "<string>"
background_selected_hover = "<string>"

[buttons.secondary]
background = "<string>"
background_hover = "<string>"
background_selected = "<string>"
background_selected_hover = "<string>"

[buffer]
action = "<string>"
background = "<string>"
background_text_input = "<string>"
background_title_bar = "<string>"
border = "<string>"
border_selected = "<string>"
code = "<string>"
highlight = "<string>"
nickname = "<string>"
selection = "<string>"
timestamp = "<string>"
topic = "<string>"
url = "<string>"

[buffer.server_messages]
# Set below if you want to have a unique color for each.
# Otherwise simply set `default` to use that for all server messages.
#
# change_host = "<string>"
# join = "<string>"
# part = "<string>"
# quit = "<string>"
# reply_topic = "<string>"
# monitored_online = "<string>"
# monitored_offline = "<string>"
# standard_reply_fail = "<string>"
# standard_reply_warn = "<string>"
# standard_reply_note = "<string>"
default = "<string>"

💡 The default Ferra theme toml file can be viewed here.

Community

This is a list of community created themes for Halloy.

💡 Have a great theme you want to share? Open a pull-request here.

Oxocarbon

Open in Halloy

Dracula

Open in Halloy

Gruvbox

Open in Halloy

Catppuccin Latte

Open in Halloy

Catppuccin Macchiato

Open in Halloy

Catppuccin Mocha

Open in Halloy

Ferra Light

Open in Halloy

Booberry

Open in Halloy

One Dark

Open in Halloy

IntelliJ Light

Open in Halloy

Macaw Light

Open in Halloy

Macaw Dark

Open in Halloy

Zenburn

Open in Halloy

Solarized Dark

Open in Halloy

Cyberpunk

Open in Halloy

Rose Pine

Open in Halloy

Rose Pine Moon

Open in Halloy

Rose Pine Dawn

Open in Halloy

Base16

The base16 color scheme framework includes hundreds of colorschemes build using 16 colors. These colorschemes have are compiled for Halloy in the 4e554c4c/base16-halloy repository.

To use these themes, download themes.tar.gz from the latest release and unpack it to the themes folder in the Halloy configuration directory. Then you can enable themes individually in config.toml.

Example

# Static
theme = "base16-gruvbox-dark-hard"

[tooltips]

Control if tooltips are displayed or not.
Note: tooltips is a root key, so it must be placed before any section.

# Type: boolean
# Values: true, false
# Default: true

tooltips = true

URL Schemes

Halloy is able to recongize different URL schemes.

IRC and IRCS

The IRC URL scheme is used to create a new connection to a server.
The format is based on the URI Syntax.

Format

<scheme>://<server>:<port>/[#channel[,#channel]]
KeyDescription
schemeCan be irc or ircs. TLS is enabled if is ircs.
serverAddress for the server. Eg: irc.libera.chat.
portOptional. Defaults to 6667 (if irc) or 6697 (if ircs).
channelOptional. List of channels, separated by a comma.

Examples

Below is a few URL examples.

Halloy

The halloy:// scheme is used to import themes. The syntax for that is halloy:///theme?e=base64EncodedThemeData. A list of community created themes can be found here.

Commands

Commands in Halloy are prefixed with /.

Example

/me says halloy!

Halloy will first try to run below commands, and lastly send it directly to the server.

CommandAliasDescription
awayMark yourself as away. If already away, the status is removed
joinjJoin channel(s) with optional key(s)
medescribeSend an action message to the channel
modemSet mode(s) on a channel or retrieve the current mode(s) set
monitorSystem to notify when users become online/offline
msgOpen a query with a nickname and send an optional message
nickChange your nickname on the current server
partleaveLeave channel(s) with an optional reason
quitDisconnect from the server with an optional reason
rawSend data to the server without modifying it
topictRetrieve the topic of a channel or set a new topic
whoisRetrieve information about user(s)