Hyprforge

How it's made

The rules that came from being wrong.

The repository keeps a list of every mistake that was hard to see coming: what happened, why it wasn't obvious, and what now stops it happening again. It's the most useful thing in there. Here's some of it.

§1From the list
the lock screen

A keysym name is the password.

XK_a is the letter a. Logging "just the keysym" writes your password down in barely-disguised form.

Nothing derived from a keystroke reaches a log. What you typed shows as a count.

your config

Unreadable isn't empty.

Treating a file that wouldn't parse as a file with nothing in it cost a user 37 keybinds written by hand.

Missing means first run. Broken means you're told, and nothing is written over it.

the lock screen

A round number is someone else's timeout.

Five seconds to lock, and our side was done in a millisecond. The compositor was waiting on us.

Measure before optimising anything that talks to another process.

tests

A test that couldn't run didn't pass.

Test runners have no "skipped". One that returned early printed ok having checked nothing.

A skipped check says so, and the check script shows it in yellow.

the login screen

The same colour, different pixels.

Login and lock read the same theme, and login was visibly washed out. The two renderers blend in different colour spaces.

Both draw with one renderer now, and "should these match" is settled by comparing pixels.

the login screen

The way in is the compositor.

Every keybind on a login screen belongs to whoever's at the keyboard. A terminal bind there is a shell without a password.

The greeter's compositor has no keybinds at all.

the clipboard

Sent isn't delivered.

A paste reported success and delivered nothing. The popup closed before the compositor read its keys.

It waits for proof the keys arrived, not for a delay that happens to be long enough.

the tray

An icon that hides is a switch you can't reach.

The Wi-Fi icon disappeared when Wi-Fi was off, exactly when you'd need its menu to turn it on.

Every icon you turned on stays visible, and a test holds it to that.

everything

Never wait without a limit.

hyprctl, gsettings and fc-list can all stop answering. A plain wait waits forever.

Every other program is given a time limit. Not answering is treated like not starting.

§2Testing

It asks the real thing.

The first tier runs anywhere: the linter, every test, and checks that the documentation and manifests still tell the truth. Every tier after it asks a real system a question it can only answer by being there. Does Hyprland parse what we generate? Does NetworkManager agree about signal strength? Does every icon name resolve in the theme you actually have?

Each tier only runs when the thing it asks is present. The live tiers only ever read, because they run on a computer someone is using, and a test that could drop your Wi-Fi isn't worth having.

$ tools/hf check
✓ lint and every test
✓ docs name things that exist
✓ Hyprland parses what we write
✓ unzip, tar and 7z agree with us
✓ NetworkManager, BlueZ, UPower
✓ the icon theme resolves every name
✓ each piece builds alone from crates.io
– fprintd: skipped, no reader here
  … 23 tiers in all
§3Standing alone

Install one piece on a clean machine. Does it work?

That's the test for every piece. Being shared when they're built is what makes them a suite. Being separate when they're installed is what keeps it honest. A missing theme file means first run, so the clipboard is themed correctly on a machine that's never seen Settings. A stopped service is something to tell you about, not a crash. A missing sibling is a line in a log, and the rest carries on.