axctl is a universal IPC daemon and CLI for Wayland compositors. It normalizes window, workspace, monitor, layout, config, and system operations across Hyprland, Niri, and MangoWC via a JSON-RPC API over a Unix socket.
- Runs a compositor-aware daemon that auto-detects Hyprland, Niri, or MangoWC
- Exposes a single JSON-RPC interface over
/tmp/axctl-$UID.sock - Provides a CLI for window and workspace management, configuration, and system helpers
- Watches a TOML config file and applies changes live when possible
- Hyprland
- Niri
- MangoWC
axctl daemondetects the active compositor and starts a JSON-RPC serveraxctl <command>is a client that sends JSON-RPC requests to the daemon- The socket lives at
/tmp/axctl-$UID.sock
curl -L get.axeni.de/axctl | shOn NixOS, the installer uses nix profile add github:Axenide/axctl instead of
writing to /usr/local/bin.
Requires Go 1.25+.
go build -o axctl .
./axctl --versionnix profile add github:Axenide/axctl
nix build
./result/bin/axctl --version
nix run# Start the daemon (keep it running)
./axctl daemon
# Query state
./axctl window list
# Stream events
./axctl subscribeGeneral form:
axctl <command> <action> [args]Run axctl with no arguments to print the full built-in command list.
axctl window list
axctl window active
axctl window focus <id>
axctl window move <l|r|u|d> [id]
axctl window resize <w> <h> [id]
axctl window fullscreen <0|1> [id]
axctl window toggle-floating [id]axctl workspace list
axctl workspace active
axctl workspace switch <id>
axctl workspace move-to <workspace_id> [window_id]axctl monitor list
axctl monitor focus <id>
axctl monitor set-dpms <monitor_id> <0|1>axctl layout set <name>axctl config get <key>
axctl config set <key> <value>
axctl config batch '{"gaps.inner": 8, "gaps.outer": 12}'
axctl config reloadSupported config keys include:
gaps.inner, gaps.outer, border.width, border.active_color,
border.inactive_color, opacity.active, opacity.inactive, blur.enabled,
blur.size, blur.passes.
axctl system get-cursor-position
axctl system switch-keyboard-layout [next|prev]
axctl system set-keyboard-layouts "us,es" "altgr-intl,"
axctl system idle-wait <ms>
axctl system is-idle <ms>
axctl system get-capabilitiesWindow, workspace, and monitor IDs are compositor-defined. Treat them as strings in scripts because Hyprland can use hexadecimal IDs while Niri uses integers.
The daemon loads TOML from:
~/.config/axctl/config.toml
If the file exists, the daemon will load it on startup and watch it for
changes (including any include files), applying updates live when supported.
Example snippet:
[appearance]
[appearance.gaps]
inner = 5
outer = 10
[appearance.border]
width = 2
active_color = "#ff5555"
inactive_color = "#333333"
[input]
[input.keyboard]
layouts = "us,es"
variants = "altgr-intl,"
[[keybinds]]
modifiers = ["SUPER"]
key = "Return"
dispatcher = "exec"
argument = "kitty"
enabled = trueSee pkg/config/example.toml for the full configuration reference.
The daemon uses these environment variables to detect sockets:
XDG_RUNTIME_DIRfor Wayland socketsWAYLAND_DISPLAYfor MangoWC fallbackNIRI_SOCKETfor NiriHYPRLAND_INSTANCE_SIGNATUREfor Hyprland
The daemon listens on:
/tmp/axctl-$UID.sock
Error: axctl daemon is already running.- Stop the existing daemon or delete a stale
/tmp/axctl-$UID.sockand restart.
- Stop the existing daemon or delete a stale
Error: no supported compositor detected- Ensure your compositor is running and the expected socket variables are set (see Environment and sockets).
Error connecting to daemon- Start the daemon with
axctl daemonand verify the socket exists.
- Start the daemon with
go test ./...See LICENSE.
