Proof Portal

Project overview

Omarchy

ProbeLabs65 findings · 95 requirements

A 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.

Inbox
ReportR-231GitHub issuePublicDecided· Out of scope

omarchy font set repoints explicitly named monospace families, not just generic "monospace"

Reported by shawn1905 · filed Sep 21, 2026 · open at source

Decided: Out of scope — decided by agents · verified 3 days ago.

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

omarchy font set repoints explicitly named monospace families, not just generic "monospace"revision 1 · captured 2026-09-28 21:23 UTC via poll

Summary

omarchy font set <X> writes a fontconfig rule that prepends <X> to every pattern whose family list mentions monospace. Because 48-guessfamily.conf appends monospace to the family list of any family whose name contains mono, that rule also captures patterns that explicitly asked for a different monospace family. After a font change, no other monospace family can be selected by name anymore — which also makes a per-app monospace font (e.g. a terminal that deliberately asks for JetBrainsMono Nerd Font) impossible without removing the rule.

Environment

  • Omarchy 4.0.4-1, Arch Linux x86_64
  • Hyprland 0.56.2
  • fontconfig 2:2.18.3-2

Steps to reproduce

omarchy font set "Sarasa Mono SC"
fc-match "DejaVu Sans Mono"          # -> Sarasa Mono SC   (expected: DejaVu Sans Mono)
fc-match "JetBrainsMono Nerd Font"   # -> Sarasa Mono SC   (expected: JetBrainsMono Nerd Font)
fc-match "Noto Sans Mono"            # -> Sarasa Mono SC   (expected: Noto Sans Mono)
fc-match "monospace"                 # -> Sarasa Mono SC   (expected)

Same with any other choice (omarchy font set "FiraCode Nerd Font Mono" makes all four return FiraCode Nerd Font Mono).

Root cause

  1. omarchy-font-set writes ~/.config/fontconfig/fonts.conf:
<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>
  1. /etc/fonts/conf.d/50-user.conf includes that file, so it is evaluated after 48-guessfamily.conf and 50-omarchy.conf.
  2. 48-guessfamily.conf runs, for any pattern whose family name contains mono:
<edit name="family" mode="append_last"><string>monospace</string></edit>

So by the time the rule from step 1 runs, an explicit request for DejaVu Sans Mono / Sarasa Mono SC / JetBrainsMono Nerd Font already carries monospace in its family list: the qual="any" test matches, prepend_first binding="strong" puts the chosen family at the head of the list, and it wins the match. The rule exists to override 50-omarchy.conf's monospace → assign JetBrainsMono Nerd Font, which is the only reason it cannot simply be dropped.

Evidence

FcConfigSubstitute pattern dumps with only the package configs active (no user rule), showing monospace sitting in the family list of explicitly named families:

monospace                : 73 families, "monospace" at index 64, 67, 71   first two: JetBrainsMono Nerd Font, DejaVu LGC Sans Mono
DejaVu Sans Mono         : 76 families, "monospace" at index 66, 69, 71, 74  first two: DejaVu Sans Mono, DejaVu LGC Sans Mono
JetBrainsMono Nerd Font  : 73 families, "monospace" at index 65, 71        first two: JetBrainsMono Nerd Font, JetBrainsMono Nerd Font
Sarasa Mono SC           : 73 families, "monospace" at index 65, 71        first two: Sarasa Mono SC, JetBrainsMono Nerd Font

Suggested fixes (both measured with fc-match)

A — exact, needs a config file ordered before `48-guessfamily.conf`. A rule evaluated earlier sees family = ["monospace"] for a generic request and ["Sarasa Mono SC", …] for a named one, so keying it on the first family value is enough:

<!-- /etc/fonts/conf.d/47-omarchy-font.conf, rewritten by `omarchy font set` -->
<match target="pattern">
  <test qual="first" name="family" compare="eq">
    <string>monospace</string>
  </test>
  <edit name="family" mode="prepend_first" binding="strong">
    <string>Sarasa Mono SC</string>
  </edit>
</match>

Measured with that file symlinked in at position 47, everything else stock:

queryresult
monospaceSarasa Mono SC ✅
Sarasa Mono SCSarasa Mono SC ✅
JetBrainsMono Nerd FontJetBrainsMono Nerd Font ✅
DejaVu Sans MonoDejaVu Sans Mono ✅
Noto Sans Mono, Liberation Mono, iA Writer Mono Sthemselves ✅
:charset=e0b0 (Nerd Font glyph)JetBrainsMono Nerd Font ✅
:charset=4e2d (中)Sarasa Mono CL ✅

Caveat: the rule then lives under /etc, so omarchy font set would need a privileged write for it (or a package/migration-owned file that it rewrites).

B — no privilege change. Keep writing ~/.config/fontconfig/fonts.conf, but test the first family against the family 50-omarchy.conf currently assigns (read out of that file at write time, so it survives a changed default):

<test qual="first" name="family" compare="eq">
  <string>JetBrainsMono Nerd Font</string>   <!-- 50-omarchy.conf's monospace assign -->
</test>

Measured: monospace → chosen font ✅; Sarasa Mono SC, DejaVu Sans Mono, Noto Sans Mono, Liberation Mono → themselves ✅. One residual case stays broken: an explicit request for JetBrainsMono Nerd Font is still repointed, since after 50-omarchy.conf's assign a generic request and that explicit request differ only by a duplicated first family value, which the match language cannot distinguish.

Workaround in use locally

Option B, regenerated by a ~/.config/omarchy/hooks/font-set.d/ hook so it survives every omarchy font set.

View raw text
## Summary

`omarchy font set <X>` writes a fontconfig rule that prepends `<X>` to **every** pattern whose family list mentions `monospace`. Because `48-guessfamily.conf` appends `monospace` to the family list of any family whose *name* contains `mono`, that rule also captures patterns that explicitly asked for a different monospace family. After a font change, no other monospace family can be selected by name anymore — which also makes a per-app monospace font (e.g. a terminal that deliberately asks for `JetBrainsMono Nerd Font`) impossible without removing the rule.

## Environment

- Omarchy 4.0.4-1, Arch Linux x86_64
- Hyprland 0.56.2
- fontconfig 2:2.18.3-2

## Steps to reproduce

```bash
omarchy font set "Sarasa Mono SC"
fc-match "DejaVu Sans Mono"          # -> Sarasa Mono SC   (expected: DejaVu Sans Mono)
fc-match "JetBrainsMono Nerd Font"   # -> Sarasa Mono SC   (expected: JetBrainsMono Nerd Font)
fc-match "Noto Sans Mono"            # -> Sarasa Mono SC   (expected: Noto Sans Mono)
fc-match "monospace"                 # -> Sarasa Mono SC   (expected)
```

Same with any other choice (`omarchy font set "FiraCode Nerd Font Mono"` makes all four return `FiraCode Nerd Font Mono`).

## Root cause

1. `omarchy-font-set` writes `~/.config/fontconfig/fonts.conf`:

```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>
```

2. `/etc/fonts/conf.d/50-user.conf` includes that file, so it is evaluated *after* `48-guessfamily.conf` and `50-omarchy.conf`.
3. `48-guessfamily.conf` runs, for any pattern whose family name contains `mono`:

```xml
<edit name="family" mode="append_last"><string>monospace</string></edit>
```

So by the time the rule from step 1 runs, an explicit request for `DejaVu Sans Mono` / `Sarasa Mono SC` / `JetBrainsMono Nerd Font` already carries `monospace` in its family list: the `qual="any"` test matches, `prepend_first binding="strong"` puts the chosen family at the head of the list, and it wins the match. The rule exists to override `50-omarchy.conf`'s `monospace` → `assign JetBrainsMono Nerd Font`, which is the only reason it cannot simply be dropped.

## Evidence

`FcConfigSubstitute` pattern dumps with only the package configs active (no user rule), showing `monospace` sitting in the family list of explicitly named families:

```
monospace                : 73 families, "monospace" at index 64, 67, 71   first two: JetBrainsMono Nerd Font, DejaVu LGC Sans Mono
DejaVu Sans Mono         : 76 families, "monospace" at index 66, 69, 71, 74  first two: DejaVu Sans Mono, DejaVu LGC Sans Mono
JetBrainsMono Nerd Font  : 73 families, "monospace" at index 65, 71        first two: JetBrainsMono Nerd Font, JetBrainsMono Nerd Font
Sarasa Mono SC           : 73 families, "monospace" at index 65, 71        first two: Sarasa Mono SC, JetBrainsMono Nerd Font
```

## Suggested fixes (both measured with `fc-match`)

**A — exact, needs a config file ordered before `48-guessfamily.conf`.** A rule evaluated earlier sees `family = ["monospace"]` for a generic request and `["Sarasa Mono SC", …]` for a named one, so keying it on the *first* family value is enough:

```xml
<!-- /etc/fonts/conf.d/47-omarchy-font.conf, rewritten by `omarchy font set` -->
<match target="pattern">
  <test qual="first" name="family" compare="eq">
    <string>monospace</string>
  </test>
  <edit name="family" mode="prepend_first" binding="strong">
    <string>Sarasa Mono SC</string>
  </edit>
</match>
```

Measured with that file symlinked in at position 47, everything else stock:

| query | result |
|---|---|
| `monospace` | Sarasa Mono SC ✅ |
| `Sarasa Mono SC` | Sarasa Mono SC ✅ |
| `JetBrainsMono Nerd Font` | JetBrainsMono Nerd Font ✅ |
| `DejaVu Sans Mono` | DejaVu Sans Mono ✅ |
| `Noto Sans Mono`, `Liberation Mono`, `iA Writer Mono S` | themselves ✅ |
| `:charset=e0b0` (Nerd Font glyph) | JetBrainsMono Nerd Font ✅ |
| `:charset=4e2d` (中) | Sarasa Mono CL ✅ |

Caveat: the rule then lives under `/etc`, so `omarchy font set` would need a privileged write for it (or a package/migration-owned file that it rewrites).

**B — no privilege change.** Keep writing `~/.config/fontconfig/fonts.conf`, but test the first family against the family `50-omarchy.conf` currently assigns (read out of that file at write time, so it survives a changed default):

```xml
<test qual="first" name="family" compare="eq">
  <string>JetBrainsMono Nerd Font</string>   <!-- 50-omarchy.conf's monospace assign -->
</test>
```

Measured: `monospace` → chosen font ✅; `Sarasa Mono SC`, `DejaVu Sans Mono`, `Noto Sans Mono`, `Liberation Mono` → themselves ✅. One residual case stays broken: an explicit request for `JetBrainsMono Nerd Font` is still repointed, since after `50-omarchy.conf`'s `assign` a generic request and that explicit request differ only by a duplicated first family value, which the match language cannot distinguish.

## Workaround in use locally

Option B, regenerated by a `~/.config/omarchy/hooks/font-set.d/` hook so it survives every `omarchy font set`.

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 16:58 UTC