Daemon Behavior
Why a daemon
You save profiles with the TUI. But who applies them when you’re not looking?
That’s what hyprmoncfgd does. It runs in the background, watches for monitor hotplug and lid events, and applies the best matching profile automatically. Plug in a monitor, close the lid, undock your laptop, connect to a projector – the daemon handles it.
This is especially useful if you move between setups regularly. A conference projector, a coworking space monitor, your desk at home – each one has different resolution, position, and scale requirements. Save a profile once, and the daemon takes care of it from then on.
Setup
If you installed via the AUR or a package manager, the systemd service is already installed. Just enable it:
systemctl --user enable --now hyprmoncfgd
If you built from source and the service file is not installed:
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
That’s it. The daemon is running. The rest of this page explains how it decides which profile to apply and how to troubleshoot it.
How it works
When the daemon detects a monitor or lid-state change, it runs through these steps:
- Read the current monitor set from Hyprland
- Score every saved profile against the connected hardware (see Profile matching below for how scoring works)
- Pick the highest-scoring profile
- If the lid is closed and an external monitor is connected, force internal laptop-panel outputs off for this apply
- Write
monitors.confatomically (temp file + rename, so a crash mid-write can’t corrupt your config) - Tell Hyprland to reload
- Re-read monitor state and verify the result matches what was intended
If the winning profile is the same one that’s already applied, the daemon skips re-applying it. You won’t see unnecessary reloads.
The daemon uses the same apply engine as the TUI. There is no separate “best effort” code path. If the TUI can apply a profile correctly, so can the daemon.
Profile matching
Profiles are matched by hardware identity (make, model, serial) – not connector name. This means your layout survives when monitors swap between DP-1 and DP-2 across reboots. Each profile is scored against the currently connected monitors:
| Condition | Points |
|---|---|
| Monitor enabled in profile and connected | +100 |
| Monitor disabled in profile but connected | +50 |
| Connected monitor not in the profile | −20 |
| Monitor enabled in profile but not connected | −30 |
Highest score wins. Ties break alphabetically by profile name.
On laptops, the daemon also reads lid state. UPower is optional, but recommended: with UPower available, lid changes arrive as D-Bus events and the daemon can react immediately. Without UPower, the daemon falls back to polling /proc/acpi/button/lid/*/state at --lid-poll-interval, which defaults to 1s and is not available on every system. If neither source exists, lid-aware switching is disabled and monitor hotplug still works.
Lid state is not a separate profile type. Save the profile for the monitor setup you actually have attached. When the lid is closed and an external monitor is connected, hyprmoncfg treats internal laptop-panel outputs like eDP-1, LVDS-1, or DSI-1 as forced off for that apply. Saved profiles are not rewritten. If workspace rules target the forced-off internal panel, those workspaces are moved to the first enabled external output in the selected profile.
Every Profile Is A Candidate
The daemon does not know which profiles are “real” and which were temporary experiments. It scores every JSON file in your profiles directory. An old throwaway profile with a high enough score will win over the one you actually want.
If you want reliable auto-switching:
- Save profiles for every real monitor setup you want the daemon to handle
- Keep one profile per setup – don’t accumulate near-duplicates
- Delete experimental profiles when you’re done experimenting
- If two profiles tie, the one whose name comes first alphabetically wins
- When auto-switching picks the wrong profile, start by listing the files in
~/.config/hyprmoncfg/profiles/– a forgotten profile is almost always the answer
Run manually
For testing or one-off use:
hyprmoncfgd
Useful flags
hyprmoncfgd --debounce 1500ms # wait longer before applying after a plug event
hyprmoncfgd --poll-interval 5s # how often to run fallback monitor checks
hyprmoncfgd --lid-poll-interval 1s # how often to run fallback lid checks
hyprmoncfgd --profile desk # always apply this specific profile
hyprmoncfgd --quiet # suppress log output
Forcing a specific profile
Use --profile <name> to bypass automatic matching entirely. The daemon applies this one profile every time, regardless of what’s connected. This is useful when you know exactly which setup you’re on and want to eliminate any chance of a wrong match.
Stop the running daemon first, then start it with the flag:
systemctl --user stop hyprmoncfgd
hyprmoncfgd --profile conference-projector
Running two daemons at the same time causes them to fight over monitors.conf – your monitors will flicker back and forth between profiles.
Logs
journalctl --user -u hyprmoncfgd -f
The log shows every step: which profiles were scored, what each one scored, which one won, what was written to monitors.conf, and whether verification passed. This is the first place to look when you want to understand why the daemon picked a particular profile.
Separate Matching From Applying
If you’re not sure whether the daemon picked the wrong profile or failed to apply the right one, test the profile directly with hyprmoncfg apply <name>. If the layout looks correct, the problem is matching, not applying – check the logs and your profile directory.
Filing A Matching Bug
If you think the daemon selected the wrong profile, open an issue and include all profiles from ~/.config/hyprmoncfg/profiles/, not just the one you expected to win. Matching depends on the full candidate set.