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-4740GitHub issuePublicReceived

omarchy-mise-install generates wrappers that recurse through PATH and hang

Reported by LukeSkypewalker · filed Aug 29, 2026Closed upstream on 2026-09-21 by bjarneo via an automated message, as a duplicate of #7234 (R-1732). GitHub close reason: completed.

Received and recorded verbatim. Nothing has been checked yet.

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?
Not yet mapped to any requirement or component.
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?
Our staff decide whether the report is valid. Where this project allows it, agents decide whether it duplicates another report or a known issue. No decision has been recorded yet.

Original report

omarchy-mise-install generates wrappers that recurse through PATH and hangrevision 1 · captured 2026-10-04 12:03 UTC via poll

omarchy-mise-install generates wrappers whose final line re-resolves the tool
by bare name through PATH. Since the wrapper itself lives in
~/.local/bin, which comes first on PATH, that lookup finds the wrapper
again and mise x re-execs it. The result is unbounded recursion: the command
never returns.

Migration 1784909971.sh — *"Regenerate mise wrappers to stop them recursing
through PATH"* — was clearly written for this bug, but the replacement it
installs still recurses. It swapped a direct self-exec for the same loop with
mise x in the middle.

Reproduce

Non-destructive, using a throwaway command name:

omarchy-mise-install gh reprogh
reprogh --version          # never returns

The generated wrapper:

#!/bin/bash
export MISE_MINIMUM_RELEASE_AGE=0
mise use -g --quiet "gh" || exit 1
exec mise x "gh" -- "reprogh" "$@"

reprogh is not a binary in the gh package at all, so mise x can only
resolve it through PATH — and PATH returns the wrapper.

Evidence

MISE_DEBUG=1 mise x gh -- gh --version prints the same line until killed:

DEBUG ARGS: mise x gh -- gh --version
DEBUG config: ~/.config/mise/config.toml
DEBUG ARGS: mise x gh -- gh --version
DEBUG config: ~/.config/mise/config.toml
...

mise env gh shows why mise x cannot escape it — mise prepends the tool
directory, but cannot get ahead of an entry that was already first:

1: ~/.local/bin                                              <- wrapper found here
...
5: ~/.local/share/mise/installs/gh/latest/gh_.../bin          <- real binary

mise use -g --quiet gh on its own exits 0. The real binary runs instantly.
There is no github.credential_command in ~/.config/mise/config.toml, so
this is not mise's known github-credential shim recursion.

It is not specific to tools whose install dir is on PATH: omp hangs
identically and its mise install directory is not on PATH at all. mise x is
not exec'ing the package's binary — it is exec'ing whatever PATH resolves.

Impact

Every tool installed this way: codex, claude, crush, gh, copilot,
opencode, pi, omp, grok, ghui.

It is easy to misread as a network problem, because git calls the credential
helper twice — once before the transfer and once after. On this machine the
push itself succeeded and only the trailing store callback wedged, so
pushes appeared to hang for minutes and time out while the refs had in fact
already landed on the remote.

Suggested fix

Resolve to an absolute path before handing it to mise x, so there is no name
left for PATH to re-resolve. Keeping mise x preserves the tool environment:

 cat >"$HOME/.local/bin/$command" <<EOF
 #!/bin/bash
 export MISE_MINIMUM_RELEASE_AGE=0
 mise use -g --quiet "$package" || exit 1
-exec mise x "$package" -- "$bin" "\$@"
+b="\$(mise which "$bin")" || exit 1
+[ -x "\$b" ] || { printf '%s: not executable: %s\n' "$command" "\$b" >&2; exit 1; }
+exec mise x "$package" -- "\$b" "\$@"
 EOF

Verified locally on gh, grok and codex: all three return immediately, and
a git push using credential.helper='!gh auth git-credential' went from
timing out at several minutes to 0.81 s.

Note that migration 1784909971.sh will not repair existing wrappers — its
sed patterns match neither the current generated form nor the patched one, so
it is already inert. Tools are re-broken by install/user/mise.sh and by
migrations/1785617047.sh / 1785846769.sh, which call omarchy-mise-install
by name.

System

  • Omarchy 4.0.1-1
  • mise 2026.8.11 linux-x64 (2026-08-23)
  • gh 2.98.0
  • Kernel 7.1.9-arch1-2, Intel Core i9-10850K

(omarchy debug is not a command in 4.0.1-1 — omarchy commands --all lists no
debug entry — so the details above are gathered by hand.)

View raw text
`omarchy-mise-install` generates wrappers whose final line re-resolves the tool
by **bare name** through `PATH`. Since the wrapper itself lives in
`~/.local/bin`, which comes first on `PATH`, that lookup finds the wrapper
again and `mise x` re-execs it. The result is unbounded recursion: the command
never returns.

Migration `1784909971.sh` — *"Regenerate mise wrappers to stop them recursing
through PATH"* — was clearly written for this bug, but the replacement it
installs still recurses. It swapped a direct self-`exec` for the same loop with
`mise x` in the middle.

## Reproduce

Non-destructive, using a throwaway command name:

```bash
omarchy-mise-install gh reprogh
reprogh --version          # never returns
```

The generated wrapper:

```bash
#!/bin/bash
export MISE_MINIMUM_RELEASE_AGE=0
mise use -g --quiet "gh" || exit 1
exec mise x "gh" -- "reprogh" "$@"
```

`reprogh` is not a binary in the `gh` package at all, so `mise x` can only
resolve it through `PATH` — and `PATH` returns the wrapper.

## Evidence

`MISE_DEBUG=1 mise x gh -- gh --version` prints the same line until killed:

```
DEBUG ARGS: mise x gh -- gh --version
DEBUG config: ~/.config/mise/config.toml
DEBUG ARGS: mise x gh -- gh --version
DEBUG config: ~/.config/mise/config.toml
...
```

`mise env gh` shows why `mise x` cannot escape it — mise prepends the tool
directory, but cannot get ahead of an entry that was already first:

```
1: ~/.local/bin                                              <- wrapper found here
...
5: ~/.local/share/mise/installs/gh/latest/gh_.../bin          <- real binary
```

`mise use -g --quiet gh` on its own exits 0. The real binary runs instantly.
There is no `github.credential_command` in `~/.config/mise/config.toml`, so
this is not mise's known github-credential shim recursion.

It is not specific to tools whose install dir is on `PATH`: `omp` hangs
identically and its mise install directory is not on `PATH` at all. `mise x` is
not exec'ing the package's binary — it is exec'ing whatever `PATH` resolves.

## Impact

Every tool installed this way: `codex`, `claude`, `crush`, `gh`, `copilot`,
`opencode`, `pi`, `omp`, `grok`, `ghui`.

It is easy to misread as a network problem, because `git` calls the credential
helper twice — once before the transfer and once after. On this machine the
push itself **succeeded** and only the trailing `store` callback wedged, so
pushes appeared to hang for minutes and time out while the refs had in fact
already landed on the remote.

## Suggested fix

Resolve to an absolute path before handing it to `mise x`, so there is no name
left for `PATH` to re-resolve. Keeping `mise x` preserves the tool environment:

```diff
 cat >"$HOME/.local/bin/$command" <<EOF
 #!/bin/bash
 export MISE_MINIMUM_RELEASE_AGE=0
 mise use -g --quiet "$package" || exit 1
-exec mise x "$package" -- "$bin" "\$@"
+b="\$(mise which "$bin")" || exit 1
+[ -x "\$b" ] || { printf '%s: not executable: %s\n' "$command" "\$b" >&2; exit 1; }
+exec mise x "$package" -- "\$b" "\$@"
 EOF
```

Verified locally on `gh`, `grok` and `codex`: all three return immediately, and
a `git push` using `credential.helper='!gh auth git-credential'` went from
timing out at several minutes to **0.81 s**.

Note that migration `1784909971.sh` will not repair existing wrappers — its
`sed` patterns match neither the current generated form nor the patched one, so
it is already inert. Tools are re-broken by `install/user/mise.sh` and by
`migrations/1785617047.sh` / `1785846769.sh`, which call `omarchy-mise-install`
by name.

## System

- Omarchy 4.0.1-1
- mise 2026.8.11 linux-x64 (2026-08-23)
- gh 2.98.0
- Kernel 7.1.9-arch1-2, Intel Core i9-10850K

(`omarchy debug` is not a command in 4.0.1-1 — `omarchy commands --all` lists no
debug entry — so the details above are gathered by hand.)

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.

No decision has been recorded yet.