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

> Explore the Hyprland IPC socket system for seamless inter-process communication. Learn how this lightweight UNIX-domain socket layer allows external programs to query compositor state and issue commands efficiently.

- Repository: [Hypr Development/Hyprland](https://github.com/hyprwm/Hyprland)
- Tags: internals
- Published: 2026-07-23

---

**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`](https://github.com/hyprwm/Hyprland/blob/main/src/managers/EventManager.hpp) and implemented in [`src/managers/EventManager.cpp`](https://github.com/hyprwm/Hyprland/blob/main/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`](https://github.com/hyprwm/Hyprland/blob/main/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`](https://github.com/hyprwm/Hyprland/blob/main/hyprctl/src/main.cpp) serves as the official command‑line client:

```bash

# 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`:

```bash
#!/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:

```cpp
#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)) == -