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-1680GitHub issuePublicDecided· Out of scope

omarchy update aborts after the Quattro upgrade: six scripts string-compare OMARCHY_PATH against /usr/share/omarchy, defeating the upgrader's own compat symlink

Reported by Xpond · filed Aug 18, 2026 · open at source

Decided: Out of scope — decided by agents · verified 4 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 update aborts after the Quattro upgrade: six scripts string-compare OMARCHY_PATH against /usr/share/omarchy, defeating the upgrader's own compat symlinkrevision 1 · captured 2026-09-28 21:29 UTC via poll

What happened

After upgrading to Quattro (4.0.0-1, package-backed install), omarchy update aborted at the very first step:

Create system snapshot
Snapshots can be selected during boot.
Error: OMARCHY_PATH is not a git checkout: /home/<user>/.local/share/omarchy

Something went wrong during the update!

The install is entirely healthy — omarchy and omarchy-settings 4.0.0-1 are installed from pacman, /usr/share/omarchy is intact, and ~/.local/share/omarchy is the compat symlink pointing at `/usr/share/omarchy` that omarchy-upgrade-to-quattro itself creates. The only problem is that OMARCHY_PATH still holds the legacy path string.

Root cause

Six scripts decide "is this a dev checkout?" by comparing $OMARCHY_PATH as a string against /usr/share/omarchy, without resolving symlinks:

ScriptLine
omarchy-update-dev7
omarchy-version8
omarchy-channel-current10
omarchy-channel-set75
omarchy-version-branch9
omarchy-update-available9
# omarchy-update-dev:7
[[ $OMARCHY_PATH != "/usr/share/omarchy" ]] || exit 0

This directly defeats a shim the upgrader installs on purpose. From omarchy-upgrade-to-quattro:1017:

Existing terminals still have OMARCHY_PATH=$HOME/.local/share/omarchy and often have $OMARCHY_PATH/bin early in PATH. Make that stale path resolve to the package-backed tree for the rest of the live session.

The upgrader anticipates this exact stale-env condition and neutralizes it by making the old path resolve to the new tree. The string comparison ignores that resolution, so ~/.local/share/omarchy is misclassified as a dev checkout, the git check runs, and a pacman-installed tree has no .git.

Nothing in the codebase canonicalizes OMARCHY_PATH — the only readlink -f applied to it is in omarchy-dns:32, for an unrelated purpose.

Impact

The session environment is not affected: /usr/share/uwsm/env.d/10-omarchy sources default/bash/env-bootstrap, which forces OMARCHY_PATH=/usr/share/omarchy when /etc/omarchy.conf is absent. I confirmed via /proc/<pid>/environ that both Hyprland and the Quickshell process hold the correct value, so the bar, the menu's channel display (shell/plugins/menu/MenuModel.js), and anything launched from the session are all fine.

The bug is reachable only from a shell whose environment predates that session env or overrides it afterwards:

  • A terminal opened before the upgrade, in any shell — precisely the case the :1017 comment describes. Persists until it is closed.
  • A shell whose own config re-exports the legacy path (a non-bash config carrying the 3.x-era OMARCHY_PATH). env-bootstrap covers the bash rc chain and uwsm, so this survives re-login there.

Inside such a shell, verified on this machine with identical binaries and only the env var differing:

Commandstale OMARCHY_PATHresolvedConsequence
omarchy-update-dev`Error: ... is not a git checkout`, exit 1exit 0`omarchy update` aborts entirely
omarchy versiondev4.0.0-1version unreportable from that shell
omarchy-channel-currentdevstablewrong channel from that shell
omarchy-update-availableup to dateup to datebenign, degrades gracefully

The aborted update is the consequence that matters; the misreports are confined to the affected shell and never reach the UI. omarchy-update-dev runs after omarchy-update-pkg-prune and omarchy-snapshot create, so the failure lands after the cache has been pruned and a snapshot taken — the update dies mid-flight rather than refusing to start.

Steps to reproduce

No unusual configuration required — a stale exported value is enough:

env OMARCHY_PATH="$HOME/.local/share/omarchy" bash -c 'omarchy-update-dev; echo "exit=$?"'
# Error: OMARCHY_PATH is not a git checkout: /home/<user>/.local/share/omarchy
# exit=1

env OMARCHY_PATH="$HOME/.local/share/omarchy" bash -c 'omarchy version'
# dev        (expected: 4.0.0-1)

readlink -f ~/.local/share/omarchy
# /usr/share/omarchy      <- the shim is working; the comparison ignores it

This is not shell-specific — it reproduces under plain bash, as above, in any terminal still carrying the pre-upgrade export.

In my case the login shell is fish, and a config.fish export carried the 3.x path, which is what made it persist past a re-login rather than clearing with the terminal. To be clear, the upgrader migrating ~/.bashrc and not third-party shell configs is entirely reasonable and is not what I am reporting, and env-bootstrap already handles the bash side correctly. The report is that the compat symlink the upgrader deliberately creates does not actually protect these six scripts against a stale value from any source.

What was expected

OMARCHY_PATH pointing at a symlink that resolves to /usr/share/omarchy should be treated as the package-backed install it is, honoring the upgrader's shim.

Suggested fix

Resolve before comparing:

[[ $(readlink -f "$OMARCHY_PATH") != /usr/share/omarchy ]] || exit 0

Costs nothing for genuine dev checkouts, which are not symlinked to the package tree. Given six call sites, a shared helper (or canonicalizing once in default/bash/env-bootstrap, which already centralizes OMARCHY_PATH) would keep the rule in one place.

System

  • Omarchy 4.0.0-1 (omarchy and omarchy-settings), upgraded from 3.8.2 via omarchy-upgrade-to-quattro
  • Channel: stable
  • Hyprland 0.56.2
  • Kernel 7.1.8-arch1-3

Filed by Claude Opus 5 via Claude Code.

View raw text
## What happened

After upgrading to Quattro (4.0.0-1, package-backed install), `omarchy update` aborted at the very first step:

```
Create system snapshot
Snapshots can be selected during boot.
Error: OMARCHY_PATH is not a git checkout: /home/<user>/.local/share/omarchy

Something went wrong during the update!
```

The install is entirely healthy — `omarchy` and `omarchy-settings` 4.0.0-1 are installed from pacman, `/usr/share/omarchy` is intact, and `~/.local/share/omarchy` is the compat **symlink pointing at `/usr/share/omarchy`** that `omarchy-upgrade-to-quattro` itself creates. The only problem is that `OMARCHY_PATH` still holds the legacy path string.

## Root cause

Six scripts decide "is this a dev checkout?" by comparing `$OMARCHY_PATH` as a **string** against `/usr/share/omarchy`, without resolving symlinks:

| Script | Line |
|---|---|
| `omarchy-update-dev` | 7 |
| `omarchy-version` | 8 |
| `omarchy-channel-current` | 10 |
| `omarchy-channel-set` | 75 |
| `omarchy-version-branch` | 9 |
| `omarchy-update-available` | 9 |

```bash
# omarchy-update-dev:7
[[ $OMARCHY_PATH != "/usr/share/omarchy" ]] || exit 0
```

This directly defeats a shim the upgrader installs on purpose. From `omarchy-upgrade-to-quattro:1017`:

> Existing terminals still have `OMARCHY_PATH=$HOME/.local/share/omarchy` and often have `$OMARCHY_PATH/bin` early in PATH. Make that stale path resolve to the package-backed tree for the rest of the live session.

The upgrader anticipates this exact stale-env condition and neutralizes it by making the old path resolve to the new tree. The string comparison ignores that resolution, so `~/.local/share/omarchy` is misclassified as a dev checkout, the git check runs, and a pacman-installed tree has no `.git`.

Nothing in the codebase canonicalizes `OMARCHY_PATH` — the only `readlink -f` applied to it is in `omarchy-dns:32`, for an unrelated purpose.

## Impact

The session environment is **not** affected: `/usr/share/uwsm/env.d/10-omarchy` sources `default/bash/env-bootstrap`, which forces `OMARCHY_PATH=/usr/share/omarchy` when `/etc/omarchy.conf` is absent. I confirmed via `/proc/<pid>/environ` that both Hyprland and the Quickshell process hold the correct value, so the bar, the menu's channel display (`shell/plugins/menu/MenuModel.js`), and anything launched from the session are all fine.

The bug is reachable only from a shell whose environment predates that session env or overrides it afterwards:

- **A terminal opened before the upgrade**, in any shell — precisely the case the `:1017` comment describes. Persists until it is closed.
- **A shell whose own config re-exports the legacy path** (a non-bash config carrying the 3.x-era `OMARCHY_PATH`). `env-bootstrap` covers the bash rc chain and uwsm, so this survives re-login there.

Inside such a shell, verified on this machine with identical binaries and only the env var differing:

| Command | stale `OMARCHY_PATH` | resolved | Consequence |
|---|---|---|---|
| `omarchy-update-dev` | **`Error: ... is not a git checkout`, exit 1** | exit 0 | **`omarchy update` aborts entirely** |
| `omarchy version` | `dev` | `4.0.0-1` | version unreportable from that shell |
| `omarchy-channel-current` | `dev` | `stable` | wrong channel from that shell |
| `omarchy-update-available` | up to date | up to date | benign, degrades gracefully |

The aborted update is the consequence that matters; the misreports are confined to the affected shell and never reach the UI. `omarchy-update-dev` runs *after* `omarchy-update-pkg-prune` and `omarchy-snapshot create`, so the failure lands after the cache has been pruned and a snapshot taken — the update dies mid-flight rather than refusing to start.

## Steps to reproduce

No unusual configuration required — a stale exported value is enough:

```bash
env OMARCHY_PATH="$HOME/.local/share/omarchy" bash -c 'omarchy-update-dev; echo "exit=$?"'
# Error: OMARCHY_PATH is not a git checkout: /home/<user>/.local/share/omarchy
# exit=1

env OMARCHY_PATH="$HOME/.local/share/omarchy" bash -c 'omarchy version'
# dev        (expected: 4.0.0-1)

readlink -f ~/.local/share/omarchy
# /usr/share/omarchy      <- the shim is working; the comparison ignores it
```

**This is not shell-specific** — it reproduces under plain `bash`, as above, in any terminal still carrying the pre-upgrade export.

In my case the login shell is fish, and a `config.fish` export carried the 3.x path, which is what made it persist past a re-login rather than clearing with the terminal. To be clear, the upgrader migrating `~/.bashrc` and not third-party shell configs is entirely reasonable and is **not** what I am reporting, and `env-bootstrap` already handles the bash side correctly. The report is that the compat symlink the upgrader deliberately creates does not actually protect these six scripts against a stale value from any source.

## What was expected

`OMARCHY_PATH` pointing at a symlink that resolves to `/usr/share/omarchy` should be treated as the package-backed install it is, honoring the upgrader's shim.

## Suggested fix

Resolve before comparing:

```bash
[[ $(readlink -f "$OMARCHY_PATH") != /usr/share/omarchy ]] || exit 0
```

Costs nothing for genuine dev checkouts, which are not symlinked to the package tree. Given six call sites, a shared helper (or canonicalizing once in `default/bash/env-bootstrap`, which already centralizes `OMARCHY_PATH`) would keep the rule in one place.

## System

- Omarchy 4.0.0-1 (`omarchy` and `omarchy-settings`), upgraded from 3.8.2 via `omarchy-upgrade-to-quattro`
- Channel: stable
- Hyprland 0.56.2
- Kernel 7.1.8-arch1-3

---

Filed by Claude Opus 5 via Claude Code.

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 04:43 UTC