Omahub
← All plugins
C

Veil

by Carasibana

Per-app window transparency: separate focused and unfocused opacity for every app

Security review

No obvious issues detected

Deterministic scan — not a security guarantee

None
Risk level
None
Analyzed commit
a3a8a36
Scanned
1 month ago

No potentially dangerous behavior detected in the analyzed commit.

Automated analysis only — not a security guarantee.

AI advisory review

No obvious issues detected

Language-model assessment · ~deepseek/deepseek-v4-flash-latest — advisory only

None
AI risk level
None
Recommendation
install
Model
~deepseek/deepseek-v4-flash-latest
Analyzed commit
a3a8a36
Reviewed
1 month ago

The plugin is a transparency control tool that writes only to the user's own state and Hyprland config paths, with no network access, credential handling, obfuscation, or destructive operations. The sampled code is defensive and well-bounded, and the deterministic scan found no issues. The manual `require("hypr.veil")` step is clearly documented and user-controlled.

How this check works

This review combines the deterministic scan (the rule-based results above) with an independent look at the plugin's code by a language model. The model reads a trimmed sample of the repository's files, the manifest, and the README, then gives a plain-language risk level and a recommendation: install (no notable danger), review (look closer first), or avoid (clearly dangerous).

It runs on the same analyzed commit as the deterministic scan and is strictly advisory — it is not a security guarantee and never blocks a plugin by itself. A human moderator still reviews plugins before they are listed.

AI advisory only — automated analysis, not a security guarantee.

Install
$ omarchy plugin add https://github.com/Carasibana/omarchy-veil --enable
Appearance #Hyprland #bar #quickshell

Veil

Per-app window transparency for Omarchy. Every app gets its own focused and unfocused opacity, adjustable from a bar widget, the Omarchy menu, or the keyboard — and the settings survive a reboot.

<img src="preview.png" alt="The Veil panel: a focused-app section with Focused and Unfocused sliders, and a defaults section below" width="420">

Why

Hyprland can set per-window opacity, but out of the box on Omarchy you get a static rule in windows.lua and a binary "make this window opaque" toggle on SUPER + BACKSPACE. There's no way to say "Firefox at 85% when I'm in it and 40% when I'm not, but leave my terminal alone" without hand-editing config and reloading.

Veil makes that a slider.

Requirements

  • Omarchy with the Quickshell-based omarchy-shell (bar plugins, omarchy plugin commands)
  • Hyprland 0.55+ — this uses the Lua config format and the set_prop dispatcher that replaced hyprctl setprop
  • jq (already present on Omarchy)

Install

omarchy plugin add https://github.com/Carasibana/omarchy-veil --enable

Pick right when it asks which bar section to use.

Then add one line to the end of ~/.config/hypr/hyprland.lua:

require("hypr.veil")

This is required, not optional. It loads the window rules Veil generates, which is what applies your settings to newly-opened windows and what makes everything survive a reboot. It must come after Omarchy's defaults — the end of the file is correct — because the last matching rule wins.

That's the whole install. The bar widget is fully functional at this point.

Optional: keybinds

Append examples/bindings.lua to ~/.config/hypr/bindings.lua:

Key Action
SUPER + numpad - / + Focused opacity −5% / +5%
SUPER + SHIFT + numpad - / + Unfocused opacity −5% / +5%
SUPER + \ Toggle this app (fully opaque, values remembered)
SUPER + SHIFT + \ Put this app back on the defaults

Numpad +/- are KP_Add / KP_Subtract — distinct keysyms from the top-row MINUS / EQUAL that Omarchy already binds to window resizing, and unaffected by NumLock. Each press shows a brief notification with the new value, since 5% steps are hard to eyeball.

Optional: Omarchy menu rows

Paste examples/omarchy-menu.jsonc into ~/.config/omarchy/extensions/omarchy-menu.jsonc. The file hot-reloads on save. You get Style › Transparency with ✓-marked presets for both sections.

Using it

Click the bar icon for the panel. Right-click it to toggle the current app without opening anything. With the panel open, a toggles the app and d puts it back on defaults. No key is bound to a full reset — that stays on the explicit button, since it is not undoable.

Sliders commit on release rather than on every frame — dragging otherwise regenerates the window rules and reloads Hyprland dozens of times per drag.

The model

Every app has a focused and an unfocused value. An app you haven't touched inherits Defaults. Turning an app off makes it fully opaque in both states while remembering its numbers, so switching it back on resumes where you left off.

Defaults ship at 98/96, the same window opacity Omarchy sets, so installing Veil changes nothing you can see until you move a slider.

The panel targets the window you were last in. The panel is a Wayland layer surface rather than a window, so opening it doesn't steal the target.

CLI

The engine is a plain script; the widget, menu, and keybinds all shell out to it, so no two surfaces can disagree about your settings.

veil app focused set 85          # current app, while focused
veil app unfocused set 40        # current app, while unfocused
veil app focused nudge +5
veil app toggle                  # opaque <-> transparent
veil app reset                   # back to defaults
veil defaults unfocused set 50
veil list                        # * marks inherited values
veil status                      # raw JSON
veil apply                       # re-apply state after a hand edit or a Hyprland restart
veil reset                       # everything back to 98/96

The app subcommands take an optional trailing window class to target something other than the app you are currently in: veil app focused set 90 firefox. (defaults, list, status, apply and reset take no class.)

Put it on your PATH if you want it handy:

ln -s ~/.config/omarchy/plugins/io.github.carasibana.veil/bin/veil ~/.local/bin/veil

Find a window's class with hyprctl clients -j | jq -r '.[].class'.

How it works

State lives in ~/.local/state/veil/opacity.json and is the single source of truth:

{
  "defaults": { "focused": 50, "unfocused": 50 },
  "apps": { "firefox": { "enabled": true, "focused": 85, "unfocused": 40 } }
}

Every change does two things, because Hyprland needs both:

  1. set_prop dispatches against live windows, for instant effect.
  2. Regenerates ~/.config/hypr/veil.lua and reloads, so windows opened later — including everything after a reboot — inherit the current state.

Both are necessary. A set_prop override outranks window rules and is permanent for that window, so once a window has been touched the rules can never reclaim it; live windows must always be set explicitly. Conversely the rules are the only thing that reaches windows that don't exist yet.

Nothing runs at login, and the widget locates the engine relative to its own QML file rather than relying on PATH. The engine itself calls the usual userland tools — jq, hyprctl, notify-send, flock, and a handful of coreutils — from PATH as any script does.

Uninstall

Put everything back to fully opaque first, while veil is still installed:

veil reset
veil defaults focused set 100
veil defaults unfocused set 100

In that order. reset clears the per-app entries but leaves the defaults at 98/96, so raise them afterwards; raising them on their own does nothing for apps that have an entry of their own.

Anything still transparent when the plugin goes stays that way until you close the window or restart Hyprland — a set_prop override lasts the life of the window, and the tool that would undo it is gone.

Then:

omarchy plugin remove io.github.carasibana.veil

Remove require("hypr.veil") from ~/.config/hypr/hyprland.lua, delete ~/.config/hypr/veil.lua, and drop the keybind/menu snippets if you added them. ~/.local/state/veil/ holds your settings — delete it to forget them.

Notes

SUPER + BACKSPACE outranks Veil. That's an Omarchy default bound to omarchy-hyprland-window-transparency-toggle, which sets Hyprland's per-window opaque prop — a hard override that beats any opacity value. If one window seems immune to Veil, check that first.

Transparency is subtler than you'd expect on dark themes. Window alpha blends toward whatever is behind, and if that's a dark wallpaper the shift can be a couple of points out of 255 — real, but nearly invisible. Also, uniform window alpha fades text and background together, so it reads as dim rather than see-through; terminals look genuinely transparent because they alpha only their background and leave glyphs opaque. And if decoration:blur:xray is on in your looknfeel.lua, transparency reveals only the blurred wallpaper, never the window behind. Try around 50% to see the effect clearly, then back off.

Omarchy's opacity opt-outs still hold. The default applies to the same default-opacity tag Omarchy uses, so windows its app files exempt — picture-in-picture, the webcam overlay, Steam, video windows — stay opaque. Giving one of those apps its own value overrides the exemption, which is the point of setting it.

Compatibility

This leans on Omarchy and Hyprland internals that carry no stability promise — the set_prop dispatcher, the o.window() Lua helper, the shell's Ui/ components, and the bar's widget-sizing contract. hyprctl setprop already disappeared once, in Hyprland 0.55. Expect occasional breakage across major Omarchy releases; open an issue and I'll chase it.

Changelog

See CHANGELOG.md.

License

MIT