Hyprland Ditches Its Config Language for Lua
The 0.55 release follows the Neovim playbook, kills the plugin ABI treadmill, and puts hyprlang on a short fuse.
Hyprland 0.55, released in May, quietly did something more consequential than any of its flashy compositor features ever have: it deprecated hyprlang, the project's homegrown config language, and made Lua the official way to configure the most-hyped Wayland compositor in the tiling world. Your hyprland.conf still loads — but only "for a few releases," and new config features won't land in the old format at all.
This is the right call, arrived at the way most projects arrive at it: the hard way. But the migration window Hyprland has set is aggressive enough that it's worth planning for now, not later.
Every config language becomes a bad programming language
Hyprland's stated rationale is refreshingly blunt. What started four years ago as simple k = v pairs mutated, feature by feature, into lines like windowrule = immediate yes, border_size 4, class:^(amongus)$, title:^(sus)$ — a comma-delimited micro-DSL with regexes embedded in it, which the maintainers themselves now describe as "unreliable, unreadable, limited and simply cluttered."
This is the oldest story in configuration. A declarative format is born simple, users demand conditionals ("different gaps on my laptop"), loops ("bind workspaces 1–10"), and composition — and the format grows ad-hoc string syntax to fake all three. Anyone who watched Vimscript accrete for thirty years, or who maintains a CI pipeline in YAML with templating bolted on, knows exactly where this ends. At some point you either keep inventing syntax or you adopt a real language that already has variables, functions, and error messages.
Lua is the well-worn answer. AwesomeWM has been Lua-all-the-way-down since 2008. Hammerspoon scripted macOS with it. WezTerm configures in it. And most relevantly, Neovim made Lua a first-class config and plugin language in 0.5 and triggered the largest plugin renaissance in the editor's history. Hyprland is following the Neovim playbook almost beat for beat: embed Lua, expose the internals as an API, let the ecosystem do the rest.
The real prize isn't config — it's the plugin ABI treadmill
Reading this as "new syntax for the same settings" undersells it. Hyprland's existing extension story is C++ plugins, loaded as shared objects and managed by hyprpm — and because they compile against Hyprland's internal headers, they're version-locked and routinely break on every release until authors rebuild. It's the classic unstable-ABI treadmill, and it's been the single most fragile part of the ecosystem.
The Lua layer attacks that directly. Alongside hl.config() for options, 0.55 exposes event callbacks via hl.on, timers, and — the headline feature — a Layout API that lets you define custom window layouts in your config and apply them globally, per-workspace, or per-monitor. Custom layouts previously required a compiled plugin. The project's framing is explicit: the scripting surface allows "things not even possible without plugins before." A scripted layout or event hook survives a compositor upgrade the way a recompiled .so never reliably did. Neovim's lesson applies here too: once extension logic moved from an FFI-ish boundary into an embedded scripting API, plugin count exploded because the maintenance cost collapsed.
What migrating actually looks like
The mechanics are sane. Hyprland looks for ~/.config/hypr/hyprland.lua; if it's absent, your old .conf loads as before. The new format is a functional API on an hl namespace rather than free-form tables:
hl.config({
general = {
gaps_in = 5,
border_size = 2,
},
})
hl.bind(mainMod .. " + Q", hl.dsp.exec_cmd(terminal))
hl.bind(mainMod .. " + left", hl.dsp.focus({ direction = "left" }))
Dispatchers become composable hl.dsp.* functions instead of magic strings, which means typos fail loudly instead of silently. You can split config across files with plain require, replacing hyprlang's source directive. And the project ships autogenerated Lua stubs (typically installed to /usr/share/hypr/stubs/) so lua-language-server gives you completion and type-checking on the whole API — something a bespoke DSL could never offer without someone writing a dedicated LSP. That workspace loop you used to fake with a shell script generating config lines is now just a for loop.
The practical migration path: keep your .conf working, port section by section into hyprland.lua with the wiki open, and wire up the stubs in your editor before you start — the API surface is large enough that flying without completion is masochism.
The two-release fuse is the part I'd push back on
Here's the catch: hyprlang support lasts "1 – 2 releases starting from 0.55." Hyprland ships releases on a cadence measured in months. That means the old format could be gone before the year is out — for a config language that four years of ricing culture, dotfiles repos, YouTube tutorials, and copy-paste guides are built on. Neovim, for all its Lua enthusiasm, never removed Vimscript; that patience is a big reason the transition generated goodwill instead of forks.
The tooling ecosystem takes the hardest hit. Everything that generates or parses Hyprland configs — Nix home-manager's Hyprland module, GUI settings editors, dotfile managers, theming frameworks that template .conf files — now targets a deprecated format. Generating Lua from Nix is doable but strictly worse than generating declarative key-values, and Turing-complete configs are effectively opaque to any tool that wants to read settings back out. Declarative formats are trivially machine-manipulable; programs are not. That trade-off is real and permanent, and it's the honest cost of this move.
For individual users, the risk profile changes too: a hyprlang typo broke one line, while an uncaught Lua error can break config load at session start. Test with a nested session before you commit your daily driver.
Still — the verdict is easy. Config-as-code has won this argument everywhere it's been tried, the plugin story alone justifies the switch, and Hyprland's user base skews toward exactly the people who'll script layouts for fun by August. Start migrating now; just don't be surprised when the grace period is shorter than you'd like.
Sources & further reading
- Hyprland 0.55 Release Notes — hypr.land
- Lua-ification of Hyprland configs — hypr.land
- Example hyprland.lua config — github.com
- Hyprland Wiki - Configuring — wiki.hypr.land
- Hyprland 0.55 Released With Lua-Based Configuration, User-Defined Layouts — phoronix.com
Mariana covers the fast-moving world of machine learning and generative AI, with a particular focus on how these technologies are reshaping development workflows. When she isn't stress-testing the latest foundation models, she's usually at a local hackathon.
Discussion 2
totally get this move. we migrated our entire monitoring stack off a custom dsl to lua last year and the relief of just having a real language with actual error messages instead of 'syntax error on line 47' was unhinged. hyprlang was getting feature-creep anyway — every new thing meant another config syntax to nail down.
yeah but the actual gotcha nobody mentions is the migration tooling. we had the same relief hitting lua, right up until we realized there's no automated converter and half our team's configs had undocumented shortcuts that only worked in the old thing. took three weeks of "wait why does this even work" archaeology. hope hyprland ships something better than 'here's the docs, good luck'.