Keyboard shortcuts

Press ← or β†’ to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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

Install from Source

The script install-linux.sh in the scripts directory of the Halloy repository will build and install Halloy on Linux systems (with the same requirements as building from source). By default the script will install Halloy in the ~/.local/ base directory (i.e. the executable will be put in ~/.local/bin/). To change the installation base directory, provide install-linux.sh with the long flag --prefix=<base/directory>.

git clone https://github.com/squidowl/halloy.git cd halloy ./scripts/install-linux.sh --prefix=<base/directory>

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, 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. ↩

Configuration

Halloy uses a TOML file for configuration called config.toml.
A default file is created when you launch Halloy for the first time. The location depends on your system:

  • Windows: %AppData%\halloy
  • Mac: ~/Library/Application Support/halloy or $HOME/.config/halloy
  • Linux: $XDG_CONFIG_HOME/halloy, $HOME/.config/halloy or $HOME/.var/app/org.squidowl.halloy/config (Flatpak)

πŸ’‘ Most configuration changes can be applied by reloading the configuration file from the sidebar menu, keyboard shortcut, or the command bar

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

Example configuration for connecting to Libera:

theme = "ferra" [servers.liberachat] nickname = "halloy-user" server = "irc.libera.chat" channels = ["#halloy"] [buffer.channel.topic] enabled = true

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

Contributors

Special thanks to all the people who makes Halloy happens

Did we forget you? We're sorry about that! Feel free to add yourself and create a pull request.

Building for Flatpak

This guide will help you to build and/or test pre-released commits of Halloy for flatpak.

If you haven't done so already, clone the Halloy repository to your local machine.

Requirements

Be sure to install all the dependencies for the above tools.

Generating Flatpak Build Sources File

To generate the generated-sources.json file that is used by the flatpak manifest, run the following command:

python3 <flatpak-builder-tools-path>/cargo/flatpak-cargo-generator.py -o <halloy-checkout-path>/assets/flatpak/generated-sources.json

Building and Installing Flatpak Locally

Finally, to build and install the flatpak locally, run the following command:

flatpak-builder --force-clean --user --install-deps-from=flathub --repo=.flatpak-builder/repo --install .flatpak-builder/build <halloy-checkout-path>/assets/flatpak/org.squidowl.halloy.json

Your flatpak should now be built, installed locally and ready for use.

Happy testing!

Releasing to Flathub

Halloy's flatpaks are released via Flathub.

Start by cloning the flathub repo for Halloy. Every release has two requirements:

  1. The generated-sources.json file must be up to date. You can generate it from the latest release tag via the commands above.
  2. The flatpak manifest file (org.squidowl.halloy.json) must be updated to point to the latest release tag of Halloy.

The caveat for #2: the version you're wanting to release must be tagged first. We use the sha256sum of the tagged tarball in the build manifest.

For example, for release 2025.6, we would need to:

# Download the tagged tarball wget https://github.com/squidowl/halloy/archive/refs/tags/2025.6.tar.gz # Get the sha256sum of the tarball sha256sum 2025.6.tar.gz | awk '{print $1}'

The url and the sha256 fields for modules.0.sources.0 in the manifest file should be updated along with an updated generated-sources.json file. After that, you can create a pull request to the Flathub repository with the updated files.

See the pull request for the 2025.6 release for an example.

Building for macOS

This guide explains how to build the Halloy .app for macOS. If you want to install a signed release version of Halloy on macOS, then you should consult the Installation documentation instead.

Prerequisites

Steps

  1. Clone the Repository

    If you haven’t already, clone the Halloy repository:

    git clone https://github.com/squidowl/halloy.git cd halloy
  2. Run the Build Script

    Execute the build-macos script:

    ./scripts/build-macos.sh

    This script will:

    • Build the Halloy binary for both x86_64 and aarch64 architectures.
    • Combine them into a universal binary using lipo.
    • Copy the binary and resources into a macOS .app bundle template located at assets/macos/Halloy.app.
    • Place the .app bundle in target/release/macos.
  3. Locate the Built Application

    After the script completes, you’ll find the generated .app bundle at:

    target/release/macos/Halloy.app

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.soju] nickname = "<your-nickname>" server = "<your-bouncer-url>" port = 6697 [servers.soju.sasl.plain] username = "<your-username>" password = "<your-password>"

πŸ’‘ as of 2025.1 Halloy supports chathistory, so the machine name (like @desktop) is no longer needed when chathistory is enabled

Using Bouncer Networks

⚠️ The soju bouncer-networks specification requires that SASL be used. If you do not use SASL, you must add servers in the legacy fashion.

As of 2025.9 Halloy supports bouncer-networks so connecting to individual servers is no longer needed. Instead, Halloy can communicate with soju to determine what networks you are currently connected to and then automatically add them in the UI.

If this is not desired, you can still add individual servers with the ZNC username syntax, for example:

[servers.libera] nickname = "<your-nickname>" server = "<your-bouncer-url>" port = 6697 [servers.soju.sasl.plain] username = "<your-username>/irc.libera.chat" password = "<your-password>"

Using Chat History

You can enable infinite scrolling history if you want to automatically load older messages.

[buffer.chathistory] infinite_scroll = 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.chat/configuration/servers.html#dangerously_accept_invalid_certs # Does your znc listen on a different port? See: # https://halloy.chat/configuration/servers.html#port

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

Multiple Servers

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

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

Optional Features

Halloy supports optional features that can be enabled during compilation to add additional functionality. These features are not included by default to keep the binary size small and compilation fast.

Building with features

To build Halloy with specific features, use the --features flag:

# Build with a feature cargo build --features tor # Build release with features cargo build --release --features tor

Available features

tor

Enables Tor network support for anonymous IRC connections. Not enabled by default.

See Proxy Configuration for usage details.

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

Pronunciation

Halloy is an English transliteration of the Danish greeting hallΓΈj. In other words, its pronunciation is close to the way most English speakers would guess based on its spelling. An approximate machine reading can be heard via IPA Reader.

Reduce Noise

It's not uncommon for channels to have many server messages for every regular message, resulting in a low signal to noise ratio. Halloy has various settings that can help reduce the number of visible server messages in the chat log. This guide will cover some of those settings.

Disable Topic Messages

Most servers and bouncers will send a message with the topic every time Halloy joins a channel. Since topics rarely change, it's often useful to hide these messages altogether with disabling the topic server message setting:

[buffer.server_messages.topic] enabled = false

Note, this will not hide the messages sent when a topic changes, only the topic messages sent on first connection to a channel.

If topic messages are hidden but a reminder of the current topic is still desired, then a topic banner can be enabled to appear at the top of each pane. Either with the label icon button in the pane's title bar, or with the topic banner settings:

[buffer.channel.topic_banner] enabled = true max_lines = 2

Smart Filters

Smart filters can be used for server messages to hide messages for users that have not sent a message recently. For example, to hide part messages for any user that has not sent a message within the 15 minutes prior to their parting:

[buffer.server_messages.part] smart = 900

For many channels join, part, quit, and nickname changes make up a lot of noise and usually aren't relevant if the user hasn't been active. To smart filter those messages these settings can be used:

[buffer.server_messages] join.smart = 900 part.smart = 900 quit.smart = 900 change_nick.smart = 900

Smart filters can also be applied to internal messages as well. For example, to hide any connect or disconnect message older than five minutes, use these settings:

[buffer.internal_messages] success.smart = 300 error.smart = 300

Condense Server Messages

It may be preferable to not hide any server messages, in which case an alternative to filtering is to condense server messages. This setting will combine multiple server messages into a one server message with a shortened style. To enable condensed messages these settings can be used:

[buffer.server_messages.condense] messages = ["join", "part", "quit"] dimmed = true

When using condensed messages, it is recommended that you specify colors for the condensed messages in your theme). Those colors will be used for the abbreviations used in the condensed messages. For example, these theme settings could be added:

[buffer.server_messages] join = "#efff95" part = "#ff6b77" quit = "#ff6b77"

Ignore

If dealing with a noisy user or bot, an ignore filter can be used to hide their messages. For example, to hide messages produced by ChanServ in the #halloy channel, the following setting can be used:

[servers.libera.filters] ignore = ["#halloy ChanServ"]

Single Pane

The settings below will configure Halloy to have a single pane (or fixed number of panes) in regular use. After applying these settings, close all but one pane. Then, when activating another channel or query in the sidebar, that buffer will replace the view in the sole remaining pane (rather than opening a new pane). When needed, new panes can be opened via the context menu on sidebar items (e.g. right-click on a channel in the sidebar and select "Open in new pane").

[actions.buffer] click_channel_name = "replace-pane" click_highlight = "replace-pane" click_username = "replace-pane" local = "replace-pane" message_channel = "replace-pane" message_user = "replace-pane" [actions.sidebar] buffer = "replace-pane"

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.

πŸ’‘ 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 = "~/.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"

URL Schemes

Halloy is able to recognize 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.

Actions

Application-wide actions; how user actions should be enacted.

Buffer

Buffer actions

Sidebar actions

Buffer

How buffer actions should be enacted

Example

# Replace pane when clicking on channel/user names in a pane, [actions.buffer] click_channel_name = "replace-pane" click_username = "replace-pane"

Configuration

click_channel_name

Action when clicking on a channel name in a pane. "new-pane" opens a new pane each time. "replace-pane" replaces the focused pane with the clicked channel. "new-window" opens a new window each time.

# Type: string # Values: "new-pane", "replace-pane", "new-window" # Default: "new-pane" [actions.buffer] click_channel_name = "new-pane"

click_highlight

Action when clicking on a highlight in the highlights buffer. "new-pane" opens a new pane each time. "replace-pane" replaces the focused pane with the buffer that contains the highlight. "new-window" opens a new window each time.

# Type: string # Values: "new-pane", "replace-pane", "new-window" # Default: "new-pane" [actions.buffer] click_highlight = "new-pane"

click_username

Action when clicking on a user name in a pane (if buffer.channel.nicklist or buffer.nickname is set to "open-query"). "new-pane" opens a new pane each time. "replace-pane" replaces the focused pane with a query for clicked user. "new-window" opens a new window each time.

# Type: string # Values: "new-pane", "replace-pane", "new-window" # Default: "new-pane" [actions.buffer] click_username = "new-pane"

local

Action when opening a local buffer (the highlights or logs buffer). "new-pane" opens a new pane each time. "replace-pane" replaces the focused pane with the local buffer. "new-window" opens a new window each time.

# Type: string # Values: "new-pane", "replace-pane", "new-window" # Default: "new-pane" [actions.buffer] local = "new-pane"

message_channel

Action when sending an empty message to a channel (via the /msg or /notice command). "new-pane" opens a new pane each time. "replace-pane" replaces the focused pane with the channel. "new-window" opens a new window each time.

# Type: string # Values: "new-pane", "replace-pane", "new-window" # Default: "new-pane" [actions.buffer] message_channel = "replace-pane"

message_user

Action when sending an empty message to a user (via Message in the user context menu or the /msg or /notice command). "new-pane" opens a new pane each time. "replace-pane" replaces the focused pane with a query for the user. "new-window" opens a new window each time.

# Type: string # Values: "new-pane", "replace-pane", "new-window" # Default: "new-pane" [actions.buffer] message_user = "replace-pane"

Sidebar

How sidebar actions should be enacted.

Example

# Open a new pane when clicking on a buffer in the sidebar # (or close the buffer if it's already open) [actions.sidebar] buffer = "new-pane" focused_buffer = "close-pane"

Configuration

buffer

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

# Type: string # Values: "new-pane", "replace-pane", "new-window" # Default: "new-pane" [actions.sidebar] buffer = "replace-pane"

focused_buffer

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

# Type: string # Values: "close-pane" # Default: not set [actions.sidebar] focused_buffer = "close-pane"

Buffer

Buffer settings for Halloy.

Configuration

line_spacing

Setting to control spacing between messages in buffers

# Type: integer # Values: positive integers # Default: 0 [buffer] line_spacing = 4

scroll_position_on_open

Scroll position of the buffer when it opens.

# Type: string # Values: "oldest-unread", "newest" # Default: "oldest-unread" [buffer] scroll_position_on_open = "newest"

Channel

Channel specific settings

Chat History

IRCv3 Chat History extension settings

Commands

Commands settings.

Backlog Separator

Customize when the backlog separator is displayed within a buffer

Date Separators

Customize how date separators are displayed within a buffer

Emojis

Emojis settings.

Internal Messages

Internal messages are messages sent from Halloy itself.

Mark as Read

When to mark a buffer as read

Nickname

Customize how nicknames are displayed within a buffer.

Server Messages

Server messages are messages sent from an IRC server.

Status message prefix

Status message prefix settings.

Text Input

Customize the text input for in buffers.

Timestamp

Customize how timestamps are displayed within a buffer.

Url

Customize how urls behave in buffers

Backlog Separator

Customize when the backlog separator is displayed within a buffer

Configuration

hide_when_all_read

Hide backlog divider when all messages in the buffer have been marked as read.

# Type: boolean # Values: true, false # Default: false [buffer.backlog_separator] hide_when_all_read = true

Channel

Channel specific settings

Message

Message settings within a channel buffer

Nicklist

Nicklist settings within a channel buffer

Topic Banner

Topic banner settings within a channel buffer

Message

Message settings within a channel buffer.

Configuration

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"

Nicklist

Nicklist settings within a channel buffer.

Configuration

alignment

Horizontal alignment of nicknames.

# Type: string # Values: "left", "right" # Default: "left" [buffer.channel.nicklist] alignment = "left"

away

Controls the appearance of away nicknames.

# Type: string or object # Values: "dimmed", "none" or { dimmed = float } # Default: "dimmed" [buffer.channel.nicklist] away = "dimmed" # with custom dimming alpha value (0.0-1.0) [buffer.channel.nicklist] away = { dimmed = 0.5 } # no away indication [buffer.channel.nicklist] away = "none"

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 non-negative integer # Default: not set [buffer.channel.nicklist] width = 150

click

Click action for when interaction with nicknames.

  • "open-query": Open a query with the User
  • "insert-nickname": Inserts the nickname into text input
# Type: string # Values: "open-query", "insert-nickname" # Default: "open-query" [buffer.channel.nicklist] click = "open-query"

Topic Banner

Topic banner settings within a channel buffer.

Configuration

enabled

Control if topic banner should be shown or not by default.

# Type: boolean # Values: true, false # Default: false [buffer.channel.topic_banner] enabled = true

max_lines

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

# Type: integer # Values: any non-negative integer # Default: 2 [buffer.channel.topic_banner] max_lines = 2

Chat History

IRCv3 chathistory extension settings

Configuration

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

Commands

Commands settings.

Configuration

show_description

Show or hide the description for a command

# Type: boolean # Values: true, false # Default: true [buffer.commands] show_description = true

Sysinfo

Configure which system information components to display when using the /sysinfo command

Sysinfo

Configure which system information components to display when using the /sysinfo command

Configuration

cpu

Show CPU information (processor brand and model)

# Type: boolean # Values: true, false # Default: true [buffer.commands.sysinfo] cpu = true

memory

Show memory information

# Type: boolean # Values: true, false # Default: true [buffer.commands.sysinfo] memory = true

gpu

Show graphics card information (adapter and backend)

# Type: boolean # Values: true, false # Default: true [buffer.commands.sysinfo] gpu = true

os

Show operating system information (version and kernel)

# Type: boolean # Values: true, false # Default: true [buffer.commands.sysinfo] os = true

uptime

Show system uptime information

# Type: boolean # Values: true, false # Default: true [buffer.commands.sysinfo] uptime = true

Date Separators

Customize how date separators are displayed within a buffer

Configuration

format

Controls the date format. The expected format is strftime.

# 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

Emojis

Emojis settings.

Example

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

Configuration

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

characters_to_trigger_picker

Minimum number of characters after : required for the emoji picker to show. E.g. :D will not show the emoji picker unless characters_to_trigger_picker is less than or equal to 1.

# Type: integer # Values: any non-negative integer # Default: 2 [buffer.emojis] characters_to_trigger_picker = 2

Internal Messages

Internal messages are messages sent from Halloy itself.

Success

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

Error

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

Error

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

Configuration

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 non-negative integer # Default: not set [buffer.internal_messages.error] smart = 180

Success

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

Configuration

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 non-negative integer # Default: not set [buffer.internal_messages.success] smart = 180

Mark as Read

When to mark a buffer as read

Configuration

on_application_exit

When exiting the application (all buffers, opened or closed, will be marked as read when the application exits).

# Type: boolean # Values: true, false # Default: false [buffer.mark_as_read] on_application_exit = false

on_buffer_close

When closing a buffer (a buffer is considered closed when it is replaced or if it is open when the application exits). If set to "scrolled-to-bottom" then a buffer will only be marked as read if it is scrolled to the bottom when closing (i.e. if the most recent messages are visible).

# Type: boolean # Values: true, false, "scrolled-to-bottom" # Default: "scrolled-to-bottom" [buffer.mark_as_read] on_buffer_close = "scrolled-to-bottom"

on_scroll_to_bottom

When scrolling to the bottom of a buffer.

# Type: boolean # Values: true, false # Default: true [buffer.mark_as_read] on_scroll_to_bottom = true

on_message_sent

When sending a message to the buffer.

# Type: boolean # Values: true, false # Default: true [buffer.mark_as_read] on_message_sent = true

Nickname

Customize how nicknames are displayed within a buffer.

Configuration

alignment

Horizontal alignment of nicknames.

# Type: string # Values: "left", "right", "top" # Default: "left" [buffer.nickname] alignment = "right"

away

Controls the appearance of away nicknames.

# Type: string or object # Values: "dimmed", "none" or { dimmed = float } # Default: "dimmed" [buffer.nickname] away = "dimmed" # with custom dimming alpha value (0.0-1.0) [buffer.nickname] away = { dimmed = 0.5 } # no away indication [buffer.nickname] away = "none"

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"

offline

Controls the appearance of offline nicknames.

# Type: string or object # Values: "solid" or "none" # Default: "solid" [buffer.nickname] offline = "solid" # no offline indication [buffer.nickname] offline = "none"

show_access_levels

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

# Type: boolean # Values: true, false # Default: true [buffer.nickname] show_access_levels = true

shown_status

What status should be indicated (by either away or offline settings), the user's current status ("current") or their status at the time of sending the message ("historical").

# Type: string or object # Values: "current" or "historical" # Default: "current" [buffer.nickname] shown_status = "current"

click

Click action for when interaction with nicknames.

  • "open-query": Open a query with the User
  • "insert-nickname": Inserts the nickname into text input
# Type: string # Values: "open-query", "insert-nickname" # Default: "open-query" [buffer.nickname] click = "open-query"

truncate

Truncate nicknames in buffer to a maximum length

# Type: integer # Values: any non-negative integer # Default: not set [buffer.nickname] truncate = 10

Server Messages

Server messages are messages sent from an IRC server.

Example

# Hide all join messages except for #halloy channel: [buffer.server_messages.join] exclude = ["*"] include = ["#halloy"] # Hide all part messages [buffer.server_messages.part] enabled = false

Types

Event TypeDescription
change_hostMessage is sent when a user changes host
change_modeMessage is sent when a mode is set
change_nickMessage is sent when a user changes nick
change_topicMessage is sent when a channel topic is changed
joinMessage is sent when a user joins a channel
kickMessage is sent when a user is kicked from a channel
monitored_offlineMessage is sent when a monitored user goes offline
monitored_onlineMessage is sent when a monitored user goes online
partMessage is sent when a user leaves a channel
quitMessage is sent when a user closes the connection to a channel or server
standard_reply_failMessage is sent when a command/function fails or an error with the session
standard_reply_noteMessage is sent when there is information about a command/function or session
standard_reply_warnMessage is sent when there is feedback about a command/function or session
topicMessage is sent when the client joins a channel to inform them of the topic (does not include message sent when topic changes)

Configuration

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 non-negative integer # Default: not set [buffer.server_messages.<server_message>] smart = 180

exclude

Exclude channels from receiving the server message. 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"]

dimmed

Dim condensed server message. Either automatically, based on text/background colors (by setting to true), or specify a dimming value in the range 0.0 (transparent) to 1.0 (no dimming).

# Type: bool or float # Values: true, false, or float # Default: true [buffer.server_messages.<server_message>] dimmed = true

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.

πŸ’‘ Not all server messages uses this setting.

# Type: string # Values: "full", "short" # Default: "full" [buffer.server_messages.<server_message>] username_format = "full"

Condense

Condense multiple consecutive server messages into a single abbreviated message

Condense

Condense multiple consecutive server messages into a single abbreviated message.

Configuration

messages

Message type(s) to condense. Supported types:

Event TypeSymbol
change-nick→
join+
part-
quit-

The color and font style of the symbols is taken from the theme setting for that event type.

# Type: array of strings # Values: ["change-nick", "join", "part", "quit"] # Default: [] [buffer.server_messages.condense] messages = ["change-nick", "join", "part", "quit"]

dimmed

Dim condensed messages. Either automatically, based on text/background colors (by setting to true), or specify a dimming value in the range 0.0 (transparent) to 1.0 (no dimming).

# Type: bool or float # Values: true, false, or float # Default: true [buffer.server_messages.condense] dimmed = true

format

How to format condensed messages:

  • "brief": Only show changes to channel state. If a user joins then leaves, then do not show any message. If a user joins, leaves, then joins again, then show that they joined the channel (+).
  • "detailed": Include messages that do not change channel state, but do not show repeated events. If a user joins then leaves, show a condensed message with both events (+-). But, if a user joins and leaves many times in a row, show only indicate that they left and re-joined (i.e. still (+-).
  • "full": Include all messages in the condensed message. If a user joins and leaves three times, then show a symbol for each event (+-+-+-).
# Type: string # Values: "brief", "detailed", "full" # Default: "brief" [buffer.server_messages.condense] format = "full"

Status Message Prefix

Status message prefix settings.

Configuration

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 = ">" }

Text Input

Customize the text input for in buffers.

Configuration

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.

Autocomplete

Customize autocomplete

Nickname

Customize nickname left of text input

Autocomplete

Customize autocomplete.

Configuration

order_by

Ordering that autocomplete uses to select from matching users.

  • "recent": Autocomplete users by their last message in the channel; the user with most recent message autocompletes first, then increasingly older messages. Users with no seen messages are matched last, in the order specified by sort_direction.
  • "alpha": Autocomplete users based on alphabetical ordering of potential matches. Ordering is ascending/descending based on sort_direction.
# Type: string # Values: "alpha", "recent" # Default: "recent" [buffer.text_input.autocomplete] order_by = "recent"

sort_direction

Sort direction when autocompleting alphabetically.

  • "asc": ascending alphabetical (aβ†’z)
  • "desc": descending alphabetical (zβ†’a)
# 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 = [": ", " "]

Nickname

Customize nickname left of text input

Configuration

enabled

Display own nickname next to text input field

# Type: boolean # Values: true, false # Default: true [buffer.text_input.nickname] enabled = true

show_access_level

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

# Type: boolean # Values: true, false # Default: true [buffer.text_input.nickname] show_access_level = true

Timestamp

Customize how timestamps are displayed within a buffer.

Configuration

format

Controls the timestamp format. The expected format is strftime.

# Type: string # Values: any valid strftime string # Default: "%R" [buffer.timestamp] format = "%R"

context_menu_format

Controls the format of shown in a timestamp's context menu. The expected format is strftime.

# Type: string # Values: any valid strftime string # Default: "%x" [buffer.timestamp] context_menu_format = "%x"

copy_format

Controls the format used when copying the timestamp into the clipboard from its context menu. The expected format is strftime. If not set, then the timestamp is copied in the date and time of day in UTC using extended format ISO 8601:2004(E) 4.3.2 with millisecond precision as is utilized in IRCv3.

# Type: string # Values: any valid strftime string or not set # Default: not set [buffer.timestamp] copy_format = "%Y-%m-%d %H:%M:%S"

brackets

Brackets around timestamps.

# Type: string # Values: { left = "<any string>", right = "<any string>" } # Default: { left = "", right = "" } [buffer.timestamp] brackets = { left = "[", right = "]" }

Url

Customize how urls behave in buffers

Configuration

prompt_before_open

Prompt before opening a hyperlink.

# Type: boolean # Values: true, false # Default: false [buffer.url] prompt_before_open = true

Commands

Commands in Halloy are prefixed with /.

Example

/me says halloy!

Types

Halloy will first try to run below commands, and lastly send it directly to the server. The argument(s) for a command are shown in tooltips, and those marked with a * will show an additional tooltip with argument-specific information on mouseover.

CommandAliasDescription
awayMark yourself as away. If already away, the status is removed
chathistoryRetrieve message history1
clearClear the message history in the current buffer
cleartopicctClear the topic of a channel2
ctcpClient-To-Client requests3
delayDelay the specified number of seconds4
detachHide the channel, but leave the bouncer's connection to the channel active[^5]5
formatfFormat text with markdown and colors
hoprejoinPart the current channel and join a new one
joinjJoin channel(s) with optional key(s)
kickKick a user from a channel2
knockRequest an invite from an invitation-only channel1
listList channel(s) on the server1
medescribeSend an action message to the channel
modemSet mode(s) on a channel or retrieve the current mode(s) set6
monitorSystem to notify when users become online/offline1
motdRequest the message of the day
msgqueryOpen a query with a nickname and send an optional message
nickChange your nickname on the current server
noticeSend a notice message to a target
partleaveLeave and close channel(s)/quer(ies) with an optional reason 7
quitDisconnect from the server with an optional reason
rawSend data to the server without modifying it
setnameChange your realname1
sysinfoSend system information (OS, CPU, memory, GPU, uptime)
topictRetrieve the topic of a channel or set a new topic2
whoisRetrieve information about user(s)

  1. Command must be supported by the bouncer/server to be executed successfully; if not supported then the command will not appear in the command picker. ↩ ↩2 ↩3 ↩4 ↩5

  2. The channel argument can be skipped when used in a channel buffer to target the channel in the buffer. ↩ ↩2 ↩3

  3. The nick argument can be skipped when used in a query buffer to target the other user in the buffer. ↩

  4. Can only be used in on_connect. ↩

  5. See soju's documentation on detaching from channels for more information. ↩

  6. The target argument can be skipped; in a channel buffer it will target the channel in the buffer, in a query buffer it will target the other user in the buffer, and in a server buffer it will target your user. ↩

  7. The targets argument can be skipped; in a channel or query buffer it will target the current buffer. ↩

CTCP

Client-to-Client Protocol response settings.

Example

# Disable responses for TIME and VERSION responses [ctcp] time = false version = false

Configuration

ping

Whether Halloy will respond to a CTCP PING message.

# Type: boolean # Values: true, false # Default: true [ctcp] ping = true

source

Whether Halloy will respond to a CTCP TIME message.

# Type: boolean # Values: true, false # Default: true [ctcp] source = true

time

Whether Halloy will respond to a CTCP TIME message.

# Type: boolean # Values: true, false # Default: true [ctcp] time = true

version

Whether Halloy will respond to a CTCP VERSION message.

# Type: boolean # Values: true, false # Default: true [ctcp] version = true

userinfo

Whether Halloy will respond to a CTCP USERINFO message. The response is enabled if this option is set to a string, which will be used as the reply.

# Type: string # Values: any string # Default: not set # Example usage: <nickname> (<realname>) # KVIrc usage: Age=<age>; Gender=<gender>; Location=<location>; Languages=<languages>; <other> [ctcp] userinfo = "<nickname> (<realname>)"

File Transfer

File transfer configuration options.

Configuration

save_directory

Default directory to save files in. If not set, user will see a file dialog. 1

# Type: string # Values: any string # Default: not set [file_transfer] save_directory = "/Users/halloy/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 non-negative integer # Default: 300 [file_transfer] timeout = 300

Auto Accept

Configure automatic acceptance of incoming file transfers

Server

Server configuration for file transfers (required when passive = true)


  1. Relative paths are prefixed with the config directory (i.e. if you have your config.toml in /home/me/.config/halloy/config.toml, path .passwd/libera will be converted to /home/me/.config/halloy/.passwd/libera). ↩

Auto Accept

Configuration for automatically accepting incoming file transfers.

Configuration

enabled

If true, automatically accept incoming file transfers. Requires save_directory to be set.

# Type: boolean # Values: true, false # Default: false [file_transfer.auto_accept] enabled = false

nicks

If true, automatically accept incoming file transfers from these nicks. Note auto_accept has to be enabled.

# Type: array of strings # Values: array of any strings # Default: [] [file_transfer.auto_accept] nicks = ["nick1", "nick2"]

masks

If true, automatically accept incoming file transfers from these nicks. Matches are made against the full nickname (i.e. nickname, username, and hostname in the format nickname!username@hostname). Note auto_accept has to be enabled.

πŸ’‘ Use toml multi-line literal strings '''\bfoo'd\b''' when writing a regex. This > allows you to write write the regex without escaping. You can also use a literal string '\bfoo\b', but then you can't use ' inside the string.

Without literal strings, you'd have to write the above as "\\bfoo'd\\b"

# Type: array of strings # Values: array of any strings # Default: [] [file_transfer.auto_accept] masks = [ '''nick!ident@example\.com''', '''.*@foobar\.com''' ]

Server

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

Configuration

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 non-negative 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 non-negative 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.

πŸ’‘ If Halloy is unable to load the specified font & weight, an fallback font may be used. If the font looks wrong, double-check the family name and that the font family has the specified weight.

Configuration

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

weight

Font weight.

# Type: string # Values: "thin", "extra-light", "light", "normal", "medium", "semibold", "bold", "extra-bold", and "black" # Default: "normal" [font] weight = "light"

bold-weight

Bold font weight. If not set, then the font weight three steps above the regular font weight (e.g. font weight "light" β†’ bold font weight "semibold").

# Type: string # Values: "thin", "extra-light", "light", "normal", "medium", "semibold", "bold", "extra-bold", and "black" # Default: not set [font] bold-weight = "semibold"

Highlights

Application wide highlights.

Nickname

Nickname highlights

Matches

Highlight based on matches

Matches

Highlight based on matches

Example

# Highlight on 'boat' and 'car' in any channel. [[highlights.match]] words = ["boat", "car"] case_insensitive = true # Highlight when regex matches in any channel except #noisy-channel. [[highlights.match]] regex = '''(?i)\bcasper\b''' exclude = ["#noisy-channel"]

Configuration

words

You can set words to be highlighted when they are written.

Example shows word matches, which will trigger on "word1", "word2" or "word3" in any channel.

# Type: array of strings # Values: array of any strings # Default: [] [[highlights.match]] words = ["word1", "word2", "word3"]

case_insensitive

This option is only available when using words as the match type. You can choose whether or not to trigger regardless of case.

# Type: boolean # Values: true, false # Default: false [[highlights.match]] words = ["word1", "word2", "word3"] case_insensitive = true

regex

Match based on regex.

Use toml multi-line literal strings '''\bfoo'd\b''' when writing a regex. This allows you to write write the regex without escaping. You can also use a literal string '\bfoo\b', but then you can't use ' inside the string.

Without literal strings, you'd have to write the above as "\\bfoo'd\\b"

Example shows a regex that matches the word "casper", regardless of case and only when it appears as a whole word in any channel.

# Type: string # Values: any string # Default: not set [[highlights.match]] regex = '''(?i)\bcasper\b'''

exclude

Channels in which you won’t be highlighted. If you pass ["#halloy"], you won’t be highlighted in that channel. You can also exclude all channels by using a wildcard: ["*"].

Example shows a regex match which will be excluded in from #noisy-channel

# Type: array of strings # Values: array of any strings # Default: [] [[highlights.match]] regex = '''(?i)\bcasper\b''' exclude = ["#noisy-channel"]

include

Channels in which you will be highlighted, only useful when combined with exclude = ["*"]. If you pass ["#halloy"], you will only be highlighted in that channel.

Example shows a words match which will only try to match in #halloy channel.

# Type: array of strings # Values: array of any strings # Default: ["*"] [[highlights.match]] words = ["word1", "word2", "word3"] exclude = ["*"] include = ["#halloy"]

Nickname

Nickname highlights

Example

# Enable nickname highlights only in channel #halloy. [highlights.nickname] exclude = ["*"] include = ["#halloy"]

Configuration

exclude

Channels in which you won’t be highlighted. If you pass ["#halloy"], you won’t be highlighted in that channel. You can also exclude all channels by using a wildcard: ["*"].

# Type: array of strings # Values: array of any strings # Default: [] [highlights.nickname] exclude = ["*"]

include

Channels in which you will be highlighted, only useful when combined with exclude = ["*"]. If you pass ["#halloy"], you will only be highlighted in that channel.

# Type: array of strings # Values: array of any strings # Default: ["*"] [highlights.nickname] exclude = ["*"] include = ["#halloy"]

case_insensitive

Whether or not to trigger regardless nickname highlight regardless of case. Uses the casemapping specified by server.

# Type: boolean # Values: true, false # Default: true [highlights.nickname] case_insensitive = false

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"

Types

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⌘ + shift + ↑ctrl + shift + ↑
restore_bufferRestore focused buffer⌘ + shift + ↓ctrl + shift + ↓
cycle_next_bufferCycle to next bufferctrl + tabctrl + tab
cycle_previous_bufferCycle to previous bufferctrl + shift + tabctrl + shift + tab
cycle_next_unread_bufferCycle to next bufferctrl + `ctrl + `
cycle_previous_unread_bufferCycle to previous bufferctrl + shift + `ctrl + shift + `
scroll_up_pageScroll buffer up a pageFn + ↑pageup
scroll_down_pageScroll buffer down a pageFn + ↓pagedown
scroll_to_topScroll to top of buffer⌘ + ↑ctrl + ↑
scroll_to_bottomScroll to bottom of buffer⌘ + ↓ctrl + ↓
leave_bufferLeave channel or close query⌘ + shift + wctrl + shift + w
mark_as_readMark focused buffer as read⌘ + shift + mctrl + shift + m
toggle_nick_listToggle nick list⌘ + βŒ₯ + mctrl + alt + m
toggle_topicToggle topic⌘ + βŒ₯ + tctrl + alt + t
toggle_sidebarToggle sidebar⌘ + βŒ₯ + bctrl + alt + b
toggle_fullscreenToggle fullscreen⌘ + ctrl + fF11
command_barToggle command bar⌘ + kctrl + k
reload_configurationReload configuration file⌘ + rctrl + r
file_transfersToggle File Transfers Buffer⌘ + jctrl + j
logsToggle Logs Buffer⌘ + lctrl + l
theme_editorToggle Theme Editor Window⌘ + tctrl + t
highlightsToggle Highlights Window⌘ + ictrl + i
quit_applicationQuit HalloyNot setNot set

Logs

Customize log buffer

Configuration

file_level

The least urgent (most verbose) log level to record to the log file. E.g. a file_level setting of "debug" will record all ERROR, WARN, INFO, and DEBUG messages to the log file. The log file is overwritten on each launch (i.e. contains log messages for the last session only). It can be accessed at:

  • Windows: %AppData%\Roaming\halloy\halloy.log
  • Mac: ~/Library/Application Support/halloy/halloy.log or $HOME/.local/share/halloy/halloy.log
  • Linux: $XDG_DATA_HOME/halloy/halloy.log, $HOME/.local/share/halloy/halloy.log, or $HOME/.var/app/org.squidowl.halloy/data/halloy/halloy.log (Flatpak)

⚠️ Changes to file_level require an application restart to take effect.

# Type: string # Values: "off", "error", "warn", "info", "debug", "trace" # Default: "debug" [logs] file_level = "debug"

pane_level

The least urgent (most verbose) log level to record to the Logs pane. E.g. a pane_level setting of "info" will record all ERROR, WARN, and INFO messages to the Logs pane. Log messages that are not recorded to the Logs pane may still be found in the log file.

# Type: string # Values: "off", "error", "warn", "info", "debug", "trace" # Default: "info" [logs] pane_level = "info"

Notifications

Customize and enable notifications.

Example

[notifications] direct_message = { sound = "peck", show_toast = true } [notifications.highlight] sound = "dong" exclude = ["NickServ", "#halloy"]

Types

Following notifications are available:

NameDescriptionContent
connectedTriggered when a server is connectedN/A
direct_messageTriggered when a direct message is receivedMessage text
disconnectedTriggered when a server disconnectsN/A
file_transfer_requestTriggered when a file transfer request is receivedFile name
highlightTriggered when you were highlighted in a bufferMessage text
monitored_onlineTriggered when a user you're monitoring is onlineN/A
monitored_offlineTriggered when a user you're monitoring is offlineN/A
reconnectedTriggered when a server reconnectsN/A

Configuration

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

show_content

Notification should show the content of the trigger (as described in the table above)).

# Type: boolean # Values: true, false # Default: false [notifications.<notification>] show_content = true

delay

Delay in milliseconds before triggering the next notification.

# Type: integer # Values: any non-negative 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_message|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_message|file_transfer_request>] include = ["HalloyUser1"] [notifications.highlight] include = ["HalloyUser1", "#halloy"]

Pane

Pane settings

Configuration

restore_on_launch

Restore the panes that were open when Halloy was last closed when launching the application.

# Type: boolean # Values: true, false # Default: true [pane] restore_on_launch = false

scrollbar

Scrollbar configuration.

width

Width of the scrollbar.

# Type: integer # Values: any non-negative integer # Default: 5 [pane.scrollbar] width = 5

scroller_width

Width of the scrollbar scroller.

# Type: integer # Values: any non-negative integer # Default: 5 [pane.scrollbar] scroller_width = 5

split_axis

Default axis used when splitting the focused pane to create a new pane (i.e. default orientation of the divider between panes). "shorter" will compare the width and height of the pane to select the splitting axis; if the width is shorter then the horizontal axis is selected, and if the height is shorter then the vertical axis is selected. "largest-shorter" will split the largest pane in the main window using the same method as "shorter", rather than splitting the focused pane.

# Type: string # Values: "horizontal", "largest-shorter", "shorter", "vertical" # Default: "shorter" [pane] split_axis = "vertical"

Platform Specific

Platform specific settings for Halloy.

macOS

macOS specific settings

Linux

Linux specific settings

Windows

Windows specific settings

Linux

Linux specific settings

Configuration

decorations

Whether the window should have a border, a title bar, etc. or not.

πŸ’‘ A restart is required for this change to take effect.

# Type: boolean # Values: true, false # Default: true [platform_specific] linux.decorations = false

macOS

macOS specific settings

Configuration

content_padding

Controls if the content (panes) are rendered inside the the titlebar content view, or padded just below it.

# Type: string # Values: "embedded-content", "padded-content" # Default: "embedded-content" [platform_specific] macos.content_padding = "embedded-content"

Controls if the sidebar is rendered inside the the titlebar content view, or padded just below it.

# Type: string # Values: "embedded-content", "padded-content" # Default: "padded-content" [platform_specific] macos.sidebar_padding = "embedded-content"

decorations

Whether the window should have a border, traffic light, a title bar, etc. or not.

πŸ’‘ A restart is required for this change to take effect.

# Type: boolean # Values: true, false # Default: true [platform_specific] macos.decorations = false

Windows

Windows specific settings

Configuration

decorations

Whether the window should have a border, a title bar, etc. or not.

πŸ’‘ A restart is required for this change to take effect.

# Type: boolean # Values: true, false # Default: true [platform_specific] windows.decorations = false

Preview

URL preview settings for Halloy.

Configuration

enabled

Enable or disable previews globally

# Type: boolean # Values: true, false # Default: true [preview] enabled = true

Request

Request settings for previews.

Image

Specific image preview settings.

Card

Specific card preview settings.

Card

Specific card preview settings.

Example

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

Configuration

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 & queries. 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 & queries 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 & queries. If you pass ["#halloy"], the channel #halloy will not show image previews. You can also exclude all channels & queries by using a wildcard: ["*"].

# Type: array of strings # Values: array of any strings # Default: [] [preview.card] exclude = []

Image

Specific image preview settings.

Example

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

Configuration

action

Action when clicking on a image. open-url will open the image in the browser, and preview will display a larger version of the image in-app.

# Type: string # Values: "open-url", "preview" # Default: "preview" [preview.image] action = "preview"

include

Include image previews from channels & queries. 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 & queries 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 & queries. If you pass ["#halloy"], the channel #halloy will not show image previews. You can also exclude all channels & queries by using a wildcard: ["*"].

# Type: array of strings # Values: array of any strings # Default: [] [preview.image] exclude = []

Request

Request settings for previews.

Configuration

user_agent

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

# Type: string # Values: any string # Default: "WhatsApp/2" [preview.request] user_agent = "WhatsApp/2"

timeout_ms

Request timeout in milliseconds. Defaults is 10s.

# Type: integer # Values: any non-negative 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 non-negative 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 non-negative 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 non-negative integer # Default: 4 [preview.request] concurrency = 4

delay_ms

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

# Type: integer # Values: any non-negative integer # Default: 500 [preview.request] delay_ms = 500

Proxy

Proxy settings for Halloy.

HTTP

Http proxy settings

SOCKS5

Socks5 proxy settings

Tor

Tor proxy settings

HTTP

Http proxy settings.

Example

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

Configuration

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 non-negative 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"

SOCKS5

Socks5 proxy settings.

Example

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

Configuration

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 non-negative 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"

Tor

Tor proxy settings. Utilizes Arti to integrate Tor support directly into Halloy. Does not integrate into a pre-existing Tor setup. To utilize an existing Tor daemon, use [proxy.socks5] instead.

It accepts no further configuration.

⚠️ Tor support is not included by default. You must build Halloy with the tor feature to use this proxy type. See Optional Features for build instructions.

Example

[proxy.tor]

Scale Factor

Application wide scale factor.

Configuration

scale_factor

⚠️ 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.

Example

# with tls [servers.liberachat] server = "irc.libera.chat" nickname = "bar" # without tls [servers.slashnet] server = "irc.slashnet.org" port = 6667 nickname = "foo" use_tls = false

πŸ’‘ Guide: Multiple servers

Configuration

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_file_first_line_only

Read nick_password from the first line of nick_password_file only.

# Type: boolean # Values: true, false # Default: true [servers.<name>] nick_password_file_first_line_only = true

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. If you want to use a plain text port like 6667 you MUST also change the use_tls setting.

# Type: integer # Values: any non-negative 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_file_first_line_only

Read password from the first line of password_file only.

# Type: boolean # Values: true, false # Default: true [servers.<name>] password_file_first_line_only = true

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 non-negative integer # Default: 180 [servers.<name>] ping_time = 180

ping_timeout

The amount of time in seconds to wait for a ping response before attempting to reconnect.

# Type: integer # Values: any non-negative 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 non-negative 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: true [servers.<name>] use_tls = true

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, in the order they are specified. The /delay <seconds> command can be used to add a delay between commands.

# Type: array of string # Values: array of any strings # Default: not set [servers.<name>] on_connect = ["/msg NickServ IDENTIFY foo bar", "/delay 2", "/join registered-club"]

anti_flood

The time (in milliseconds) between sending messages to servers without SAFERATE. Timing is not strictly guaranteed; small groups of messages may be allowed to be sent at a faster rate, messages may be delayed in order to be batched, automated messages are included in the queue (most at a lower priority than user messages), etc.

# Type: integer # Values: 100 .. 60000 # Default: 2000 [servers.<name>] anti_flood = 2000

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. When the server does not support SAFERATE (and anti-flood protections are enabled) then who_poll_interval will be increased to more than twice anti_flood if it is not already.

# 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

Filters

Filter messages based on various criteria

SASL Plain

Plain SASL auth using a username and password

SASL External

External SASL auth uses a PEM encoded X509 certificate.

Filters

Filter messages based on various criteria.

Configuration

ignore

A list of nicknames to ignore. Optionally, the nickname may be preceded by a channel name like so: "#channel nickname" - this will ignore the nickname for a specific channel only.

# Type: array of strings # Values: array of any strings # Default: not set [servers.<name>.filters] ignore = [ "ignored_user", "another_user", "#specific-channel user_only_for_channel" ]

SASL External

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

Configuration

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. 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\\"). ↩ ↩2

  2. Relative paths are prefixed with the config directory (i.e. if you have your config.toml in /home/me/.config/halloy/config.toml, path .passwd/libera will be converted to /home/me/.config/halloy/.passwd/libera). ↩ ↩2

SASL Plain

Plain SASL auth using a username and password

Configuration

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_file_first_line_only

Read password from the first line of password_file only.

# Type: boolean # Values: true, false # Default: true [servers.<name>] password_file_first_line_only = true

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 = ""

Sidebar

Sidebar settings for Halloy.

Configuration

server_icon_size

Adjust server icon size.

Note: If set larger than the line height of the specified font then the icon will not render.

# Type: integer # Values: any positive integer" # Default: 12 [sidebar] server_icon_size = 12

position

Sidebar position within the application window.

# Type: string # Values: "left", "top", "right", "bottom" # Default: "left" [sidebar] position = "left"

max_width

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

# Type: integer # Values: any non-negative integer # Default: not set [sidebar] max_width = 200

show_menu_button

Show or hide the user menu button in the sidebar.

# Type: bool # Values: true, false # Default: true [sidebar] show_menu_button = true

order_by

Ordering that servers are listed in the sidebar uses to select from matching users.

  • "config": The same order they are specified in the configuration file.
  • "alpha": Case-insensitive alphabetical ordering.
# Type: string # Values: "alpha", "config" # Default: "alpha" [sidebar] order_by = "config"

Scrollbar

Scrollbar in sidebar

Unread Indicator

Unread buffer indicator style

Scrollbar

Scrollbar in sidebar

Configuration

width

Width of the scrollbar.

# Type: integer # Values: any non-negative integer # Default: 5 [sidebar.scrollbar] width = 5

scroller_width

Width of the scrollbar scroller.

# Type: integer # Values: any non-negative integer # Default: 5 [sidebar.scrollbar] scroller_width = 5

Unread Indicator

Unread buffer indicator style.

Configuration

title

Changes buffer title color when unread messages are present

# Type: boolean # Values: true, false # Default: false [sidebar.unread_indicator] title = false

icon

Changes the icon which appears when unread messages are present. To disable use "none".

# Type: string # Values: "dot", "circle-empty", "dot-circled", "certificate", "asterisk", "speaker", "lightbulb", "star", "none" # Default: "dot" [sidebar.unread_indicator] icon = "dot"

highlight_icon

Changes the icon which appears when unread highlight messages are present. To disable use "none".

# Type: string # Values: "dot", "circle-empty", "dot-circled", "certificate", "asterisk", "speaker", "lightbulb", "star", "none" # Default: "circle-empty" [sidebar.unread_indicator] highlight_icon = "circle-empty"

icon_size

Changes the unread icon size.

Note: If set larger than the line height of the specified font then the icon will not render.

# Type: integer # Values: any positive integer" # Default: 6 [sidebar.unread_indicator] icon_size = 6

highlight_icon_size

Changes the highlight unread icon size.

Note: If set larger than the line height of the specified font then the icon will not render.

# Type: integer # Values: any positive integer" # Default: 8 [sidebar.unread_indicator] highlight_icon_size = 8

Themes

Example

# Static single theme = "ferra" # Static multiple (random selection) theme = ["ferra", "booberry"] # Dynamic single theme = { light = "ferra-light", dark = "ferra" } # Dynamic multiple (random selection) theme = { light = ["ferra-light", "booberry-light"], dark = ["ferra", "booberry"] }

Configuration

⚠️ theme is a root key, so it must be placed before every section.

theme

Specify the theme name(s) to use. The theme must correspond to a file in the themes folder of your Halloy configuration directory. For more details, see the configuration overview. The default theme in Halloy is Ferra.

When multiple themes are specified, Halloy will randomly select one each time the application starts. When a dynamic theme is used, Halloy will match the appearance of the OS.

  • type: string, array of strings, or object
  • values: "<string>", ["<string>", "<string>"], { light = "<string>", dark = "<string>" }, { light = ["<string>", "<string>"], dark = ["<string>", "<string>"] }
  • default: "ferra"

πŸ’‘ See all community created themes and base16 themes.

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 fall back to transparent. A custom theme is structured as follows:

[general] background = "<string>" border = "<string>" horizontal_rule = "<string>" scrollbar = "<string>" unread_indicator = "<string>" highlight_indicator = "<string>" [text] primary = "<string>" secondary = "<string>" tertiary = "<string>" success = "<string>" error = "<string>" warning = "<string>" info = "<string>" debug = "<string>" trace = "<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>" nickname_offline = "<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>" # change_mode = "<string>" # change_nick = "<string>" # join = "<string>" # kick = "<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>" # wallops = "<string>" default = "<string>"

πŸ’‘ The default Ferra theme toml file can be viewed on GitHub.

Community

Community created themes for Halloy

Base16

Community collection of base16 themes

Base16

The base16 color scheme framework includes hundreds of color schemes build using 16 colors. These color schemes 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"

Community

Discover community created themes for Halloy at https://themes.halloy.chat.

To use these themes, download them and place the files in the themes directory within your configuration folder. For more details, see the configuration overview.

Tooltips

Control if tooltips are displayed or not.

Configuration

tooltip

πŸ’‘ tooltips is a root key, so it must be placed before any section.

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