Hyprland Lua loaders hardcode $HOME/.config instead of honouring XDG_CONFIG_HOME #82

Open
opened 2026-10-01 22:20:56 +08:00 by Breadway · 2 comments
Owner

How I found it

Setting up a sandboxed nested Hyprland session to test bos-settings: with XDG_CONFIG_HOME pointed at a copy of the config, the session still read the real ~/.config/hypr/*.json. hyprland.lua, scripts/ui/settings.lua and scripts/display/monitors.lua all build paths from os.getenv("HOME") .. "/.config/hypr/".

Confidence

Medium. Observed; real-world impact only when XDG_CONFIG_HOME is set to something other than ~/.config.

Explanation

bos-settings writes settings.json, monitors.json, binds.json and autostart.json under dirs::config_dir() (which honours XDG_CONFIG_HOME), while the Lua loaders read from $HOME/.config. If a user sets XDG_CONFIG_HOME, every Settings change is written somewhere Hyprland never reads, silently. Expected: resolve os.getenv("XDG_CONFIG_HOME") or HOME .. "/.config" once and use it everywhere.

## How I found it Setting up a sandboxed nested Hyprland session to test bos-settings: with `XDG_CONFIG_HOME` pointed at a copy of the config, the session still read the real `~/.config/hypr/*.json`. `hyprland.lua`, `scripts/ui/settings.lua` and `scripts/display/monitors.lua` all build paths from `os.getenv("HOME") .. "/.config/hypr/"`. ## Confidence Medium. Observed; real-world impact only when XDG_CONFIG_HOME is set to something other than ~/.config. ## Explanation bos-settings writes `settings.json`, `monitors.json`, `binds.json` and `autostart.json` under `dirs::config_dir()` (which honours XDG_CONFIG_HOME), while the Lua loaders read from `$HOME/.config`. If a user sets XDG_CONFIG_HOME, every Settings change is written somewhere Hyprland never reads, silently. Expected: resolve `os.getenv("XDG_CONFIG_HOME") or HOME .. "/.config"` once and use it everywhere.
Author
Owner

PR opened: #96 (Breadway/bos #96)
Head SHA: 4d0f74b602
One helper (scripts/lib/paths.lua) resolves the config dir; all loaders use it. Verified by a standalone lua/luajit check (18/18) on staged copies only, not in a live or nested Hyprland. Needs independent review.

PR opened: https://git.breadway.dev/Breadway/bos/pulls/96 (Breadway/bos #96) Head SHA: 4d0f74b602d0dcc897ef6170d4b7c4f41ee241ec One helper (scripts/lib/paths.lua) resolves the config dir; all loaders use it. Verified by a standalone lua/luajit check (18/18) on staged copies only, not in a live or nested Hyprland. Needs independent review.
Author
Owner

Caveat on PR #96 (head 4d0f74b602): Unverified assumption (found after the PR was opened): hyprland.lua locates scripts/lib/paths.lua with debug.getinfo(1, "S").source. That only works if Hyprland loads the config as a file chunk (source starting with "@"). If Hyprland loads it from a string, the fallback is "." and dofile fails at the top of hyprland.lua, which would stop the whole config. The standalone test loads the file directly, so it does not cover this. Not verified against a live or nested Hyprland. Needs a check in a private nested session before merge, or a fallback to the XDG/HOME rule if source is not a path.

Caveat on PR #96 (head 4d0f74b602d0dcc897ef6170d4b7c4f41ee241ec): Unverified assumption (found after the PR was opened): hyprland.lua locates scripts/lib/paths.lua with debug.getinfo(1, "S").source. That only works if Hyprland loads the config as a file chunk (source starting with "@"). If Hyprland loads it from a string, the fallback is "." and dofile fails at the top of hyprland.lua, which would stop the whole config. The standalone test loads the file directly, so it does not cover this. Not verified against a live or nested Hyprland. Needs a check in a private nested session before merge, or a fallback to the XDG/HOME rule if source is not a path.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Breadway/bos#82
No description provided.