How the Hyprland IPC Socket System Works for Inter‑Process Communication

Hyprland implements a lightweight, UNIX‑domain‑socket based IPC (inter‑process communication) layer that lets external programs query the compositor’s state and issue commands through a non‑blocking event loop integrated with the Wayland event system.

The Hyprland IPC socket system provides the foundation for scriptable window management in the hyprwm/Hyprland repository. This architecture enables real‑time communication between the compositor and external tools without relying on D‑Bus or complex protocols, allowing any component to emit events via the global g_pEventManager instance.

Core Architecture Components

The IPC implementation centers on three primary abstractions defined in src/managers/EventManager.hpp and implemented in src/managers/EventManager.cpp.

CEventManager and Socket Initialization

The CEventManager class acts as the IPC server. During instantiation, it creates a UNIX‑domain socket at ${XDG_RUNTIME_DIR}/hypr/.hyprsunset.sock (falling back to $HOME/.local/share/hypr/ if XDG_RUNTIME_DIR is unset) and registers it with the compositor’s Wayland event loop. It manages two critical callbacks: onServerEvent for incoming connections and onClientEvent for write‑ready or disconnected clients.

SHyprIPCEvent Structure

Events are encapsulated in the SHyprIPCEvent struct, which holds an event name string and an associated data payload. This simple event=data format allows easy parsing in any programming language.

Global Event Manager Instance

The g_pEventManager global pointer exposes the event system throughout the codebase. Any Hyprland component can emit an IPC event by constructing an SHyprIPCEvent and calling g_pEventManager->postEvent(event), which triggers the distribution pipeline.

Event Flow and Communication Lifecycle

The IPC system follows a five‑stage pipeline that ensures ordered, non‑blocking delivery:

  1. Server startup – CEventManager creates the socket file and registers onServerEvent and onClientEvent callbacks with the main loop.

  2. Client connection – When a client (such as hyprctl or a custom script) connects, CEventManager adds a new SClient entry to the m_clients vector, storing the file descriptor and an event‑queue vector.

  3. Event emission – Compositor components build an SHyprIPCEvent (e.g., {"workspace","1"}) and invoke postEvent. This method calls formatEvent(event) to produce a "event data\n" string and pushes it onto every client’s events queue.

  4. Flushing – The main loop invokes onClientEvent for each ready client. The flushClient method writes queued strings to the socket, handling partial writes via writeOffset. If a client closes or encounters an error, it is removed from m_clients.

  5. Client read – Clients read lines delimited by \n, parsing the first token as the event name and the remainder as payload. The reference implementation in hyprctl/src/main.cpp demonstrates parsing these responses for display or command execution.

Socket Path and Runtime Configuration

The socket file location follows XDG Base Directory specifications:

  • Primary path: ${XDG_RUNTIME_DIR}/hypr/.hyprsunset.sock
  • Fallback path: $HOME/.local/share/hypr/.hyprsunset.sock

Because the socket is non‑blocking and integrated into the Wayland event loop, IPC traffic never stalls the compositor, and the SClient abstraction guarantees each listener receives a consistent, ordered stream of events.

Practical IPC Usage Examples

Querying State with hyprctl

The hyprctl utility in hyprctl/src/main.cpp serves as the official command‑line client:


# Query the active workspace

hyprctl workspaces

# Listen for live events with JSON output

hyprctl monitors -j

Bash Scripts Using socat

For custom automation, you can write directly to the socket using socat:

#!/usr/bin/env bash
SOCKET="${XDG_RUNTIME_DIR:-$HOME/.local/share}/hypr/.hyprsunset.sock"

# Send a dispatch command to open a terminal

printf "dispatch exec,alacritty\n" | socat - UNIX-CONNECT:"$SOCKET"

Custom C++ Client

A minimal C++ implementation demonstrates direct socket communication:

#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <iostream>
#include <cstring>

int main() {
    const char *runtimeDir = getenv("XDG_RUNTIME_DIR");
    std::string socketPath = runtimeDir 
        ? std::string(runtimeDir) + "/hypr/.hyprsunset.sock"
        : std::string(getenv("HOME")) + "/.local/share/hypr/.hyprsunset.sock";

    int fd = socket(AF_UNIX, SOCK_STREAM, 0);
    sockaddr_un addr{};
    addr.sun_family = AF_UNIX;
    strncpy(addr.sun_path, socketPath.c_str(), sizeof(addr.sun_path) - 1);
    
    if (connect(fd, (sockaddr*)&addr, sizeof(addr)) == -

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →