1. Introduction

This document is the specification of weechat relay protocol: the protocol used to relay WeeChat data to clients, which are mostly remote interfaces.

1.1. Terminology

The following terms are used in this document:

  • relay: this is the WeeChat with relay plugin, which acts as "server" and allows clients to connect

  • client: this is another software, connected to relay via a network connection; in most cases, this client is a remote interface.

1.2. Network diagram

The clients are connected to relay like shown in this diagram:

                                              ┌──────────┐ Workstation
 ┌────────┐                               ┌───┤ client 1 │ (Linux, Windows,
 │  irc   │◄──┐  ╔═══════════╤═══════╗    │   └──────────┘ BSD, macOS, …)
 └────────┘   └──╢           │       ║◄───┘   ┌──────────┐
   ......        ║  WeeChat  │ Relay ║◄───────┤ client 2 │ Mobile device
 ┌────────┐   ┌──╢           │       ║◄───┐   └──────────┘ (Android, iPhone, …)
 │ jabber │◄──┘  ╚═══════════╧═══════╝    │      ......
 └────────┘                               │   ┌──────────┐
   ......                                 └───┤ client N │ Other devices
                                              └──────────┘


└────────────┘   └───────────────────┘╘══════╛└────────────────────────────────┘
network servers    ncurses interface    relay         remote interfaces
All clients here are clients using weechat protocol in relay plugin.
The relay plugin also allows api and irc protocols (not described in this document).

2. Protocol generalities

  • Connections from client to relay are made using TCP sockets on IP/port used by relay plugin to listen to new connections.

  • Number of clients is limited by the option relay.network.max_clients.

  • Each client is independent from other clients.

  • Messages from client to relay are called commands, they are sent as text (a string).

  • Messages from relay to client are called messages, they are sent as binary data.

3. Commands (client → relay)

Commands have format:

(id) command arguments\n

Fields are:

  • id: optional message identifier that will be sent in answer from relay; it must be enclosed in parentheses, and must not start with an underscore (ids starting with underscore are reserved for WeeChat event messages)

  • command: a command (see table below)

  • arguments: optional arguments for command (many arguments are separated by spaces).

List of available commands (detail in next chapters):

Command Description

handshake

Handshake: prepare client authentication and set options, before init command.

init

Authenticate with relay.

hdata

Request a hdata.

info

Request an info.

infolist

Request an infolist.

nicklist

Request a nicklist.

input

Send data to a buffer (text or command).

completion

Request completion of a string.

sync

Synchronize buffer(s): get updates for buffer(s).

desync

Desynchronize buffer(s): stop updates for buffer(s).

quit

Disconnect from relay.

3.1. handshake

WeeChat ≥ 2.9, updated in versions 3.5, 4.0.0.

Perform an handshake between the client and WeeChat: this is required in most cases to know the session settings and prepare the authentication with the init command.

Only one handshake is allowed before the init command.

Syntax:

(id) handshake [<option>=<value>,[<option>=<value>,...]]

Arguments:

  • option: one of following options:

    • password_hash_algo: list of hash algorithms supported by the client (separated by colons), allowed values are:

      • plain: plain text password (no hash)

      • sha256: password salted and hashed with SHA256 algorithm

      • sha512: password salted and hashed with SHA512 algorithm

      • pbkdf2+sha256: password salted and hashed with PBKDF2 algorithm (using SHA256 hash)

      • pbkdf2+sha512: password salted and hashed with PBKDF2 algorithm (using SHA512 hash)

    • compression: list of supported compression types supported by the client (separated by colons and sorted from most important to the fallback value); if compression is enabled, messages from relay to client are compressed to save bandwidth; allowed values are:

      • off: no compression (default if option is not given)

      • zlib: compress with zlib  (WeeChat ≥ 0.3.7)

      • zstd: compress with Zstandard : better compression and much faster than zlib for both compression and decompression (WeeChat ≥ 3.5)

    • escape_commands: commands sent by the client to relay must be escaped: all backslashes are interpreted and a single backslash must be escaped (\\); this allows for example the client to send multiline messages (chars \n are converted to newlines, see input command) (WeeChat ≥ 4.0.0)

Notes about option password_hash_algo:

  • If the option is not given (or if the handshake command is not sent by the client), relay uses automatically plain authentication (if allowed on relay side).

  • Relay chooses the most secure algorithm available on both client and relay, by order of priority from first (most secure) to last used:

    1. pbkdf2+sha512

    2. pbkdf2+sha256

    3. sha512

    4. sha256

    5. plain

WeeChat replies with a hashtable containing the following keys and values:

  • password_hash_algo: the password authentication negotiated: supported by both the client and relay:

    • (empty value): negotiation failed, password authentication is NOT possible; in this case the connection with the client is immediately closed

    • plain

    • sha256

    • sha512

    • pbkdf2+sha256

    • pbkdf2+sha512

  • password_hash_iterations: number of iterations for hash (for the PBKDF2 algorithm only)

  • totp:

    • on: Time-based One-Time Password (TOTP) is configured and expected in the init command

    • off: Time-based One-Time Password (TOTP) is not enabled and not needed in the init command

  • nonce: a buffer of unpredictable bytes, sent as hexadecimal, to prevent replay attacks; if password_hash_algo is a hash algorithm, the client must compute the hash of password on this nonce, concatenated with a client nonce and the user password (the relay nonce + the client nonce is the salt used in the password hash algorithm)

  • compression: compression type:

    • off: messages are not compressed

    • zlib: messages are compressed with zlib 

    • zstd: messages are compressed with Zstandard 

  • escape_commands:

    • on: all backslashes are interpreted in the client messages

    • off: backslashes are NOT interpreted in the client messages and used as-is

With WeeChat ≤ 2.8, the command handshake is not implemented, WeeChat silently ignores this command, even if it is sent before the init command.
So it is safe to send this command to any WeeChat version.

Examples:

  • Nothing offered by the client, authentication password "plain" will be used if allowed on relay side:

(handshake) handshake

Response:

id: 'handshake'
htb: {
    'password_hash_algo': 'plain',
    'password_hash_iterations': '100000',
    'totp': 'on',
    'nonce': '85B1EE00695A5B254E14F4885538DF0D',
    'compression': 'off',
    'escape_commands': 'off',
}
  • Escape of commands enabled by the client (WeeChat ≥ 4.0.0):

(handshake) handshake escape_commands=on

Response:

id: 'handshake'
htb: {
    'password_hash_algo': 'plain',
    'password_hash_iterations': '100000',
    'totp': 'on',
    'nonce': '85B1EE00695A5B254E14F4885538DF0D',
    'compression': 'off',
    'escape_commands': 'on',
}
  • Only "plain" is supported by the client:

(handshake) handshake password_hash_algo=plain

Response:

id: 'handshake'
htb: {
    'password_hash_algo': 'plain',
    'password_hash_iterations': '100000',
    'totp': 'on',
    'nonce': '85B1EE00695A5B254E14F4885538DF0D',
    'compression': 'off',
    'escape_commands': 'off',
}
  • Only "plain", "sha256" and "pbkdf2+sha256" are supported by the client:

(handshake) handshake password_hash_algo=plain:sha256:pbkdf2+sha256

Response:

id: 'handshake'
htb: {
    'password_hash_algo': 'pbkdf2+sha256',
    'password_hash_iterations': '100000',
    'totp': 'on',
    'nonce': '85B1EE00695A5B254E14F4885538DF0D',
    'compression': 'off',
    'escape_commands': 'off',
}

The client can authenticate with this command (see init command), the salt is the relay nonce + client nonce ("A4B73207F5AAE4" in hexadecimal), the password is "test" in this example:

init password_hash=pbkdf2+sha256:85b1ee00695a5b254e14f4885538df0da4b73207f5aae4:100000:ba7facc3edb89cd06ae810e29ced85980ff36de2bb596fcf513aaab626876440
  • Only "sha256" and "sha512" are supported by the client, enable zstd (preferred) or zlib compression:

(handshake) handshake password_hash_algo=sha256:sha512,compression=zstd:zlib

Response:

id: 'handshake'
htb: {
    'password_hash_algo': 'sha512',
    'password_hash_iterations': '100000',
    'totp': 'on',
    'nonce': '85B1EE00695A5B254E14F4885538DF0D',
    'compression': 'zstd',
    'escape_commands': 'off',
}

3.2. init

Updated in versions 2.4, 2.8, 2.9, 3.5.

Authenticate with relay.

This must be first command sent to relay (only handshake command can be sent before init).
If not sent, relay will close connection on first command received (except handshake), without warning.

Syntax:

(id) init [<option>=<value>,[<option>=<value>,...]]

Arguments:

  • option: one of following options:

    • password: password used to authenticate on relay (option relay.network.password in WeeChat)

    • password_hash: hash of password used to authenticate on relay (option relay.network.password in WeeChat), see below for the format (WeeChat ≥ 2.8)

    • totp: Time-based One-Time Password (TOTP) used as secondary authentication factor, in addition to the password (option relay.network.totp_secret in WeeChat) (WeeChat ≥ 2.4)

With WeeChat ≥ 1.6, commas can be escaped in the value, for example init password=foo\,bar to send the password "foo,bar".

Format of hashed password is one of the following, where hash is the hashed password as hexadecimal:

  • sha256:salt:hash with:

    • salt: salt (hexadecimal), which must start with the server nonce, concatenated to the client nonce

    • hash: the hashed salt + password (hexadecimal)

  • sha512:salt:hash with:

    • salt: salt (hexadecimal), which must start with the server nonce, concatenated to the client nonce

    • hash: the hashed salt + password (hexadecimal)

  • pbkdf2+sha256:salt:iterations:hash with:

    • salt: salt (hexadecimal), which must start with the server nonce, concatenated to the client nonce

    • iterations: number of iterations

    • hash: the hashed salt + password with SHA256 algorithm (hexadecimal)

  • pbkdf2+sha512:salt:iterations:hash with:

    • salt: salt (hexadecimal), which must start with the server nonce, concatenated to the client nonce

    • iterations: number of iterations

    • hash: the hashed salt + password with SHA512 algorithm (hexadecimal)

Hexadecimal strings can be lower or upper case, relay can decode both.

Examples:

  • Initialize with password:

init password=mypass
  • Initialize with commas in the password (WeeChat ≥ 1.6):

init password=mypass\,with\,commas
  • Initialize with password and TOTP (WeeChat ≥ 2.4):

init password=mypass,totp=123456
  • Initialize with hashed password "test" (SHA256: salt=relay nonce + client nonce) (WeeChat ≥ 2.9):

init password_hash=sha256:85b1ee00695a5b254e14f4885538df0da4b73207f5aae4:2c6ed12eb0109fca3aedc03bf03d9b6e804cd60a23e1731fd17794da423e21db
  • Initialize with hashed password "test" (SHA512: salt=relay nonce + client nonce) (WeeChat ≥ 2.9):

init password_hash=sha512:85b1ee00695a5b254e14f4885538df0da4b73207f5aae4:0a1f0172a542916bd86e0cbceebc1c38ed791f6be246120452825f0d74ef1078c79e9812de8b0ab3dfaf598b6ca14522374ec6a8653a46df3f96a6b54ac1f0f8
  • Initialize with hashed password "test" (PBKDF2: SHA256, salt=relay nonce + client nonce, 100000 iterations) (WeeChat ≥ 2.9):

init password_hash=pbkdf2+sha256:85b1ee00695a5b254e14f4885538df0da4b73207f5aae4:100000:ba7facc3edb89cd06ae810e29ced85980ff36de2bb596fcf513aaab626876440

3.3. hdata

Request a hdata.

Syntax:

(id) hdata <path> [<keys>]

Arguments:

  • path: path to a hdata, with format: "hdata:pointer/var/var/…​/var", the last var is the hdata returned:

    • hdata: name of hdata

    • pointer: pointer (eg: "0x1234abcd") or list name (for example: "gui_buffers") (count allowed, see below)

    • var: a variable name in parent hdata (previous name in path) (count allowed, see below)

  • keys: comma-separated list of keys to return in hdata (if not specified, all keys are returned, which is not recommended on large hdata structures)

A count is allowed after pointer and variables, with format "(N)". Possible values are:

  • positive number: iterate using next element, N times

  • negative number: iterate using previous element, N times

  • *: iterate using next element, until end of list

With WeeChat ≥ 1.6, if the hdata path is invalid or if a NULL pointer is found, an empty hdata is returned (see example in hdata object).
With older versions, nothing was returned.

Examples:

  • Request "number" and "full_name" of all buffers:

(hdata_buffers) hdata buffer:gui_buffers(*) number,full_name

Response:

id: 'hdata_buffers'
hda:
    keys: {
        'number': 'int',
        'full_name': 'str',
    }
    path: ['buffer']
    item 1:
        __path: ['0x558d61ea3e60']
        number: 1
        full_name: 'core.weechat'
    item 2:
        __path: ['0x558d62840ea0']
        number: 1
        full_name: 'irc.server.libera'
    item 3:
        __path: ['0x558d62a9cea0']
        number: 2
        full_name: 'irc.libera.#weechat'
  • Request all lines of first buffer:

(hdata_lines) hdata buffer:gui_buffers/own_lines/first_line(*)/data

Response:

id: 'hdata_lines'
hda:
    keys: {
        'buffer': 'ptr',
        'y': 'int',
        'date': 'tim',
        'date_usec': 'int',
        'date_printed': 'tim',
        'date_usec_printed': 'int',
        'str_time': 'str',
        'tags_count': 'int',
        'tags_array': 'arr',
        'displayed': 'chr',
        'notify_level': 'chr',
        'highlight': 'chr',
        'refresh_needed': 'chr',
        'prefix': 'str',
        'prefix_length': 'int',
        'message': 'str',
    }
    path: ['buffer', 'lines', 'line', 'line_data']
    item 1:
        __path: ['0x558d61ea3e60', '0x558d61ea40e0', '0x558d62920d80', '0x558d62abf040']
        buffer: '0x558d61ea3e60'
        y: -1
        date: 1588404926
        date_usec: 118712
        date_printed: 1588404926
        date_usec_printed: 118712
        str_time: 'F@0025209F@0024535F@0024026'
        tags_count: 0
        tags_array: []
        displayed: 1
        notify_level: 0
        highlight: 0
        refresh_needed: 0
        prefix: ''
        prefix_length: 0
        message: 'this is the first line'
    item 2:
        __path: ['0x558d61ea3e60', '0x558d61ea40e0', '0x558d626779f0', '0x558d62af9700']
        buffer: '0x558d61ea3e60'
        y: -1
        date: 1588404930
        date_usec: 25
        date_printed: 1588404930
        date_usec_printed: 25
        str_time: 'F@0025209F@0024535F@0024030'
        tags_count: 0
        tags_array: []
        displayed: 1
        notify_level: 0
        highlight: 0
        refresh_needed: 0
        prefix: ''
        prefix_length: 0
        message: 'this is the second line'
  • Request the hotlist content:

(hdata_hotlist) hdata hotlist:gui_hotlist(*)

Response:

id: 'hdata_hotlist'
hda:
    keys: {
        'priority': 'int',
        'creation_time.tv_sec': 'tim',
        'creation_time.tv_usec': 'lon',
        'buffer': 'ptr',
        'count': 'arr',
        'prev_hotlist': 'ptr',
        'next_hotlist': 'ptr',
    }
    path: ['hotlist']
    item 1:
        __path: ['0x558d629601b0']
        priority: 3
        creation_time.tv_sec: 1588405398
        creation_time.tv_usec: 355383
        buffer: '0x558d62a9cea0'
        count: [1, 1, 0, 1]
        prev_hotlist: '0x0'
        next_hotlist: '0x0'

3.4. info

Request an info.

Syntax:

(id) info <name> [<arguments>]

Arguments:

  • name: name of info to retrieve

  • arguments: arguments (optional)

Examples:

  • Request WeeChat version:

(info_version) info version

Response:

id: 'info_version'
inf: ('version', '2.9-dev')
  • Request WeeChat version as number:

(info_version_number) info version_number

Response:

id: 'info_version_number'
inf: ('version_number', '34144256')
  • Request WeeChat directory:

(info_weechat_config_dir) info weechat_config_dir

Response:

id: 'info_weechat_config_dir'
inf: ('weechat_config_dir', '/home/user/.config/weechat')

3.5. infolist

Request an infolist.

Content of infolist is a duplication of actual data. Wherever possible, use hdata command, which is direct access to data (it is faster, uses less memory and returns smaller objects in message).

Syntax:

(id) infolist <name> [<pointer> [<arguments>]]

Arguments:

  • name: name of infolist to retrieve

  • pointer: pointer (optional)

  • arguments: arguments (optional)

Examples:

  • Request infolist "buffer":

(infolist_buffer) infolist buffer

Response:

id: 'infolist_buffer'
inl:
    name: buffer
    item 1:
        pointer: '0x558d61ea3e60'
        current_buffer: 1
        plugin: '0x0'
        plugin_name: 'core'
        number: 1
        layout_number: 1
        layout_number_merge_order: 0
        name: 'weechat'
        full_name: 'core.weechat'
        old_full_name: None
        short_name: 'weechat'
        type: 0
        notify: 3
        num_displayed: 1
        active: 1
        hidden: 0
        zoomed: 0
        print_hooks_enabled: 1
        day_change: 1
        clear: 1
        filter: 1
        closing: 0
        first_line_not_read: 0
        lines_hidden: 0
        prefix_max_length: 0
        time_for_each_line: 1
        nicklist_case_sensitive: 0
        nicklist_display_groups: 1
        nicklist_max_length: 0
        nicklist_count: 0
        nicklist_groups_count: 0
        nicklist_nicks_count: 0
        nicklist_visible_count: 0
        title: 'WeeChat 2.9-dev (C) 2003-2020 - https://weechat.org/'
        input: 1
        input_get_any_user_data: 0
        input_get_unknown_commands: 0
        input_get_empty: 0
        input_multiline: 0
        input_buffer: ''
        input_buffer_alloc: 256
        input_buffer_size: 0
        input_buffer_length: 0
        input_buffer_pos: 0
        input_buffer_1st_display: 0
        num_history: 0
        text_search: 0
        text_search_direction: 0
        text_search_exact: 0
        text_search_regex: 0
        text_search_regex_compiled: '0x0'
        text_search_where: 0
        text_search_history: 0
        text_search_found: 0
        text_search_ptr_history: '0x0'
        text_search_input: None
        highlight_words: None
        highlight_disable_regex: None
        highlight_disable_regex_compiled: '0x0'
        highlight_regex: None
        highlight_regex_compiled: '0x0'
        highlight_tags_restrict: None
        highlight_tags: None
        hotlist_max_level_nicks: None
        keys_count: 0
        localvar_name_00000: 'plugin'
        localvar_value_00000: 'core'
        localvar_name_00001: 'name'
        localvar_value_00001: 'weechat'
  • Request infolist "window":

(infolist_window) infolist window

Response:

id: 'infolist_window'
inl:
    name: window
    item 1:
        pointer: '0x558d61ddc800'
        current_window: 1
        number: 1
        x: 14
        y: 0
        width: 259
        height: 71
        width_pct: 100
        height_pct: 100
        chat_x: 14
        chat_y: 1
        chat_width: 259
        chat_height: 68
        buffer: '0x558d61ea3e60'
        start_line_y: 0

3.6. nicklist

Request a nicklist, for one or all buffers.

Syntax:

(id) nicklist [<buffer>]

Arguments:

  • buffer: pointer (eg: "0x1234abcd") or full name of buffer (for example: core.weechat or irc.libera.#weechat)

Examples:

  • Request nicklist for all buffers:

(nicklist_all) nicklist

Response:

id: 'nicklist_all'
hda:
    keys: {
        'group': 'chr',
        'visible': 'chr',
        'level': 'int',
        'name': 'str',
        'color': 'str',
        'prefix': 'str',
        'prefix_color': 'str',
    }
    path: ['buffer', 'nicklist_item']
    item 1:
        __path: ['0x558d61ea3e60', '0x558d61ea4120']
        group: 1
        visible: 0
        level: 0
        name: 'root'
        color: None
        prefix: None
        prefix_color: None
    item 2:
        __path: ['0x558d62840ea0', '0x558d61e75f90']
        group: 1
        visible: 0
        level: 0
        name: 'root'
        color: None
        prefix: None
        prefix_color: None
    item 3:
        __path: ['0x558d62a9cea0', '0x558d62abf2e0']
        group: 1
        visible: 0
        level: 0
        name: 'root'
        color: None
        prefix: None
        prefix_color: None
    item 4:
        __path: ['0x558d62a9cea0', '0x558d62afb9d0']
        group: 1
        visible: 1
        level: 1
        name: '000|o'
        color: 'weechat.color.nicklist_group'
        prefix: None
        prefix_color: None
    item 5:
        __path: ['0x558d62a9cea0', '0x558d62aff930']
        group: 0
        visible: 1
        level: 0
        name: 'FlashCode'
        color: 'weechat.color.chat_nick_self'
        prefix: '@'
        prefix_color: 'lightgreen'
    item 6:
        __path: ['0x558d62a9cea0', '0x558d62af9930']
        group: 1
        visible: 1
        level: 1
        name: '001|v'
        color: 'weechat.color.nicklist_group'
        prefix: None
        prefix_color: None
    item 7:
        __path: ['0x558d62a9cea0', '0x558d62afc510']
        group: 1
        visible: 1
        level: 1
        name: '999|...'
        color: 'weechat.color.nicklist_group'
        prefix: None
        prefix_color: None
    item 8:
        __path: ['0x558d62a9cea0', '0x558d6292c290']
        group: 0
        visible: 1
        level: 0
        name: 'flashy'
        color: '142'
        prefix: ' '
        prefix_color: 'lightblue'
    item 9:
        __path: ['0x558d62914680', '0x558d62afc4b0']
        group: 1
        visible: 0
        level: 0
        name: 'root'
        color: None
        prefix: None
        prefix_color: None
  • Request nicklist for buffer "irc.libera.#weechat":

(nicklist_weechat) nicklist irc.libera.#weechat

Response:

id: 'nicklist_weechat'
hda:
    keys: {
        'group': 'chr',
        'visible': 'chr',
        'level': 'int',
        'name': 'str',
        'color': 'str',
        'prefix': 'str',
        'prefix_color': 'str',
    }
    path: ['buffer', 'nicklist_item']
    item 1:
        __path: ['0x558d62a9cea0', '0x558d62abf2e0']
        group: 1
        visible: 0
        level: 0
        name: 'root'
        color: None
        prefix: None
        prefix_color: None
    item 2:
        __path: ['0x558d62a9cea0', '0x558d62afb9d0']
        group: 1
        visible: 1
        level: 1
        name: '000|o'
        color: 'weechat.color.nicklist_group'
        prefix: None
        prefix_color: None
    item 3:
        __path: ['0x558d62a9cea0', '0x558d62aff930']
        group: 0
        visible: 1
        level: 0
        name: 'FlashCode'
        color: 'weechat.color.chat_nick_self'
        prefix: '@'
        prefix_color: 'lightgreen'
    item 4:
        __path: ['0x558d62a9cea0', '0x558d62af9930']
        group: 1
        visible: 1
        level: 1
        name: '001|v'
        color: 'weechat.color.nicklist_group'
        prefix: None
        prefix_color: None
    item 5:
        __path: ['0x558d62a9cea0', '0x558d62afc510']
        group: 1
        visible: 1
        level: 1
        name: '999|...'
        color: 'weechat.color.nicklist_group'
        prefix: None
        prefix_color: None
    item 6:
        __path: ['0x558d62a9cea0', '0x558d6292c290']
        group: 0
        visible: 1
        level: 0
        name: 'flashy'
        color: '142'
        prefix: ' '
        prefix_color: 'lightblue'

3.7. input

Send data to a buffer.

Syntax:

(id) input <buffer> <data>

Arguments:

  • buffer: pointer (eg: "0x1234abcd") or full name of buffer (for example: core.weechat or irc.libera.#weechat)

  • data: data to send to buffer: if beginning by /, this will be executed as a command on buffer, otherwise text is sent as input of buffer

Examples:

  • Send command "/help filter" on WeeChat core buffer:

input core.weechat /help filter
  • Send message "hello!" to #weechat channel:

input irc.libera.#weechat hello!
  • Send multiline message to #test channel (option escape_commands must have been enabled in handshake command and requires WeeChat ≥ 4.0.0):

input irc.ergo.#test this message has\n2 lines

3.8. completion

WeeChat ≥ 2.9.

Request completion of a string: list of possible words at a given position in a string for a given buffer.

Syntax:

(id) completion <buffer> <position> [<data>]

Arguments:

  • buffer: pointer (eg: "0x1234abcd") or full name of buffer (for example: core.weechat or irc.libera.#weechat)

  • position: position for completion in string (starts to 0); if the value is -1, the position is the length of data (so the completion is made at the end of data)

  • data: the input string; if not given, completion is performed on an empty string

WeeChat replies with a hdata:

Name Type Description

context

string

Completion context: "null" (no completion), "command", "command_arg", "auto".

base_word

string

The base word used for completion.

pos_start

integer

Index of first char to replace (starts to 0).

pos_end

integer

Index of last char to replace (starts to 0).

add_space

integer

1 if a space must be added after words, 0 otherwise.

list

array of strings

List of words found; empty if nothing was found to complete at asked position.

In case of error, for example invalid buffer or internal error on WeeChat side, an empty hdata is returned.

Examples:

  • Completion of a command argument:

(completion_help) completion core.weechat -1 /help fi

Response:

id: 'completion_help'
hda:
    keys: {
        'context': 'str',
        'base_word': 'str',
        'pos_start': 'int',
        'pos_end': 'int',
        'add_space': 'int',
        'list': 'arr',
    }
    path: ['completion']
    item 1:
      __path: ['0x55d0ccc842c0']
      context: 'command_arg'
      base_word: 'fi'
      pos_start: 6
      pos_end: 7
      add_space: 0
      list: [
          'fifo',
          'fifo.file.enabled',
          'fifo.file.path',
          'filter',
      ]
  • Completion of a command in the middle of a word:

(completion_query) completion core.weechat 5 /quernick

Response:

id: 'completion_query'
hda:
    keys: {
        'context': 'str',
        'base_word': 'str',
        'pos_start': 'int',
        'pos_end': 'int',
        'add_space': 'int',
        'list': 'arr',
    }
    path: ['completion']
    item 1:
        __path: ['0x55d0ccc88470']
        context: 'command'
        base_word: 'quer'
        pos_start: 1
        pos_end: 4
        add_space: 1
        list: ['query']
  • Nothing to complete:

(completion_abcdefghijkl) completion core.weechat -1 abcdefghijkl

Response:

id: 'completion_abcdefghijkl'
hda:
    keys: {
        'context': 'str',
        'base_word': 'str',
        'pos_start': 'int',
        'pos_end': 'int',
        'add_space': 'int',
        'list': 'arr',
    }
    path: ['completion']
    item 1:
        __path: ['0x55d0ccc88470']
        context: 'auto'
        base_word: 'abcdefghijkl'
        pos_start: 0
        pos_end: 11
        add_space: 1
        list: []
  • Completion on an invalid buffer:

(completion_help) completion buffer.does.not.exist -1 /help fi

Response:

id: 'completion_help'
hda:
    keys: {}
    path: ['completion']

3.9. sync

Updated in version 0.4.1.

Synchronize one or more buffers, to get updates.

It is recommended to send this command immediately after you asked data for buffers (lines, …​). It can be send in same message (after a new line char: "\n").

Syntax:

(id) sync [<buffer>[,<buffer>...] <option>[,<option>...]]

Arguments:

  • buffer: pointer (eg: "0x1234abcd") or full name of buffer (for example: core.weechat or irc.libera.#weechat); name "*" can be used to specify all buffers

  • options: one of following keywords, separated by commas (default is buffers,upgrade,buffer,nicklist for "*" and buffer,nicklist for a buffer):

    • buffers: receive signals about buffers (opened/closed, moved, renamed, merged/unmerged, hidden/unhidden); this can be used only with name "*" (WeeChat ≥ 0.4.1)

    • upgrade: receive signals about WeeChat upgrade (upgrade, upgrade ended); this can be used only with name "*" (WeeChat ≥ 0.4.1)

    • buffer: receive signals about buffer (new lines, type changed, title changed, local variable added/removed, and same signals as buffers for the buffer) (updated in version 0.4.1)

    • nicklist: receive nicklist after changes

Examples:

  • Synchronize all buffers with nicklist (the 3 commands are equivalent, but the first one is recommended for compatibility with future versions):

sync
sync *
sync * buffers,upgrade,buffer,nicklist
  • Synchronize WeeChat core buffer:

sync core.buffer
  • Synchronize #weechat channel, without nicklist:

sync irc.libera.#weechat buffer
  • Get general signals + all signals for #weechat channel:

sync * buffers,upgrade
sync irc.libera.#weechat

3.10. desync

Updated in version 0.4.1.

Desynchronize one or more buffers, to stop updates.

This will remove options for buffers. If some options are still active for buffers, the client will still receive updates for these buffers.

Syntax:

(id) desync [<buffer>[,<buffer>...] <option>[,<option>...]]

Arguments:

  • buffer: pointer (eg: "0x1234abcd") or full name of buffer (for example: core.weechat or irc.libera.#weechat); name "*" can be used to specify all buffers

  • options: one of following keywords, separated by commas (default is buffers,upgrade,buffer,nicklist for "*" and buffer,nicklist for a buffer); see sync command for values

When using buffer "*", the other buffers synchronized (using a name) are kept.
So if you send: "sync *", then "sync irc.libera.#weechat", then "desync *", the updates on #weechat channel will still be sent by WeeChat (you must remove it explicitly to stop updates).

Examples:

  • Desynchronize all buffers (the 3 commands are equivalent, but the first one is recommended for compatibility with future versions):

desync
desync *
desync * buffers,upgrade,buffer,nicklist
  • Desynchronize nicklist for #weechat channel (keep buffer updates):

desync irc.libera.#weechat nicklist
  • Desynchronize #weechat channel:

desync irc.libera.#weechat

3.11. test

Test command: WeeChat will reply with various different objects.

This command is useful to test the decoding of binary objects returned by WeeChat.

Syntax:

(id) test

Returned objects (in this order):

Type Description Value

chr

char

65 ("A")

int

integer

123456

int

integer

-123456

lon

long

1234567890

lon

long

-1234567890

str

string

"a string"

str

string

""

str

string

NULL

buf

buffer

"buffer"

buf

buffer

NULL

ptr

pointer

0x1234abcd

ptr

pointer

NULL

tim

time

1321993456

arr str

array of strings

[ "abc", "de" ]

arr int

array of integers

[ 123, 456, 789 ]

You must not use the pointer values returned by this command, they are not valid. This command must be used only to test decoding of a message sent by WeeChat.

Example:

(test) test

Response:

id: 'test'
chr: 65
int: 123456
int: -123456
lon: 1234567890
lon: -1234567890
str: 'a string'
str: ''
str: None
buf: 'buffer'
buf: None
ptr: '0x1234abcd'
ptr: '0x0'
tim: 1321993456
arr: ['abc', 'de']
arr: [123, 456, 789]

3.12. ping

WeeChat ≥ 0.4.2.

Send a ping to WeeChat which will reply with a message "_pong" and same arguments.

This command is useful to test that connection with WeeChat is still alive and measure the response time.

Syntax:

(id) ping [<arguments>]

Example:

ping 1370802127000

Response:

id:'_pong'
str: '1370802127000'

3.13. quit

Disconnect from relay.

Syntax:

(id) quit

Example:

quit

4. Messages (relay → client)

Messages are sent as binary data, using following format (with size in bytes):

┌────────╥─────────────╥─────────╥────────┬──────────╥───────╥────────┬──────────┐
│ length ║ compression ║   id    ║ type 1 │ object 1 ║  ...  ║ type N │ object N │
└────────╨─────────────╨─────────╨────────┴──────────╨───────╨────────┴──────────┘
 └──────┘ └───────────┘ └───────┘ └──────┘ └────────┘         └──────┘ └────────┘
     4          1        4 + str      3        ??                 3        ??
 └────────────────────┘ └───────────────────────────────────────────────────────┘
       header (5)                          compressed data (??)
 └──────────────────────────────────────────────────────────────────────────────┘
                               'length' bytes
  • length (unsigned integer, 4 bytes): number of bytes of whole message (including this field)

  • compression (byte): flag:

    • 0x00: following data is not compressed

    • 0x01: following data is compressed with zlib 

    • 0x02: following data is compressed with Zstandard 

  • id (string, 4 bytes + content): identifier sent by client (before command name); it can be empty (string with zero length and no content) if no identifier was given in command

  • type (3 chars): a type: 3 letters (see table below)

  • object: an object (see table below)

4.1. Compression

If flag compression is equal to 0x01 or 0x02, then all data after is compressed with zlib  or Zstandard , and therefore must be uncompressed before being processed.

4.2. Identifier

There are two types of identifiers (id):

  • id sent by client: relay will answer with same id in its answer

  • id of an event: on some events, relay will send message to client using a specific id, beginning with underscore (see table below)

WeeChat reserved identifiers:

Identifier Received with sync Data sent Description Recommended action in client

_buffer_opened

buffers / buffer

hdata: buffer

Buffer opened.

Open buffer.

_buffer_type_changed

buffers / buffer

hdata: buffer

Type of buffer changed.

Change type of buffer.

_buffer_moved

buffers / buffer

hdata: buffer

Buffer moved.

Move buffer.

_buffer_merged

buffers / buffer

hdata: buffer

Buffer merged.

Merge buffer.

_buffer_unmerged

buffers / buffer

hdata: buffer

Buffer unmerged.

Unmerge buffer.

_buffer_hidden

buffers / buffer

hdata: buffer

Buffer hidden.

Hide buffer.

_buffer_unhidden

buffers / buffer

hdata: buffer

Buffer unhidden.

Unhide buffer.

_buffer_renamed

buffers / buffer

hdata: buffer

Buffer renamed.

Rename buffer.

_buffer_title_changed

buffers / buffer

hdata: buffer

Title of buffer changed.

Change title of buffer.

_buffer_localvar_added

buffers / buffer

hdata: buffer

Local variable added.

Add local variable in buffer.

_buffer_localvar_changed

buffers / buffer

hdata: buffer

Local variable changed.

Change local variable in buffer.

_buffer_localvar_removed

buffers / buffer

hdata: buffer

Local variable removed.

Remove local variable from buffer.

_buffer_closing

buffers / buffer

hdata: buffer

Buffer closing.

Close buffer.

_buffer_cleared

buffer

hdata: buffer

Buffer cleared.

Clear buffer.

_buffer_line_added

buffer

hdata: line

Line added in buffer.

Display line in buffer.

_buffer_line_data_changed

buffer

hdata: line

Line changed in buffer.

Update line displayed in buffer.

_nicklist

nicklist

hdata: nicklist_item

Nicklist for a buffer.

Replace nicklist.

_nicklist_diff

nicklist

hdata: nicklist_item

Nicklist diffs for a buffer .

Update nicklist.

_pong

(always)

string: ping arguments

Answer to a "ping".

Measure response time.

_upgrade

upgrade

(empty)

WeeChat is upgrading.

Desync from WeeChat (or disconnect).

_upgrade_ended

upgrade

(empty)

Upgrade of WeeChat done.

Sync/resync with WeeChat.

_buffer_opened

This message is sent to the client when the signal "buffer_opened" is sent by WeeChat.

Data sent as hdata:

Name Type Description

number

integer

Buffer number (≥ 1).

full_name

string

Full name (example: irc.libera.#weechat).

short_name

string

Short name (example: #weechat).

nicklist

integer

1 if buffer has a nicklist, otherwise 0.

title

string

Buffer title.

local_variables

hashtable

Local variables.

prev_buffer

pointer

Pointer to previous buffer.

next_buffer

pointer

Pointer to next buffer.

Example: channel #weechat joined on libera, new buffer irc.libera.#weechat:

id: '_buffer_opened'
hda:
    keys: {
        'number': 'int',
        'full_name': 'str',
        'short_name': 'str',
        'nicklist': 'int',
        'title': 'str',
        'local_variables': 'htb',
        'prev_buffer': 'ptr',
        'next_buffer': 'ptr',
    }
    path: ['buffer']
    item 1:
        __path: ['0x35a8a60']
        number: 3
        full_name: 'irc.libera.#weechat'
        short_name: None
        nicklist: 0
        title: None
        local_variables: {
            'plugin': 'irc',
            'name': 'libera.#weechat',
        }
        prev_buffer: '0x34e7400'
        next_buffer: '0x0'

_buffer_moved

This message is sent to the client when the signal "buffer_moved" is sent by WeeChat.

Data sent as hdata:

Name Type Description

number

integer

Buffer number (≥ 1).

full_name

string

Full name (example: irc.libera.#weechat).

prev_buffer

pointer

Pointer to previous buffer.

next_buffer

pointer

Pointer to next buffer.

Example: buffer irc.libera.#weechat moved to number 2:

id: '_buffer_moved'
hda:
    keys: {
        'number': 'int',
        'full_name': 'str',
        'prev_buffer': 'ptr',
        'next_buffer': 'ptr',
    }
    path: ['buffer']
    item 1:
        __path: ['0x34588c0']
        number: 2
        full_name: 'irc.libera.#weechat'
        prev_buffer: '0x347b9f0'
        next_buffer: '0x3471bc0'

_buffer_merged

This message is sent to the client when the signal "buffer_merged" is sent by WeeChat.

Data sent as hdata:

Name Type Description

number

integer

Buffer number (≥ 1).

full_name

string

Full name (example: irc.libera.#weechat).

prev_buffer

pointer

Pointer to previous buffer.

next_buffer

pointer

Pointer to next buffer.

Example: buffer irc.libera.#weechat merged with buffer #2:

id: '_buffer_merged'
hda:
    keys: {
        'number': 'int',
        'full_name': 'str',
        'prev_buffer': 'ptr',
        'next_buffer': 'ptr',
    }
    path: ['buffer']
    item 1:
        __path: ['0x4db4c00']
        number: 2
        full_name: 'irc.libera.#weechat'
        prev_buffer: '0x4cef9b0'
        next_buffer: '0x0'

_buffer_unmerged

This message is sent to the client when the signal "buffer_unmerged" is sent by WeeChat.

Data sent as hdata:

Name Type Description

number

integer

Buffer number (≥ 1).

full_name

string

Full name (example: irc.libera.#weechat).

prev_buffer

pointer

Pointer to previous buffer.

next_buffer

pointer

Pointer to next buffer.

Example: buffer irc.libera.#weechat unmerged:

id: '_buffer_unmerged'
hda:
    keys: {
        'number': 'int',
        'full_name': 'str',
        'prev_buffer': 'ptr',
        'next_buffer': 'ptr',
    }
    path: ['buffer']
    item 1:
        __path: ['0x4db4c00']
        number: 3
        full_name: 'irc.libera.#weechat'
        prev_buffer: '0x4cef9b0'
        next_buffer: '0x0'

_buffer_hidden

WeeChat ≥ 1.0.

This message is sent to the client when the signal "buffer_hidden" is sent by WeeChat.

Data sent as hdata:

Name Type Description

number

integer

Buffer number (≥ 1).

full_name

string

Full name (example: irc.libera.#weechat).

prev_buffer

pointer

Pointer to previous buffer.

next_buffer

pointer

Pointer to next buffer.

Example: buffer irc.libera.#weechat hidden:

id: '_buffer_hidden'
hda:
    keys: {
        'number': 'int',
        'full_name': 'str',
        'prev_buffer': 'ptr',
        'next_buffer': 'ptr',
    }
    path: ['buffer']
    item 1:
        __path: ['0x4db4c00']
        number: 2
        full_name: 'irc.libera.#weechat'
        prev_buffer: '0x4cef9b0'
        next_buffer: '0x0'

_buffer_unhidden

WeeChat ≥ 1.0.

This message is sent to the client when the signal "buffer_unhidden" is sent by WeeChat.

Data sent as hdata:

Name Type Description

number

integer

Buffer number (≥ 1).

full_name

string

Full name (example: irc.libera.#weechat).

prev_buffer

pointer

Pointer to previous buffer.

next_buffer

pointer

Pointer to next buffer.

Example: buffer irc.libera.#weechat unhidden:

id: '_buffer_unhidden'
hda:
    keys: {
        'number': 'int',
        'full_name': 'str',
        'prev_buffer': 'ptr',
        'next_buffer': 'ptr',
    }
    path: ['buffer']
    item 1:
        __path: ['0x4db4c00']
        number: 3
        full_name: 'irc.libera.#weechat'
        prev_buffer: '0x4cef9b0'
        next_buffer: '0x0'

_buffer_renamed

This message is sent to the client when the signal "buffer_renamed" is sent by WeeChat.

Data sent as hdata:

Name Type Description

number

integer

Buffer number (≥ 1).

full_name

string

Full name (example: irc.libera.#weechat).

short_name

string

Short name (example: #weechat).

local_variables

hashtable

Local variables.

Example: private buffer renamed from FlashCode to Flash2:

id: '_buffer_renamed'
hda:
    keys: {
        'number': 'int',
        'full_name': 'str',
        'short_name': 'str',
        'local_variables': 'htb',
    }
    path: ['buffer']
    item 1:
        __path: ['0x4df7b80']
        number: 5
        full_name: 'irc.libera.Flash2'
        short_name: 'Flash2'
        local_variables: {
            'server': 'libera',
            'plugin': 'irc',
            'type': 'private',
            'channel': 'FlashCode',
            'nick': 'test',
            'name': 'libera.Flash2',
        }

_buffer_title_changed

This message is sent to the client when the signal "buffer_title_changed" is sent by WeeChat.

Data sent as hdata:

Name Type Description

number

integer

Buffer number (≥ 1).

full_name

string

Full name (example: irc.libera.#weechat).

title

string

Buffer title.

Example: topic changed on channel #weechat:

id: '_buffer_title_changed'
hda:
    keys: {
        'number': 'int',
        'full_name': 'str',
        'title': 'str',
    }
    path: ['buffer']
    item 1:
        __path: ['0x4a715d0']
        number: 3
        full_name: 'irc.libera.#weechat'
        title: 'Welcome on #weechat!  https://weechat.org/'

_buffer_cleared

WeeChat ≥ 1.0.

This message is sent to the client when the signal "buffer_cleared" is sent by WeeChat.

Data sent as hdata:

Name Type Description

number

integer

Buffer number (≥ 1).

full_name

string

Full name (example: irc.libera.#weechat).

Example: buffer irc.libera.#weechat has been cleared:

id: '_buffer_cleared'
hda:
    keys: {
        'number': 'int',
        'full_name': 'str',
    }
    path: ['buffer']
    item 1:
        __path: ['0x4a715d0']
        number: 3
        full_name: 'irc.libera.#weechat'

_buffer_type_changed

This message is sent to the client when the signal "buffer_type_changed" is sent by WeeChat.

Data sent as hdata:

Name Type Description

number

integer

Buffer number (≥ 1).

full_name

string

Full name (example: irc.libera.#weechat).

type

integer

Buffer type: 0 = formatted (default), 1 = free content.

Example: type of buffer script.scripts changed from formatted (0) to free content (1):

id: '_buffer_type_changed'
hda:
    keys: {
        'number': 'int',
        'full_name': 'str',
        'type': 'int',
    }
    path: ['buffer']
    item 1:
        __path: ['0x27c9a70']
        number: 4
        full_name: 'script.scripts'
        type: 1

_buffer_localvar_added

This message is sent to the client when the signal "buffer_localvar_added" is sent by WeeChat.

Data sent as hdata:

Name Type Description

number

integer

Buffer number (≥ 1).

full_name

string

Full name (example: irc.libera.#weechat).

local_variables

hashtable

Local variables.

Example: local variable test added in buffer irc.libera.#weechat:

id='_buffer_localvar_added', objects:
hda:
    keys: {
        'number': 'int',
        'full_name': 'str',
        'local_variables': 'htb',
    }
    path: ['buffer']
    item 1:
        __path: ['0x4a73de0']
        number: 3
        full_name: 'irc.libera.#weechat'
        local_variables: {
            'server': 'libera',
            'test': 'value',
            'plugin': 'irc',
            'type': 'channel',
            'channel': '#weechat',
            'nick': 'test',
            'name': 'libera.#weechat',
        }

_buffer_localvar_changed

This message is sent to the client when the signal "buffer_localvar_changed" is sent by WeeChat.

Data sent as hdata:

Name Type Description

number

integer

Buffer number (≥ 1).

full_name

string

Full name (example: irc.libera.#weechat).

local_variables

hashtable

Local variables.

Example: local variable test updated in buffer irc.libera.#weechat:

id='_buffer_localvar_changed', objects:
hda:
    keys: {
        'number': 'int',
        'full_name': 'str',
        'local_variables': 'htb',
    }
    path: ['buffer']
    item 1:
        __path: ['0x4a73de0']
        number: 3
        full_name: 'irc.libera.#weechat'
        local_variables: {
            'server': 'local',
            'test': 'value2',
            'plugin': 'irc',
            'type': 'channel',
            'channel': '#weechat',
            'nick': 'test',
            'name': 'libera.#weechat',
        }

_buffer_localvar_removed

This message is sent to the client when the signal "buffer_localvar_removed" is sent by WeeChat.

Data sent as hdata:

Name Type Description

number

integer

Buffer number (≥ 1).

full_name

string

Full name (example: irc.libera.#weechat).

local_variables

hashtable

Local variables.

Example: local variable test removed from buffer irc.libera.#weechat:

id: '_buffer_localvar_removed'
hda:
    keys: {
        'number': 'int',
        'full_name': 'str',
        'local_variables': 'htb',
    }
    path: ['buffer']
    item 1:
        __path: ['0x4a73de0']
        number: 3
        full_name: 'irc.libera.#prout'
        local_variables: {
            'server': 'local',
            'plugin': 'irc',
            'type': 'channel',
            'channel': '#weechat',
            'nick': 'test',
            'name': 'libera.#weechat',
        }

_buffer_line_added

This message is sent to the client when the signal "buffer_line_added" is sent by WeeChat.

Data sent as hdata:

Name Type Description

buffer

pointer

Buffer pointer.

id

integer

Line identifier.

date

time

Date of message.

date_usec

integer

Microseconds of date.

date_printed

time

Date when WeeChat displayed message.

date_usec_printed

integer

Microseconds of date when WeeChat displayed message.

displayed

char

1 if message is displayed, 0 if message is filtered (hidden).

notify_level

char

Notify level: -1 = notify disabled, 0 = low, 1 = message, 2 = private, 3 = highlight.

highlight

char

1 if line has a highlight, otherwise 0.

tags_array

array of strings

List of tags for line.

prefix

string

Prefix.

message

string

Message.

Example: new message hello! from nick FlashCode on buffer irc.libera.#weechat:

id: '_buffer_line_added'
hda:
    keys: {
        'buffer': 'ptr',
        'id': 'int',
        'date': 'tim',
        'date_usec': 'int',
        'date_printed': 'tim',
        'date_usec_printed': 'int',
        'displayed': 'chr',
        'notify_level': 'chr',
        'highlight': 'chr',
        'tags_array': 'arr',
        'prefix': 'str',
        'message': 'str',
    }
    path: ['line_data']
    item 1:
        __path: ['0x4a49600']
        buffer: '0x4a715d0'
        id: 12
        date: 1362728993
        date_usec: 902765
        date_printed: 1362728993
        date_usec_printed: 902765
        displayed: 1
        notify_level: 1
        highlight: 0
        tags_array: [
            'irc_privmsg',
            'notify_message',
            'prefix_nick_142',
            'nick_FlashCode',
            'log1',
        ]
        prefix: 'F06@F@00142FlashCode'
        message: 'hello!'

_buffer_line_data_changed

This message is sent to the client when the signal "buffer_line_data_changed" is sent by WeeChat.

Data sent as hdata: same data as _buffer_line_added.

Example: message hello! from nick FlashCode on buffer irc.libera.#weechat has been updated:

id: '_buffer_line_data_changed'
hda:
    keys: {
        'buffer': 'ptr',
        'id': 'int',
        'date': 'tim',
        'date_usec': 'int',
        'date_printed': 'tim',
        'date_usec_printed': 'int',
        'displayed': 'chr',
        'notify_level': 'chr',
        'highlight': 'chr',
        'tags_array': 'arr',
        'prefix': 'str',
        'message': 'str',
    }
    path: ['line_data']
    item 1:
        __path: ['0x4a49600']
        buffer: '0x4a715d0'
        id: 12
        date: 1362728993
        date_usec: 902765
        date_printed: 1362728993
        date_usec_printed: 902765
        displayed: 1
        notify_level: 1
        highlight: 0
        tags_array: [
            'irc_privmsg',
            'notify_message',
            'prefix_nick_142',
            'nick_FlashCode',
            'log1',
        ]
        prefix: 'F06@F@00142FlashCode'
        message: 'hello!'

_buffer_closing

This message is sent to the client when the signal "buffer_closing" is sent by WeeChat.

Data sent as hdata:

Name Type Description

number

integer

Buffer number (≥ 1).

full_name

string

Full name (example: irc.libera.#weechat).

Example: buffer irc.libera.#weechat is being closed by WeeChat:

id: '_buffer_closing'
hda:
    keys: {
        'number': 'int',
        'full_name': 'str',
    }
    path: ['buffer']
    item 1:
        __path: ['0x4a715d0']
        number: 3
        full_name: 'irc.libera.#weechat'

_nicklist

This message is sent to the client when large updates are made on a nicklist (groups/nicks added/removed/changed). The message contains full nicklist.

When small updates are made on a nicklist (for example just add one nick), another message with identifier _nicklist_diff is sent (see below).

Data sent as hdata:

Name Type Description

group

char

1 for a group, 0 for a nick.

visible

char

1 if group/nick is displayed, otherwise 0.

level

integer

Level of group (0 for a nick).

name

string

Name of group/nick.

color

string

Name color.

prefix

string

Prefix (only for a nick).

prefix_color

string

Prefix color (only for a nick).

Example: nicklist for buffer irc.libera.#weechat:

id: '_nicklist'
hda:
    keys: {
        'group': 'chr',
        'visible': 'chr',
        'level': 'int',
        'name': 'str',
        'color': 'str',
        'prefix': 'str',
        'prefix_color': 'str',
    }
    path: ['buffer', 'nicklist_item']
    item 1:
        __path: ['0x4a75cd0', '0x31e95d0']
        group: 1
        visible: 0
        level: 0
        name: 'root'
        color: None
        prefix: None
        prefix_color: None
    item 2:
        __path: ['0x4a75cd0', '0x41247b0']
        group: 1
        visible: 1
        level: 1
        name: '000|o'
        color: 'weechat.color.nicklist_group'
        prefix: None
        prefix_color: None
    item 3:
        __path: ['0x4a75cd0', '0x4a60d20']
        group: 0
        visible: 1
        level: 0
        name: 'FlashCode'
        color: '142'
        prefix: '@'
        prefix_color: 'lightgreen'
    item 4:
        __path: ['0x4a75cd0', '0x4aafaf0']
        group: 1
        visible: 1
        level: 1
        name: '001|v'
        color: 'weechat.color.nicklist_group'
        prefix: None
        prefix_color: None
    item 5:
        __path: ['0x4a75cd0', '0x4a48d80']
        group: 1
        visible: 1
        level: 1
        name: '999|...'
        color: 'weechat.color.nicklist_group'
        prefix: None
        prefix_color: None
    item 6:
        __path: ['0x4a75cd0', '0x4a5f560']
        group: 0
        visible: 1
        level: 0
        name: 'test'
        color: 'weechat.color.chat_nick_self'
        prefix: ' '
        prefix_color: ''

_nicklist_diff

WeeChat ≥ 0.4.1.

This message is sent to the client when small updates are made on a nicklist (groups/nicks added/removed/changed). The message contains nicklist differences (between old nicklist and current one).

Data sent as hdata:

Name Type Description

_diff

char

Type of diff (see below).

group

char

1 for a group, 0 for a nick.

visible

char

1 if group/nick is displayed, otherwise 0.

level

integer

Level of group (0 for a nick).

name

string

Name of group/nick.

color

string

Name color.

prefix

string

Prefix (only for a nick).

prefix_color

string

Prefix color (only for a nick).

The value of _diff can be:

  • ^: the parent group: group(s) or nick(s) after this one are related to this group

  • +: group/nick added in the parent group

  • -: group/nick removed from the parent group

  • *: group/nick updated in the parent group

Example: nick master added in group 000|o (channel ops on an IRC channel), nicks nick1 and nick2 added in group 999|…​ (standard users on an IRC channel):

id: '_nicklist_diff'
hda:
    keys: {
        '_diff': 'chr',
        'group': 'chr',
        'visible': 'chr',
        'level': 'int',
        'name': 'str',
        'color': 'str',
        'prefix': 'str',
        'prefix_color': 'str',
    }
    path: ['buffer', 'nicklist_item']
    item 1:
        __path: ['0x46f2ee0', '0x343c9b0']
        _diff: 94 ('^')
        group: 1
        visible: 1
        level: 1
        name: '000|o'
        color: 'weechat.color.nicklist_group'
        prefix: None
        prefix_color: None
    item 2:
        __path: ['0x46f2ee0', '0x47e7f60']
        _diff: 43 ('+')
        group: 0
        visible: 1
        level: 0
        name: 'master'
        color: 'magenta'
        prefix: '@'
        prefix_color: 'lightgreen'
    item 3:
        __path: ['0x46f2ee0', '0x46b8e70']
        _diff: 94 ('^')
        group: 1
        visible: 1
        level: 1
        name: '999|...'
        color: 'weechat.color.nicklist_group'
        prefix: None
        prefix_color: None
    item 4:
        __path: ['0x46f2ee0', '0x3dba240']
        _diff: 43 ('+')
        group: 0
        visible: 1
        level: 0
        name: 'nick1'
        color: 'green'
        prefix: ' '
        prefix_color: ''
    item 5:
        __path: ['0x46f2ee0', '0x3c379d0']
        _diff: 43 ('+')
        group: 0
        visible: 1
        level: 0
        name: 'nick2'
        color: 'lightblue'
        prefix: ' '
        prefix_color: ''

_pong

WeeChat ≥ 0.4.2.

This message is sent to the client when relay receives a "ping" message.

Data sent as string: arguments received in the "ping" message.

The recommended action in client is to measure the response time and disconnect if it is high.

_upgrade

WeeChat ≥ 0.3.8.

This message is sent to the client when WeeChat is starting upgrade process.

There is no data in the message.

The recommended action in client is to desynchronize from WeeChat (send command desync), or to disconnect from WeeChat (because after upgrade, all pointers will change).

During WeeChat upgrade, the socket remains opened (except if connection uses TLS).

_upgrade_ended

WeeChat ≥ 0.3.8.

This message is sent to the client when WeeChat has finished the upgrade process.

There is no data in the message.

The recommended action in client is to resynchronize with WeeChat: resend all commands sent on startup after the init.

4.3. Objects

Objects are identified by 3 letters, called type. Following types are used:

Type Value Length

chr

Signed char

1 byte

int

Signed integer

4 bytes

lon

Signed long integer

1 byte + length of integer as string

str

String

4 bytes + length of string (without final \0)

buf

Buffer of bytes

4 bytes + length of data

ptr

Pointer

1 byte + length of pointer as string

tim

Time

1 byte + length of time as string

htb

Hashtable

Variable

hda

Hdata content

Variable

inf

Info: name + content

Variable

inl

Infolist content

Variable

arr

Array of objects

3 bytes (type) + number of objects + data

Char

A signed char is stored as 1 byte.

Example:

┌────┐
│ 41 │ ────► 65 (0x41: "A")
└────┘

Integer

A signed integer is stored as 4 bytes, encoded as big-endian format (most significant byte first).

Range: -2147483648 to 2147483647.

Examples:

┌────┬────┬────┬────┐
│ 00 │ 01 │ E2 │ 40 │ ────► 123456
└────┴────┴────┴────┘

┌────┬────┬────┬────┐
│ FF │ FE │ 1D │ C0 │ ────► -123456
└────┴────┴────┴────┘

Long integer

A signed long integer is encoded as a string, with length on one byte.

Range: -9223372036854775808 to 9223372036854775807.

Examples:

┌────╥────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐
│ 0A ║ 31 │ 32 │ 33 │ 34 │ 35 │ 36 │ 37 │ 38 │ 39 │ 30 │ ────► 1234567890
└────╨────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘
 └──┘ └───────────────────────────────────────────────┘
length '1'  '2'  '3'  '4'  '5'  '6'  '7'  '8'  '9'  '0'

┌────╥────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐
│ 0B ║ 2D │ 31 │ 32 │ 33 │ 34 │ 35 │ 36 │ 37 │ 38 │ 39 │ 30 │ ────► -1234567890
└────╨────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘
 └──┘ └────────────────────────────────────────────────────┘
length '-'  '1'  '2'  '3'  '4'  '5'  '6'  '7'  '8'  '9'  '0'

String

A string is a length (integer on 4 bytes) + content of string (without final \0).

Example:

┌────┬────┬────┬────╥────┬────┬────┬────┬────┐
│ 00 │ 00 │ 00 │ 05 ║ 68 │ 65 │ 6C │ 6C │ 6F │ ────► "hello"
└────┴────┴────┴────╨────┴────┴────┴────┴────┘
 └─────────────────┘ └──────────────────────┘
       length         'h'  'e'  'l'  'l'  'o'

An empty string has a length of zero:

┌────┬────┬────┬────┐
│ 00 │ 00 │ 00 │ 00 │ ────► ""
└────┴────┴────┴────┘
 └─────────────────┘
       length

A NULL string (NULL pointer in C) has a length of -1:

┌────┬────┬────┬────┐
│ FF │ FF │ FF │ FF │ ────► NULL
└────┴────┴────┴────┘
 └─────────────────┘
       length

Buffer

Same format as string; content is just an array of bytes.

Pointer

A pointer is encoded as string (hex), with length on one byte.

Example:

┌────╥────┬────┬────┬────┬────┬────┬────┬────┬────┐
│ 09 ║ 31 │ 61 │ 32 │ 62 │ 33 │ 63 │ 34 │ 64 │ 35 │ ────► 0x1a2b3c4d5
└────╨────┴────┴────┴────┴────┴────┴────┴────┴────┘
 └──┘ └──────────────────────────────────────────┘
length '1'  'a'  '2'  'b'  '3'  'c'  '4'  'd'  '5'

A NULL pointer has a length of 1 with value 0:

┌────╥────┐
│ 01 ║ 30 │ ────► NULL (0x0)
└────╨────┘
 └──┘ └──┘
length '0'

Time

A time (number of seconds) is encoded as a string, with length on one byte.

Example:

┌────╥────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐
│ 0A ║ 31 │ 33 │ 32 │ 31 │ 39 │ 39 │ 33 │ 34 │ 35 │ 36 │ ────► 1321993456
└────╨────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘
 └──┘ └───────────────────────────────────────────────┘
length '1'  '3'  '2'  '1'  '9'  '9'  '3'  '4'  '5'  '6'

Hashtable

A hashtable contains type for keys, type for values, number of items in hashtable (integer on 4 bytes), and then keys and values of items.

┌───────────┬─────────────┬───────╥───────┬─────────╥─────╥───────┬─────────┐
│ type_keys │ type_values │ count ║ key 1 │ value 1 ║ ... ║ key N │ value N │
└───────────┴─────────────┴───────╨───────┴─────────╨─────╨───────┴─────────┘

Example:

┌─────┬─────┬───╥──────┬─────╥──────┬─────┐
│ str │ str │ 2 ║ key1 │ abc ║ key2 │ def │ ────► { 'key1' => 'abc',
└─────┴─────┴───╨──────┴─────╨──────┴─────┘         'key2' => 'def' }
 └───┘ └───┘ └─┘ └──────────┘ └──────────┘
 type  type count   item 1       item 2
 keys values

Hdata

A hdata contains a path with hdata names, list of keys, number of set of objects, and then set of objects (path with pointers, then objects).

┌────────┬──────┬───────╥────────┬─────────────────────╥─────╥────────┬─────────────────────╥─────┐
│ h-path │ keys │ count ║ p-path │ value 1 ... value N ║ ... ║ p-path │ value 1 ... value N ║ ... │
└────────┴──────┴───────╨────────┴─────────────────────╨─────╨────────┴─────────────────────╨─────┘
  • h-path (string): path used to reach hdata (example: buffer/lines/line/line_data); the last element in path is the hdata returned

  • keys (string): string with list of key:type (separated by commas), example: number:int,name:str

  • count (integer): number of set of objects

  • p-path: path with pointers to objects (number of pointers here is number of elements in path)

  • values: list of values (number of values is number of keys returned for hdata)

Example of hdata with two buffers (weechat core and libera server) and two keys (number and full_name):

# command
hdata buffer:gui_buffers(*) number,full_name

# response
┌────────┬──────────────────────────┬───╥─────────┬───┬──────────────╥─────────┬───┬───────────────────┐
│ buffer │ number:int,full_name:str │ 2 ║ 0x12345 │ 1 │ core.weechat ║ 0x6789a │ 2 │ irc.server.libera │
└────────┴──────────────────────────┴───╨─────────┴───┴──────────────╨─────────┴───┴───────────────────┘
 └──────┘ └────────────────────────┘ └─┘ └──────────────────────────┘ └───────────────────────────────┘
  h-path          keys              count          buffer 1                        buffer 2

Example of hdata with lines of core buffer:

# command
hdata buffer:gui_buffers(*)/lines/first_line(*)/data

# response
┌─────────────────────────────┬─────┬────╥──
│ buffer/lines/line/line_data │ ... │ 50 ║ ...
└─────────────────────────────┴─────┴────╨──
 └───────────────────────────┘ └───┘ └──┘
      h-path (hdata names)     keys  count

   ──╥───────────┬───────────┬───────────┬───────────┬───────╥──
 ... ║ 0x23cf970 │ 0x23cfb60 │ 0x23d5f40 │ 0x23d8a10 │ ..... ║ ...
   ──╨───────────┴───────────┴───────────┴───────────┴───────╨──
      └─────────────────────────────────────────────┘ └─────┘
                    p-path (pointers)                 objects
      └─────────────────────────────────────────────────────┘
                              line 1

   ──╥───────────┬───────────┬───────────┬───────────┬───────╥──────────────┐
 ... ║ 0x23cf970 │ 0x23cfb60 │ 0x23d6110 │ 0x23d9420 │ ..... ║ ............ │
   ──╨───────────┴───────────┴───────────┴───────────┴───────╨──────────────┘
      └─────────────────────────────────────────────┘ └─────┘
                    p-path (pointers)                 objects
      └─────────────────────────────────────────────────────┘ └────────────┘
                         line 2                                 lines 3-50

Example of hdata with nicklist:

# command
nicklist

# response
┌───────────────────┬──
│ buffer/nick_group │ ...
└───────────────────┴──
 └─────────────────┘
        h-path

   ──╥───────────────────────────────────────────────────────────┬────╥──
 ... ║ group:chr,visible:chr,name:str,color:str,prefix:str,(...) │ 12 ║ ...
   ──╨───────────────────────────────────────────────────────────┴────╨──
      └─────────────────────────────────────────────────────────┘ └──┘
                                 keys                             count

   ──╥─────────┬─────────┬───┬───┬──────┬─┬─┬─┬───╥──
 ... ║ 0x12345 │ 0x6789a │ 1 │ 0 │ root │ │ │ │ 0 ║ ...
   ──╨─────────┴─────────┴───┴───┴──────┴─┴─┴─┴───╨──
      └─────────────────┘ └──────────────────────┘
             p-path               objects
      └──────────────────────────────────────────┘
                  group (nicklist root)

   ──╥─────────┬─────────┬───┬───┬───────┬─┬─┬─┬───╥──
 ... ║ 0x123cf │ 0x678d4 │ 1 │ 0 │ 000|o │ │ │ │ 1 ║ ...
   ──╨─────────┴─────────┴───┴───┴───────┴─┴─┴─┴───╨──
      └─────────────────┘ └───────────────────────┘
             p-path                objects
      └───────────────────────────────────────────┘
                    group (channel ops)

   ──╥─────────┬─────────┬───┬───┬──────────┬──────┬───┬────────────┬───╥──
 ... ║ 0x128a7 │ 0x67ab2 │ 0 │ 1 │ ChanServ │ blue │ @ │ lightgreen │ 0 ║ ...
   ──╨─────────┴─────────┴───┴───┴──────────┴──────┴───┴────────────┴───╨──
      └─────────────────┘ └────────────────────────────────────────────┘
             p-path                          objects
      └────────────────────────────────────────────────────────────────┘
                               nick (@ChanServ)

Example of empty hdata (hotlist is empty in WeeChat):

# command
hdata hotlist:gui_hotlist(*)

# response
┌────────┬────────┬───┐
│ (NULL) │ (NULL) │ 0 │
└────────┴────────┴───┘
 └──────┘ └──────┘ └─┘
  h-path    keys  count

Info

A info contains a name and a value (both are strings).

┌──────┬───────┐
│ name │ value │
└──────┴───────┘
  • name (string): name of info

  • value (string): value

Example of info version:

┌─────────┬───────────────────┐
│ version │ WeeChat 0.3.7-dev │
└─────────┴───────────────────┘

Infolist

A infolist contains a name, number of items, and then items (set of variables).

┌──────┬───────╥────────╥─────╥────────┐
│ name │ count ║ item 1 ║ ... ║ item N │
└──────┴───────╨────────╨─────╨────────┘

An item is:

┌───────╥────────┬────────┬─────────╥─────╥────────┬────────┬─────────┐
│ count ║ name 1 │ type 1 │ value 1 ║ ... ║ name N │ type N │ value N │
└───────╨────────┴────────┴─────────╨─────╨────────┴────────┴─────────┘
  • name (string): name of infolist (buffer, window, bar, …​)

  • count (integer): number of items

  • item:

    • count: number of variables in item

    • name: name of variable

    • type: type of variable (int, str, …​)

    • value: value of variable

Example of infolist with two buffers (weechat core and libera server):

# command
infolist buffer

# response
┌────────┬───╥────┬─────────┬─────┬─────────┬─────╥────┬─────────┬─────┬─────────┬─────┐
│ buffer │ 2 ║ 42 │ pointer │ ptr │ 0x12345 │ ... ║ 42 │ pointer │ ptr │ 0x6789a │ ... │
└────────┴───╨────┴─────────┴─────┴─────────┴─────╨────┴─────────┴─────┴─────────┴─────┘
 └──────┘ └─┘ └──────────────────────────────────┘ └──────────────────────────────────┘
   name  count              item 1                               item 2

Array

An array is a type (3 bytes) + number of objects (integer on 4 bytes) + data.

Example of array with two strings:

┌─────╥────┬────┬────┬────╥────┬────┬────┬────╥────┬────┬────╥────┬────┬────┬────╥────┬────┐
│ str ║ 00 │ 00 │ 00 │ 02 ║ 00 │ 00 │ 00 │ 03 ║ 61 │ 62 │ 63 ║ 00 │ 00 │ 00 │ 02 ║ 64 │ 65 │ ────► [ "abc", "de" ]
└─────╨────┴────┴────┴────╨────┴────┴────┴────╨────┴────┴────╨────┴────┴────┴────╨────┴────┘
 └───┘ └─────────────────┘ └─────────────────┘ └────────────┘ └─────────────────┘ └───────┘
 type   number of strings        length         'a'  'b'  'c'       length         'd'  'e'

Example of array with three integers:

┌─────╥────┬────┬────┬────╥────┬────┬────┬────╥────┬────┬────┬────╥────┬────┬────┬────┐
│ int ║ 00 │ 00 │ 00 │ 03 ║ 00 │ 00 │ 00 │ 7B ║ 00 │ 00 │ 01 │ C8 ║ 00 │ 00 │ 03 │ 15 │ ────► [ 123, 456, 789 ]
└─────╨────┴────┴────┴────╨────┴────┴────┴────╨────┴────┴────┴────╨────┴────┴────┴────┘
 └───┘ └─────────────────┘ └─────────────────┘ └─────────────────┘ └─────────────────┘
 type   number of integers      123 (0x7B)         456 (0x1C8)         789 (0x315)

A NULL array:

┌─────╥────┬────┬────┬────┐
│ str ║ 00 │ 00 │ 00 │ 00 │ ────► NULL
└─────╨────┴────┴────┴────┘
 └───┘ └─────────────────┘
 type   number of strings

5. Typical session

    ┌────────┐                         ┌───────┐                ┌─────────┐
    │ Client ├ ─ ─ ─ ─(network)─ ─ ─ ─ ┤ Relay ├────────────────┤ WeeChat │
    └────────┘                         └───────┘                └─────────┘
         ║                                 ║                         ║
         ╟───────────────────────────────► ║                         ║
         ║ open socket                     ║ add client              ║
         ║                                 ║                         ║
         ╟───────────────────────────────► ║                         ║
         ║ cmd: handshake ...              ║ negotiate algos         ║
         ║                                 ║ and options             ║
         ║ ◄───────────────────────────────╢                         ║
         ║        msg: id: "handshake" ... ║                         ║
         ║                                 ║                         ║
         ╟───────────────────────────────► ║                         ║
         ║ cmd: init password=xxx,...      ║ authenticate client     ║
         ║                                 ║                         ║
         ╟───────────────────────────────► ║                         ║
         ║ cmd: hdata buffer ...           ╟───────────────────────► ║
         ║      sync ...                   ║ request hdata           ║ read hdata
         ║                                 ║                         ║ values
         ║                                 ║ ◄───────────────────────╢
         ║ ◄───────────────────────────────╢                   hdata ║
  create ║                 msg: hda buffer ║                         ║
 buffers ║                                 ║                         ║
         ║            ........             ║         ........        ║
         ║                                 ║                         ║
         ╟───────────────────────────────► ║                         ║
         ║ cmd: input ...                  ╟───────────────────────► ║
         ║                                 ║ send data to buffer     ║ send data
         ║                                 ║                         ║ to buffer
         ║            ........             ║         ........        ║
         ║                                 ║                         ║ signal
         ║                                 ║ ◄───────────────────────╢ received
         ║ ◄───────────────────────────────╢              signal XXX ║ (hooked by
 update  ║          msg: id: "_buffer_..." ║                         ║ relay)
 buffers ║                                 ║                         ║
         ║            ........             ║         ........        ║
         ║                                 ║                         ║
         ╟───────────────────────────────► ║                         ║
         ║ cmd: ping ...                   ║                         ║
         ║                                 ║                         ║
         ║ ◄───────────────────────────────╢                         ║
 measure ║            msg: id: "_pong" ... ║                         ║
response ║                                 ║                         ║
    time ║            ........             ║         ........        ║
         ║                                 ║                         ║
         ╟───────────────────────────────► ║                         ║
         ║ cmd: quit                       ║ disconnect client       ║
         ║                                 ║                         ║