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-hook runs hooks with bash, ignoring shebang and executable bit — non-bash hook silently hung omarchy-update
Reported by lvkz-okcapsule · filed Aug 31, 2026Closed upstream on 2026-09-21 by bjarneo via an automated message, as a duplicate of #8492 (R-1395). GitHub close reason: completed.
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
What happened
omarchy-update hung indefinitely — no output, no error — right after the post-transaction pacman hooks. The stuck process tree:
omarchy-update
└─ omarchy-hook post-update
└─ bash ~/.config/omarchy/hooks/post-update.d/70-menu-order-check
└─ import json ← ImageMagick's `import`, waiting forever for a screenshot clickThe hook was a Python script with a #!/usr/bin/env python3 shebang. omarchy-hook runs every hook with bash explicitly, so bash interpreted the Python source: the comment lines were harmless, but import json invoked ImageMagick's import(1), which blocks waiting for the user to click a window. The update sat there silently until the process was killed by hand.
Cause
bin/omarchy-hook invokes hooks as bash "$hook" rather than executing the file:
if [[ -d $HOOK_DIR ]]; then
for hook in "$HOOK_DIR"/*; do
[[ -f $hook ]] || continue
[[ $hook == *.sample ]] && continue
bash "$hook" "$@" || echo "Hook failed: $hook"
done
fiThis diverges from the manual (https://omarchy.org/manual/dotfiles/) in two ways:
- Shebangs are ignored. The manual's framing ("every executable file in there runs") and
omarchy hook installcopying the script and marking it executable both suggest a hook is executed as a program, i.e. its shebang is honored. It isn't — everything is fed to bash. - The executable bit isn't checked. The manual says every executable file runs, but the loop runs every non-
.sampleregular file regardless of permissions.
The failure mode is the nasty part: a non-bash hook doesn't fail cleanly, it gets half-interpreted by bash. Depending on what's installed that can silently hang the whole update (any Python hook + ImageMagick reproduces this).
Suggested fix
Execute hooks directly when they're executable, keeping bash as the fallback:
if [[ -x $hook ]]; then
"$hook" "$@" || echo "Hook failed: $hook"
else
bash "$hook" "$@" || echo "Hook failed: $hook"
fi(Same for the single $HOOK_PATH case.)
If the intent is that hooks are bash-only, a line in the manual saying so — and perhaps a warning when a hook's first line isn't a bash shebang — would also resolve this; the silent hang is the real problem.
Reproduce: printf '#!/usr/bin/env python3\nimport json\n' > ~/.config/omarchy/hooks/post-update.d/99-repro; omarchy-hook post-update (with ImageMagick installed) — hangs.
View raw text
## What happened
`omarchy-update` hung indefinitely — no output, no error — right after the post-transaction pacman hooks. The stuck process tree:
```
omarchy-update
└─ omarchy-hook post-update
└─ bash ~/.config/omarchy/hooks/post-update.d/70-menu-order-check
└─ import json ← ImageMagick's `import`, waiting forever for a screenshot click
```
The hook was a Python script with a `#!/usr/bin/env python3` shebang. `omarchy-hook` runs every hook with `bash` explicitly, so bash interpreted the Python source: the comment lines were harmless, but `import json` invoked ImageMagick's `import(1)`, which blocks waiting for the user to click a window. The update sat there silently until the process was killed by hand.
## Cause
`bin/omarchy-hook` invokes hooks as `bash "$hook"` rather than executing the file:
```bash
if [[ -d $HOOK_DIR ]]; then
for hook in "$HOOK_DIR"/*; do
[[ -f $hook ]] || continue
[[ $hook == *.sample ]] && continue
bash "$hook" "$@" || echo "Hook failed: $hook"
done
fi
```
This diverges from the manual (https://omarchy.org/manual/dotfiles/) in two ways:
1. **Shebangs are ignored.** The manual's framing ("every executable file in there runs") and `omarchy hook install` copying the script and marking it executable both suggest a hook is executed as a program, i.e. its shebang is honored. It isn't — everything is fed to bash.
2. **The executable bit isn't checked.** The manual says every *executable* file runs, but the loop runs every non-`.sample` regular file regardless of permissions.
The failure mode is the nasty part: a non-bash hook doesn't fail cleanly, it gets half-interpreted by bash. Depending on what's installed that can silently hang the whole update (any Python hook + ImageMagick reproduces this).
## Suggested fix
Execute hooks directly when they're executable, keeping bash as the fallback:
```bash
if [[ -x $hook ]]; then
"$hook" "$@" || echo "Hook failed: $hook"
else
bash "$hook" "$@" || echo "Hook failed: $hook"
fi
```
(Same for the single `$HOOK_PATH` case.)
If the intent is that hooks are bash-only, a line in the manual saying so — and perhaps a warning when a hook's first line isn't a bash shebang — would also resolve this; the silent hang is the real problem.
Reproduce: `printf '#!/usr/bin/env python3\nimport json\n' > ~/.config/omarchy/hooks/post-update.d/99-repro; omarchy-hook post-update` (with ImageMagick installed) — hangs.
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.