Arrange Hyprland monitors without coordinate math.
<img alt="Terminal Trove Tool of the Week" src="https://github.com/crmne/hyprmoncfg/raw/v1.8.0/docs/assets/images/terminal-trove-tool-of-the-week-light.svg" height="48">
hyprmoncfg is a terminal layout editor, CLI, profile store, and hotplug/lid-aware daemon for Hyprland monitor setups. Drag displays into place, save hardware-aware profiles, apply them safely, and let the daemon switch profiles when monitors or your laptop lid changes.

desk, conference, or home-officemonitors.lua automatically when hyprland.lua is active, while preserving legacy monitors.conf setupsArch Linux:
yay -S hyprmoncfg
Latest main from AUR:
yay -S hyprmoncfg-git
Void Linux (Unofficial Repo):
echo "repository=https://mirror.black-hole.dev/$(uname -m)/" | sudo tee /etc/xbps.d/20-repository-extra.conf
sudo xbps-install -S hyprmoncfg
Build from source:
git clone https://github.com/crmne/hyprmoncfg.git
cd hyprmoncfg
go build -o bin/hyprmoncfg ./cmd/hyprmoncfg
go build -o bin/hyprmoncfgd ./cmd/hyprmoncfgd
install -Dm755 bin/hyprmoncfg ~/.local/bin/hyprmoncfg
install -Dm755 bin/hyprmoncfgd ~/.local/bin/hyprmoncfgd
Distro packagers should use PACKAGING.md.
Make sure ~/.config/hypr/hyprland.conf sources monitors.conf:
source = ~/.config/hypr/monitors.conf
Hyprland does not read that file automatically. hyprmoncfg creates and rewrites monitors.conf, then refuses to write if the source chain is missing so you do not edit a file Hyprland ignores.
hyprmoncfg
Drag monitors into place, press s, type a profile name like desk, and press Enter.
Apply it later from the CLI:
hyprmoncfg apply desk
After an AUR install:
systemctl --user daemon-reload
systemctl --user enable --now hyprmoncfgd
After a manual install:
mkdir -p ~/.config/systemd/user
cp packaging/systemd/hyprmoncfgd.local.service ~/.config/systemd/user/hyprmoncfgd.service
systemctl --user daemon-reload
systemctl --user enable --now hyprmoncfgd
The daemon scores every profile in ~/.config/hyprmoncfg/profiles/, so delete throwaway profiles before relying on automatic switching.
hyprmoncfg adapts to your theme. Here are some examples:
| Layout editor | Save dialog |
|---|---|
![]() |
![]() |
Configuring monitors in Hyprland means writing monitor= lines by hand. A 4K display at 1.33333x scale is effectively 2880x1620 pixels, so the monitor next to it needs to start at x=2880. Vertically centering a 1080p panel against it means doing division in your head, reloading, noticing the layout is wrong, and editing again.
It gets worse when setups change:
monitor= lines by hand and hope the coordinates are right.DP-1 and DP-2 can swap between boots.hyprmoncfg ships two binaries:
hyprmoncfg |
TUI + CLI for layout editing, profile management, and workspace planning |
hyprmoncfgd |
Background daemon that auto-applies the best matching profile on hotplug and lid changes |
Both use the same apply engine:
write monitors.conf -> reload Hyprland -> verify live state -> confirm or revert
There is no separate best-effort daemon path. If the TUI can apply a profile correctly, the daemon uses the same machinery.
Profiles live in ~/.config/hyprmoncfg/profiles/. Each profile has a canonical JSON file plus generated .conf and .lua sidecars you can keep as plain Hyprland snippets if you stop using hyprmoncfg. Add the directory to your dotfile manager and your layouts roam across every machine you own.
With chezmoi:
chezmoi add ~/.config/hyprmoncfg
Now your desk at home, your laptop on the road, and your Raspberry Pi in the closet all share the same profile library. The daemon picks the right one based on what's actually plugged in.
You don't commit the active ~/.config/hypr/monitors.conf or ~/.config/hypr/monitors.lua. You commit your profiles. The tool writes the active generated monitor config for you.
| hyprmoncfg | Monique | HyprDynamicMonitors | HyprMon | nwg-displays | kanshi | |
|---|---|---|---|---|---|---|
| GUI or TUI | TUI | GUI | TUI | TUI | GUI | CLI |
| Spatial layout editor | Yes | Yes | Partial | Yes | Yes | No |
| Drag-and-drop | Yes | Yes | No | Yes | Yes | No |
| Snapping | Yes | Not documented | No | Yes | Yes | No |
| Profiles | Yes | Yes | Yes | Yes | No | Yes |
| Auto-switching daemon | Yes | Yes | Yes | No (roadmap) | No | Yes |
| Workspace planning | Yes | Yes | No | No | Basic | No |
| Mirror support | Yes | Yes | Yes | Yes | Yes | No |
| Safe apply with revert | Yes | Yes | No | Partial (manual rollback) | No | No |
| Hyprland 0.55 Lua config | Yes | No | No | No | Yes | N/A |
| Include-chain verification | Yes | No | No | No | No | No |
| Additional runtime dependencies | None | Python + GTK4 + libadwaita | UPower, D-Bus | None | Python + GTK3 | None |
Full documentation at hyprmoncfg.dev.
Install the pre-commit hook to run CI checks locally before each commit:
ln -sf "$(pwd)/scripts/pre-commit" .git/hooks/pre-commit
The hook runs go mod tidy, go vet, go test, and go build.
Regenerate demo videos and screenshots:
./scripts/capture_media.sh
The media scripts use the installed hyprmoncfg from PATH.
Regenerate only screenshots:
./scripts/capture_screenshots.sh
MIT
—
$ claude mcp add hyprmoncfg \
-- python -m otcore.mcp_server <graph>