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

omarchy-mise-install wrappers exec-loop forever when mise shims are on PATH after ~/.local/bin

Reported by xreed88 · filed Sep 23, 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-mise-install wrappers exec-loop forever when mise shims are on PATH after ~/.local/binrevision 1 · captured 2026-09-28 21:23 UTC via poll

System details

Intel i9-9880H, Intel UHD 630 + NVIDIA Quadro T2000 Mobile, Omarchy 4.0.4-1, mise-bin 2026.9.12-1

What's wrong?

A wrapper generated by omarchy-mise-install can call itself forever. It never exits, and it pins a CPU core by running mise use -g about twice a second in the same PID. On my machine a background service's claude --version ran for 19 hours this way before I noticed the fans.

Cause. The generated wrapper ends with:

exec mise x "<package>" -- "<bin>" "$@"

mise x is expected to put the tool's install dir first in PATH, so <bin> resolves to the real binary. But when mise's shims dir is also on PATH, mise x leaves the PATH order as it is. If ~/.local/bin comes first, <bin> resolves back to the wrapper, which execs itself in the same PID, runs mise use -g again, and repeats with no end.

Login shells don't hit this, because mise activate puts the install dirs first. It does hit processes that get a PATH snapshot with ~/.local/bin early and the shims later. The case I hit was a systemd user unit whose Environment=PATH= was captured at install time.

Steps to reproduce

M=$HOME/.local/share/mise
PATH="$HOME/.local/bin:$(dirname "$(mise which codex)"):$M/shims:/usr/bin" \
  timeout 5 codex --version; echo "rc=$?"    # rc=124 (hangs)

# The same PATH without the shims dir works:
PATH="$HOME/.local/bin:$(dirname "$(mise which codex)"):/usr/bin" \
  timeout 5 codex --version; echo "rc=$?"    # rc=0

Of my installed wrappers, claude, codex, gh, grok and opencode loop under that kind of PATH.

Suggested fix. Resolve the binary to an absolute path before exec, so the wrapper can never find itself. In the omarchy-mise-install heredoc:

mise use -g --quiet $package_arg || exit 1
bin_path=\$(mise which --tool $package_arg $bin_arg) || exit 1
exec mise x $package_arg -- "\$bin_path" "\$@"

I tested this with codex under the looping PATH above: it prints the version and exits 0. The existing migrations that recognize the wrapper format would need to learn the new form. Optional hardening: exit if bin_path is the wrapper itself ([ "$bin_path" -ef "$0" ]), so a future resolution bug fails fast instead of spinning.

View raw text
### System details

Intel i9-9880H, Intel UHD 630 + NVIDIA Quadro T2000 Mobile, Omarchy 4.0.4-1, mise-bin 2026.9.12-1

### What's wrong?

A wrapper generated by `omarchy-mise-install` can call itself forever. It never exits, and it pins a CPU core by running `mise use -g` about twice a second in the same PID. On my machine a background service's `claude --version` ran for 19 hours this way before I noticed the fans.

**Cause.** The generated wrapper ends with:

```bash
exec mise x "<package>" -- "<bin>" "$@"
```

`mise x` is expected to put the tool's install dir first in `PATH`, so `<bin>` resolves to the real binary. But when mise's **shims** dir is also on `PATH`, `mise x` leaves the `PATH` order as it is. If `~/.local/bin` comes first, `<bin>` resolves back to the wrapper, which execs itself in the same PID, runs `mise use -g` again, and repeats with no end.

Login shells don't hit this, because `mise activate` puts the install dirs first. It does hit processes that get a `PATH` snapshot with `~/.local/bin` early and the shims later. The case I hit was a systemd user unit whose `Environment=PATH=` was captured at install time.

**Steps to reproduce**

```bash
M=$HOME/.local/share/mise
PATH="$HOME/.local/bin:$(dirname "$(mise which codex)"):$M/shims:/usr/bin" \
  timeout 5 codex --version; echo "rc=$?"    # rc=124 (hangs)

# The same PATH without the shims dir works:
PATH="$HOME/.local/bin:$(dirname "$(mise which codex)"):/usr/bin" \
  timeout 5 codex --version; echo "rc=$?"    # rc=0
```

Of my installed wrappers, `claude`, `codex`, `gh`, `grok` and `opencode` loop under that kind of `PATH`.

**Suggested fix.** Resolve the binary to an absolute path before exec, so the wrapper can never find itself. In the `omarchy-mise-install` heredoc:

```bash
mise use -g --quiet $package_arg || exit 1
bin_path=\$(mise which --tool $package_arg $bin_arg) || exit 1
exec mise x $package_arg -- "\$bin_path" "\$@"
```

I tested this with `codex` under the looping `PATH` above: it prints the version and exits 0. The existing migrations that recognize the wrapper format would need to learn the new form. Optional hardening: exit if `bin_path` is the wrapper itself (`[ "$bin_path" -ef "$0" ]`), so a future resolution bug fails fast instead of spinning.

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 17:39 UTC