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

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

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-hook runs every hook via bash, ignoring the shebang — silently hangs on non-bash hooks that collide with a real binary namerevision 1 · captured 2026-09-28 21:24 UTC via poll

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
fi

When bash parses the Python file as shell script, it hits the line:

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.:

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)
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