Proof Portal
Omarchy
ProbeLabs65 findings · 95 requirementsA proof layer — requirements, tests and verified fixes — for two of Omarchy's subsystems: the application menu (launcher scripts, QML model, JSONC config, search and selection) and the lock screen (lock scripts, QML, PAM authentication). Scope is deliberately limited to those components of omacom/omarchy; the rest of the distribution is not covered.
omarchy font set redirects every family whose name contains "mono", not just generic monospace
Reported by DanielSRojo · filed Aug 26, 2026 · open at source
At a glance
- 1 · What is claimed?
- Only the report text below — no validator has restated it as checkable claims yet.
- 2 · What does it affect?
- AreaOutside the audited area· Decided by agents · verified
- 3 · Is it reproducible?
- No validation has been run yet.
- 4 · What remains unclear?
- Not validated yet: no claims, no reproducer.
- 5 · What happens next?
- Decided by agents and verified by a second, independent agent — see the decision.
Original report
What happened
omarchy font set <name> writes a ~/.config/fontconfig/fonts.conf that
redirects every family whose name contains "mono" to the chosen font, not
just requests for the generic monospace. Afteromarchy font set "Monaspace Neon NF", half the fonts offered byomarchy font list become unreachable:
$ fc-match monospace
Monaspace Neon NF # intended
$ fc-match "JetBrainsMono Nerd Font"
Monaspace Neon NF # BUG
$ fc-match "Liberation Mono"
Monaspace Neon NF # BUG
$ fc-match "Adwaita Mono"
Monaspace Neon NF # BUG
$ fc-match "Nimbus Mono PS"
Monaspace Neon NF # BUG
$ fc-match "iA Writer Mono S"
Monaspace Neon NF # BUG
$ fc-match "Monaspace Argon NF"
Monaspace Argon NF # unaffected, see Cause
$ fc-match "Liberation Sans"
Liberation Sans # unaffectedAll of those are installed, and all ten appear in omarchy font list. The five
marked BUG are exactly the five whose names contain "Mono".
What was expected
Only the generic monospace should be redirected. A request naming a specific
installed family should return that family.
Steps to reproduce
omarchy font set "Monaspace Neon NF" # any font whose name lacks "mono"
fc-match "Liberation Mono" # -> Monaspace Neon NF, not Liberation Mono
# bisect to confirm the source
mv ~/.config/fontconfig/fonts.conf{,.off}
fc-match "Liberation Mono" # -> Liberation Mono, correct
mv ~/.config/fontconfig/fonts.conf{.off,}
fc-match "Liberation Mono" # -> Monaspace Neon NF againCause
omarchy-font-set writes:
<match target="pattern">
<test name="family" qual="any"><string>monospace</string></test>
<edit name="family" mode="prepend_first" binding="strong">
<string>$font_name</string>
</edit>
</match>Two things combine:
/etc/fonts/conf.d/48-guessfamily.confloads earlier and appends the
generic monospace to the family list of any pattern whose family name
contains the substring mono:
<match target="pattern">
<test name="family" compare="contains"><string>mono</string></test>
<edit name="family" mode="append_last"><string>monospace</string></edit>
</match> This is a name heuristic, not real monospace detection. So a request for
Liberation Mono arrives at the rule above with family
[Liberation Mono, monospace], and the qual="any" test matches it.
mode="prepend_first"inserts at the head of the whole family list, ahead
of the family the application actually asked for, and binding="strong"
makes it win.
This also explains why the Monaspace families are the one set that escapes:Monaspace does not contain mono, so 48-guessfamily.conf never appends the
generic to them and the rule never matches. The bug is invisible if you only
ever test with Monaspace.
Load order on a stock install, via fc-conflist:
+ /etc/fonts/conf.d/48-guessfamily.conf: Guess a generic-family for substitution
+ /etc/fonts/conf.d/50-omarchy.conf
+ /home/<user>/.config/fontconfig/fonts.conf
+ /etc/fonts/conf.d/50-user.conf
+ /etc/fonts/conf.d/60-generic.confSuggested fix
Use the alias/prefer idiom, which inserts after the matched generic rather than
at the head of the list, so a named family still outranks it:
<alias binding="strong">
<family>monospace</family>
<prefer><family>$font_name</family></prefer>
</alias>Verified: this makes all five named families above resolve correctly again.
One caveat, in case it is not already known: this alone does not restore the
intended default, because 50-omarchy.conf uses mode="assign" for its own
monospace default. assign replaces the literal monospace token withJetBrainsMono Nerd Font before the user file is loaded, so nothing downstream
can match monospace any more and the alias never fires — fc-match monospace
then returns JetBrainsMono. Switching 50-omarchy.conf's three generic rules
(monospace, sans-serif, serif) to alias/prefer as well would fix both
halves and let a user override compose with them as intended.
Impact
Any application that names a monospace font explicitly silently gets the wrong
one. It also makes font previewing impossible: launching a terminal with an
explicit font override renders the omarchy font set font instead, with no
error. That is how this was found — two ghostty windows launched with different--font-family values rendered pixel-identically.
System
- Omarchy 4.0.1-1
- fontconfig 2:2.18.3-2
- Kernel 7.1.9-arch1-2
- AMD Ryzen 5 5600G, Radeon RX 6650 XT
View raw text
### What happened
`omarchy font set <name>` writes a `~/.config/fontconfig/fonts.conf` that
redirects **every family whose name contains "mono"** to the chosen font, not
just requests for the generic `monospace`. After
`omarchy font set "Monaspace Neon NF"`, half the fonts offered by
`omarchy font list` become unreachable:
```
$ fc-match monospace
Monaspace Neon NF # intended
$ fc-match "JetBrainsMono Nerd Font"
Monaspace Neon NF # BUG
$ fc-match "Liberation Mono"
Monaspace Neon NF # BUG
$ fc-match "Adwaita Mono"
Monaspace Neon NF # BUG
$ fc-match "Nimbus Mono PS"
Monaspace Neon NF # BUG
$ fc-match "iA Writer Mono S"
Monaspace Neon NF # BUG
$ fc-match "Monaspace Argon NF"
Monaspace Argon NF # unaffected, see Cause
$ fc-match "Liberation Sans"
Liberation Sans # unaffected
```
All of those are installed, and all ten appear in `omarchy font list`. The five
marked BUG are exactly the five whose names contain "Mono".
### What was expected
Only the generic `monospace` should be redirected. A request naming a specific
installed family should return that family.
### Steps to reproduce
```bash
omarchy font set "Monaspace Neon NF" # any font whose name lacks "mono"
fc-match "Liberation Mono" # -> Monaspace Neon NF, not Liberation Mono
# bisect to confirm the source
mv ~/.config/fontconfig/fonts.conf{,.off}
fc-match "Liberation Mono" # -> Liberation Mono, correct
mv ~/.config/fontconfig/fonts.conf{.off,}
fc-match "Liberation Mono" # -> Monaspace Neon NF again
```
### Cause
`omarchy-font-set` writes:
```xml
<match target="pattern">
<test name="family" qual="any"><string>monospace</string></test>
<edit name="family" mode="prepend_first" binding="strong">
<string>$font_name</string>
</edit>
</match>
```
Two things combine:
1. `/etc/fonts/conf.d/48-guessfamily.conf` loads earlier and appends the
generic `monospace` to the family list of any pattern whose family name
*contains the substring* `mono`:
```xml
<match target="pattern">
<test name="family" compare="contains"><string>mono</string></test>
<edit name="family" mode="append_last"><string>monospace</string></edit>
</match>
```
This is a name heuristic, not real monospace detection. So a request for
`Liberation Mono` arrives at the rule above with family
`[Liberation Mono, monospace]`, and the `qual="any"` test matches it.
2. `mode="prepend_first"` inserts at the head of the whole family list, ahead
of the family the application actually asked for, and `binding="strong"`
makes it win.
This also explains why the Monaspace families are the one set that escapes:
`Monaspace` does not contain `mono`, so `48-guessfamily.conf` never appends the
generic to them and the rule never matches. The bug is invisible if you only
ever test with Monaspace.
Load order on a stock install, via `fc-conflist`:
```
+ /etc/fonts/conf.d/48-guessfamily.conf: Guess a generic-family for substitution
+ /etc/fonts/conf.d/50-omarchy.conf
+ /home/<user>/.config/fontconfig/fonts.conf
+ /etc/fonts/conf.d/50-user.conf
+ /etc/fonts/conf.d/60-generic.conf
```
### Suggested fix
Use the alias/prefer idiom, which inserts after the matched generic rather than
at the head of the list, so a named family still outranks it:
```xml
<alias binding="strong">
<family>monospace</family>
<prefer><family>$font_name</family></prefer>
</alias>
```
Verified: this makes all five named families above resolve correctly again.
One caveat, in case it is not already known: this alone does not restore the
intended default, because `50-omarchy.conf` uses `mode="assign"` for its own
monospace default. `assign` replaces the literal `monospace` token with
`JetBrainsMono Nerd Font` before the user file is loaded, so nothing downstream
can match `monospace` any more and the alias never fires — `fc-match monospace`
then returns JetBrainsMono. Switching `50-omarchy.conf`'s three generic rules
(`monospace`, `sans-serif`, `serif`) to alias/prefer as well would fix both
halves and let a user override compose with them as intended.
### Impact
Any application that names a monospace font explicitly silently gets the wrong
one. It also makes font previewing impossible: launching a terminal with an
explicit font override renders the `omarchy font set` font instead, with no
error. That is how this was found — two ghostty windows launched with different
`--font-family` values rendered pixel-identically.
### System
- Omarchy 4.0.1-1
- fontconfig 2:2.18.3-2
- Kernel 7.1.9-arch1-2
- AMD Ryzen 5 5600G, Radeon RX 6650 XT
Validation
Not checked yet. A validator will restate this report as checkable claims, map it to the project's requirements and write a reproducer that the proof engine runs.
Linked
Not linked to any known issue, other report or change yet.
Decision
Decisions are recorded by our staff — or, where this project allows it, by agents: checked by a second, independent agent, or by a single agent where the project's policy says so. Any decision reached so far is shown below.
- Out of scopeDecided by agents · verified · 2026-10-09 09:17 UTC