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 every hook via bash, ignoring the shebang — silently hangs on non-bash hooks that collide with a real binary name
Reported by hbabb · filed Aug 27, 2026 · open at source
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
What happened
omarchy-update hung indefinitely at the theme-set step of migration 1787481315 ("Re-stage the current theme..."). Process tree at the time it was stuck:
omarchy-update
└─ omarchy-migrate
└─ migrations/1787481315.sh
└─ omarchy-theme-refresh
└─ omarchy-theme-set ethereal
└─ omarchy-hook theme-set ethereal
└─ bash omarchy-intellij-theme-sync.py ethereal (PID in do_wait — blocked)
└─ import colorsys (PID in poll_schedule_timeou — blocked on X/Wayland input)~/.config/omarchy/hooks/theme-set.d/omarchy-intellij-theme-sync.py is a hook installed by the (third-party, Omarchy-plugin-distributed) fchtngr.intellij-theme-sync plugin. It's a Python 3 script with a correct #!/usr/bin/env python3 shebang and is installed chmod 755 (install -Dm755 ...), so it's directly executable.
Root cause
omarchy-hook invokes every hook unconditionally with bash, ignoring the executable bit and shebang:
# /usr/share/omarchy/bin/omarchy-hook
if [[ -f $HOOK_PATH ]]; then
bash "$HOOK_PATH" "$@" || echo "Hook failed: $HOOK_PATH"
fi
if [[ -d $HOOK_DIR ]]; then
for hook in "$HOOK_DIR"/*; do
[[ -f $hook ]] || continue
[[ $hook == *.sample ]] && continue
bash "$hook" "$@" || echo "Hook failed: $hook"
done
fiWhen bash parses the Python file as shell script, it hits the line:
import colorsysBash treats import as a command name — and /usr/bin/import happens to exist (a magick/ImageMagick symlink, the interactive screen-capture tool). Bash executes import colorsys, which is ImageMagick's import waiting for the user to interactively click a window/region to capture, saving it as a file named colorsys. That process never returns on its own.
Because omarchy-hook, omarchy-theme-set, omarchy-theme-refresh, the migration script, and omarchy-migrate all run synchronously (several with set -e) and wait on their children, the entire omarchy-update blocks indefinitely on this single hook — with no error, timeout, or indication of what it's waiting on.
Even after killing the stray import process, the actual hook logic never runs, since bash aborts by the point Python's real syntax (f-strings, type hints, dict literals, etc.) causes further shell parse errors — so the intended effect of the hook (regenerating the JetBrains theme files) silently doesn't happen.
Why this isn't just a plugin bug
The plugin does everything right: ships a +x Python script with a proper shebang, installed via install -Dm755. omarchy-hook is what discards that by hardcoding bash instead of respecting how the file says it should be run. Any hook that isn't a bash script is subject to this — the ImageMagick collision is what turns this particular file into a silent hang instead of a fast, visible failure, but the underlying dispatch bug applies to any non-bash hook.
Suggested fix
Dispatch based on the hook's executable bit / shebang instead of forcing bash, e.g.:
run_hook() {
local hook=$1; shift
if [[ -x $hook ]]; then
"$hook" "$@"
else
bash "$hook" "$@"
fi
}(falling back to bash only for non-executable plain shell files, to stay backward compatible with any hooks that currently rely on that).
Reproduction
- Install a
theme-set.dhook that is achmod +xscript in a non-bash language with a proper shebang (e.g. Python via thefchtngr.intellij-theme-syncplugin,omarchy plugin install fchtngr.intellij-theme-sync). - Trigger a theme change or run
omarchy-updatefar enough to reach a migration that callsomarchy-theme-refresh/omarchy-theme-set(currently migration1787481315). - Observe the update hang.
ps -eo pid,ppid,stat,wchan,cmd --forestshows abash <hook>.py ...process blocked indo_waitwith a child literally named after the first import in the file (in this caseimport colorsys, resolving to ImageMagick'simport, blocked inpoll_schedule_timeouwaiting for interactive screen-capture input).
Environment
- Omarchy: 4.0.1-1
- Kernel: 7.1.8-arch1-3
- Plugin:
fchtngr.intellij-theme-syncv4.3.0 (installed viaomarchy plugin install)
View raw text
## What happened
`omarchy-update` hung indefinitely at the `theme-set` step of migration `1787481315` ("Re-stage the current theme..."). Process tree at the time it was stuck:
```
omarchy-update
└─ omarchy-migrate
└─ migrations/1787481315.sh
└─ omarchy-theme-refresh
└─ omarchy-theme-set ethereal
└─ omarchy-hook theme-set ethereal
└─ bash omarchy-intellij-theme-sync.py ethereal (PID in do_wait — blocked)
└─ import colorsys (PID in poll_schedule_timeou — blocked on X/Wayland input)
```
`~/.config/omarchy/hooks/theme-set.d/omarchy-intellij-theme-sync.py` is a hook installed by the (third-party, Omarchy-plugin-distributed) `fchtngr.intellij-theme-sync` plugin. It's a Python 3 script with a correct `#!/usr/bin/env python3` shebang and is installed `chmod 755` (`install -Dm755 ...`), so it's directly executable.
## Root cause
`omarchy-hook` invokes every hook unconditionally with `bash`, ignoring the executable bit and shebang:
```bash
# /usr/share/omarchy/bin/omarchy-hook
if [[ -f $HOOK_PATH ]]; then
bash "$HOOK_PATH" "$@" || echo "Hook failed: $HOOK_PATH"
fi
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
```
When `bash` parses the Python file as shell script, it hits the line:
```python
import colorsys
```
Bash treats `import` as a command name — and `/usr/bin/import` happens to exist (a `magick`/ImageMagick symlink, the interactive screen-capture tool). Bash executes `import colorsys`, which is ImageMagick's `import` waiting for the user to interactively click a window/region to capture, saving it as a file named `colorsys`. That process never returns on its own.
Because `omarchy-hook`, `omarchy-theme-set`, `omarchy-theme-refresh`, the migration script, and `omarchy-migrate` all run synchronously (several with `set -e`) and wait on their children, the entire `omarchy-update` blocks indefinitely on this single hook — with no error, timeout, or indication of what it's waiting on.
Even after killing the stray `import` process, the actual hook logic never runs, since bash aborts by the point Python's real syntax (f-strings, type hints, dict literals, etc.) causes further shell parse errors — so the intended effect of the hook (regenerating the JetBrains theme files) silently doesn't happen.
## Why this isn't just a plugin bug
The plugin does everything right: ships a `+x` Python script with a proper shebang, installed via `install -Dm755`. `omarchy-hook` is what discards that by hardcoding `bash` instead of respecting how the file says it should be run. Any hook that isn't a bash script is subject to this — the ImageMagick collision is what turns this particular file into a silent *hang* instead of a fast, visible failure, but the underlying dispatch bug applies to any non-bash hook.
## Suggested fix
Dispatch based on the hook's executable bit / shebang instead of forcing `bash`, e.g.:
```bash
run_hook() {
local hook=$1; shift
if [[ -x $hook ]]; then
"$hook" "$@"
else
bash "$hook" "$@"
fi
}
```
(falling back to `bash` only for non-executable plain shell files, to stay backward compatible with any hooks that currently rely on that).
## Reproduction
1. Install a `theme-set.d` hook that is a `chmod +x` script in a non-bash language with a proper shebang (e.g. Python via the `fchtngr.intellij-theme-sync` plugin, `omarchy plugin install fchtngr.intellij-theme-sync`).
2. Trigger a theme change or run `omarchy-update` far enough to reach a migration that calls `omarchy-theme-refresh`/`omarchy-theme-set` (currently migration `1787481315`).
3. Observe the update hang. `ps -eo pid,ppid,stat,wchan,cmd --forest` shows a `bash <hook>.py ...` process blocked in `do_wait` with a child literally named after the first import in the file (in this case `import colorsys`, resolving to ImageMagick's `import`, blocked in `poll_schedule_timeou` waiting for interactive screen-capture input).
## Environment
- Omarchy: 4.0.1-1
- Kernel: 7.1.8-arch1-3
- Plugin: `fchtngr.intellij-theme-sync` v4.3.0 (installed via `omarchy plugin install`)
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 09:25 UTC