Omahub
← All plugins
W

Plug

by weedwhitesandwine

Manage all your plugins, catch every update, and have AI scan the code BEFORE you update or install.

Security review

No obvious issues detected

Deterministic scan — not a security guarantee

None
Risk level
None
Analyzed commit
993f7c5
Scanned
2 weeks 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

Low
AI risk level
Low
Recommendation
install
Model
~deepseek/deepseek-v4-flash-latest
Analyzed commit
993f7c5
Reviewed
2 weeks ago

The deterministic scan found no issues, and the sampled code is consistent with that: the config-editing helpers are carefully defensive, state stays under ~/.local/state/plug, and the potentially powerful operations are user-triggered. Residual risk is limited to the plugin necessarily running as the user and being able to invoke git, omarchy, hyprctl, and user-chosen AI review tools. No obfuscation, hidden persistence, credential theft, or destructive install behavior was observed.

  • The plugin can edit ~/.config/hypr/bindings.lua and ~/.config/omarchy/shell.json and can run plugin-management commands as the user; this is inherent to the plugin's advertised function.
  • Choosing Claude Code or Opencode may send plugin source code or diffs to external AI services; the README discloses this, but users should understand that remote review is not fully offline.
  • The sampled code includes defensive safeguards around file edits and command execution, but the plugin is still a powerful, user-level tool and not sandboxed.
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/weedwhitesandwine/plug --enable
System #quickshell #ai #security

Plug

Manage all your plugins, catch every update, and have AI scan the code BEFORE you update or install.

Plug

Plugins run as you, with no sandbox. A plugin you install is code you have not read, and an update is more of it. Plug manages your installed community plugins — toggle, remove, browse and install more — and puts the same gate in front of both moments: before a plugin is installed, and before an update is applied, an AI reviewer of your choice reads the actual code and tells you, in plain English, whether it is safe.

What it does

  • Installed — every community plugin you have, each row with the same four controls in the same place: update, restore, remove and an on/off switch. The update control lights green the moment the plugin's repository has moved past what you installed; restore lights up once Plug has applied an update it can undo. Laid out two-up to save space, with a folded Official section for Omarchy's own optional bar widgets — those show just the on/off switch, lined up with the community rows (a built-in is part of Omarchy, not an installed copy, so there is nothing to update or remove).

  • The trust mark on each row — a check, a circle, or an exclamation — is a quick capability read of the plugin's source — what it can reach, run and write — and it is one of three things, never a number:

    • ✅ Green check — squeaky clean. Nothing that leaves the machine, nothing alarming even mentioned, no install step. It keeps to itself.
    • ❗ Red exclamation — read it first. Not a stop sign: a warning that this needs your eyes. Code that actually runs one of: reading private files (.ssh, id_rsa, .gnupg, keyring, /etc/shadow), or hiding itself behind an encoder (atob, eval, a packed line). No listed plugin is expected to be red. If it appears, read the code before anything else.
    • 🟡 Amber circle — the honest middle. It reaches the network, has a setup script that installs or escalates, runs privileged commands (sudo/pkexec) or a package manager, or merely displays any of those for you to copy — the reason on the row says which. A capability held openly is not an accusation; most useful plugins live here.

    The row always says why — "reaches the network", "has a setup script", "shows you commands as root" — and it tells running something apart from merely displaying it for you to copy. Comments are ignored.

  • Review an update — Plug fetches the exact changes, runs a fast offline scan, and hands the diff to your chosen AI reviewer (read-only). You get a safe / be careful / do not verdict, a plain-English summary of what changed, anything to watch for, and the author's own commit notes — then you decide. It also judges the update the way the marketplace's own approval checks do (new privileges, downloads, network hosts, background processes, or writes outside the plugin). The reviewer is told which question it is answering — a first install, or a change to something already installed.

  • Restore — undo the last update you applied, returning the plugin to the version it was on before. Plug then flags the update as available again, so nothing is lost — you can re-apply it whenever you are ready.

  • Store — search the community marketplace, and read a plugin before you install it. Pressing install does not install: Plug clones the plugin to a throwaway directory, scans what it can do, has your reviewer read the whole source, and tells you plainly whether it looks safe — then you decide, with the button reading Install anyway if the answer was no. The copy is deleted either way, and nothing in it is ever run. When you do install, Plug clones the repository again into a private copy, pins that copy to the exact commit you read, and hands the pinned copy to omarchy plugin add — so the code Omarchy validates, loads and switches on is that commit, whatever the repository holds by then. If the author has pushed since, Plug says so before anything lands and lets you choose between the version you read and reading the new one; if the commit you read has been rewritten away, nothing is installed. Double-click a row to open the plugin's own repository page. Omarchy's built-in plugins appear here too, marked OFFICIAL and shown for discovery only.

  • Any repository, listed or not — paste a GitHub address into the Store's search box and Plug offers to read that, exactly the way it reads a catalog entry. Plenty of plugins are never listed — a link in a forum, a friend's repo — and those are the ones that have had the least scrutiny, so they are the ones most worth reading first.

  • Manual installs — adding a plugin only copies its files and enables it; it builds nothing and starts nothing. A plugin that needs packages, a compiled daemon or a service therefore ships a script and expects you to run it, and that script runs as you the moment you start it, before any of the plugin's own code loads. Plug finds that script, reads it, lists what it would do to your machine, and hands you the commands — it will not run it for you. Reviewing code and then executing it is the one thing this plugin exists not to do.

Choosing your reviewer

The reviewer is entirely your choice, set in Settings. Plug offers only the tools you actually have:

  • Claude Code — if the claude command is installed and starts. It is run once, in an empty working directory, in plan mode with no tools at all, and under a throwaway home directory holding only its own Claude settings — the environment it sees carries its own credentials and nothing else your shell or your real home was carrying. It reads the diff it was given and has nothing else to act with.

  • Opencode — if the Opencode program and bwrap (bubblewrap) are both already installed. Opencode keeps its own tools, so it runs inside a sandbox: a read-only system, a home that exists only in memory, and nothing of yours inside it but Opencode itself and its credentials, with editing, shell commands and web fetches denied. Its models are listed from Opencode, free tier first, and the default is a free one — so it costs nothing unless you pick a model that does.

    Plug never installs Opencode, and never downloads anything in order to run a review. Omarchy puts a stand-in named opencode on your PATH that goes and gets the program when you run it, and Plug will not run that: doing so would mean fetching and executing whatever a registry served at that moment, which is code no one has reviewed, from the plugin whose job is to show you code before it runs. It asks mise instead, which reports only what is already installed. If Opencode is installed, it is found and offered — including where the stand-in is shadowing it on your PATH. If it is not, Opencode is absent from the list and Settings says why, with the command that installs it: mise use -g opencode. It is offered from the next shell start.

    Running the stand-in yourself is not enough on every machine. The current one installs through mise, which Plug can find; an older one fetches the package into npm's cache on each run and installs nothing, and a machine carrying that one has no installed Opencode however many times it has been used. mise use -g opencode is the answer in both cases.

  • Local servers — Ollama or LM Studio, if they are running. The review is a request to localhost, so nothing leaves your machine — a real LLM review that is completely private. Their loaded models are listed automatically.

  • Just the offline scan — no AI at all; Plug reports what its own capability scan found. Everything stays local.

Interactive apps such as ChatGPT Desktop or Grok Bot are not offered: they are windows, not something Plug can call for a one-shot review.

Authentication belongs to the reviewer you chose: Plug runs its command, and that command uses the sign-in it already has. With Claude Code, that is the Claude account set up in your terminal; with Opencode, whatever opencode auth login saved, or a provider key already in your environment. If the tool is not signed in, the review falls back to the offline scan.

Privacy. A reviewer that runs somewhere else — Claude Code, or Opencode on a provider model — is sent the code it is asked to judge, and only then: the diff when you review an update, the plugin's full source when you check one before installing it. That code is public and comes from a public repository, but it does leave your machine. A local server (Ollama, LM Studio) or the offline scan keeps everything on it.

Install

omarchy plugin add https://github.com/weedwhitesandwine/plug.git --enable

Open it from the bar icon, or from a terminal:

omarchy-shell shell toggle io.github.weedwhitesandwine.plug

A hotkey is off by default — set one in Settings if you want. Plug checks every shortcut Hyprland is actually using (including Omarchy's own, which are not in bindings.lua) and refuses a combination that is already taken.

Update

omarchy plugin update io.github.weedwhitesandwine.plug --yes

Remove

Hide the bar icon and clear the hotkey in Settings first (that removes Plug's entry from shell.json and its block from bindings.lua), then:

omarchy plugin remove io.github.weedwhitesandwine.plug

Its state is left in ~/.local/state/plug/, which you can delete.

What it runs, reads and writes

Its own state, all inside ~/.local/state/plug/: state.json (git and scan results per plugin), catalog.json (the marketplace catalog, cached), settings.json (your choices), locks.json (restore bookkeeping — which version each applied update came from), review-<plugin-id>.json (the last review of that plugin: the verdict, the summary, and the two commits it was read between, which is what the apply is checked against), and outcome.json (the result of the last job — written when an install, update, restore or removal finishes, shown and deleted the next time Plug opens), and, if you use Opencode, opencode-models.json (its model list, cached so Plug does not ask again on every settings open). A state file an earlier version of Plug wrote and this one does not is removed from that directory on the first run after an upgrade, so this list stays the whole of it.

Outside its own directory — only in response to something you do:

Path When
~/.config/hypr/bindings.lua only when you set or clear a hotkey, and only Plug's own marked block, between -- >>> plug hotkey and -- <<< plug hotkey, along with the blank line it writes above that block. Resolved the same way if it is a dotfiles symlink
~/.config/omarchy/shell.json only when you show or hide the bar icon. It adds, moves or removes its own {"id": …} entry and leaves every other setting as it found it, though the file is rewritten as standard JSON with two-space indentation. Where a dotfiles manager has symlinked this path into its own repository, the link is resolved and the real file written, so the link survives

Both files are edited through a descriptor held open on the target's parent directory for the whole edit: the directory is opened one component at a time, refusing a symlink at any of them, and the read, the staging and the rename are all made through that descriptor rather than by name again. It is checked once more immediately before the rename, and the edit is refused if the path no longer leads to it. Bytes that are not valid UTF-8 are carried through bindings.lua unchanged. | a plugin's own checkout under ~/.config/omarchy/plugins/… | git fetch against every installed plugin's remote each time the panel opens (the update check, which you can turn off with autoCheck) and each time you press Check for updates; and, for the one plugin you act on, a fast-forward when you update it or a reset when you restore it | | a temporary directory | three things, all deleted afterwards: a shallow clone of a plugin you asked Plug to check before installing; when you install, a clone of that repository's default branch pinned to the commit you read, which is what omarchy plugin add copies from; and — when you review an update — a copy of the incoming version's files extracted from the plugin's own repository, so the reviewer reads the new code rather than only the diff |

Commands it runs: python3 (Plug's own engine, plugd.py — every job goes through it); omarchy-shell shell listPlugins / listShellConfig / setPluginEnabled (read the list and your shell config; enable/disable on your click); head, which every command's output is piped through so nothing oversized is ever held; omarchy-hyprland-session-locked, asked before a restart so one never happens over a lock screen; omarchy-restart-shell (only after you apply an update or a restore — see below — and never while the screen is locked) with omarchy-shell shell ping / summon to bring Plug back afterwards; omarchy plugin add / remove (install/uninstall on your click); git inside each plugin's checkout (read its state, fetch updates, show the diff, apply or revert); hyprctl binds (read active shortcuts) and hyprctl reload (after a hotkey change); bash (Plug's own plug-ctl.sh, which holds the two consent edits: the hotkey block and the bar-icon entry, both made by plug-edit.py beside it); wl-copy (only when you press Copy the commands on a manual install, with the commands passed as an argument rather than through a shell); xdg-open (only when you open a plugin's repository page); and the AI reviewer you chose — the claude command, the opencode command inside a bwrap sandbox, or a request to a local server on localhost; and mise which <name>, where a reviewer's command on your PATH is a shim or a stand-in rather than the program itself. That one is asked with mise's auto_install turned off, so it reports a tool that is installed and fails for one that is not.

One Opencode command runs outside the sandbox: models, to list what it can run, at most once a day. It is run as the resolved program on your disk, never through a wrapper that would fetch anything to answer.

What runs when the shell starts. Plug builds its reviewer list once, as the shell loads it. That run does four things: it looks for claude and opencode on your PATH, running mise which for the real program wherever what it finds is a mise shim or a stand-in that would go and get the program — which applies to every reviewer, not only Opencode, and means a stand-in is never run to find out what it is; it starts each one it found, once, with --version — under the same throwaway home, or inside the same sandbox, that a review would use, so a reviewer is offered only when it has been seen to run; an HTTP request to localhost:11434 and localhost:1234 to see whether Ollama or LM Studio is listening; and, if Opencode's own program is installed and its saved model list is more than a day old, that program's models command to refresh it. The list is then read from disk until it ages out again, and a listing that fails is not retried for ten minutes.

The two local-server requests go to the loopback interface and ask one question each — whether a local server is there. Every program in that run is one already installed on your machine.

hyprctl binds also runs at startup, to know which key combinations Hyprland has already taken. Everything the reviewer list needs is gathered in that one run, and it is the same list every time you open Settings afterwards.

Network: each installed plugin's git remote, to check for and fetch updates; the repository of a store plugin you ask Plug to check before installing; the marketplace catalog on raw.githubusercontent.com; when you review an update with Claude Code, Anthropic — never otherwise. A local-server reviewer stays on localhost.

When the catalog is fetched. Starting the shell never fetches it — Plug reads the saved copy from disk and stops there. A fetch happens when you open the Store and the saved copy is more than six hours old, or when you press the refresh control beside the search box. There is no timer. Set autoCatalog to false in settings.json to leave it to the refresh control alone. A fetch that fails changes nothing: the saved copy is written only on success, so the Store keeps working offline and says which copy you are looking at.

Restarting the shell. Applying an update or a restore ends with a shell restart, because that is what makes changed plugin code take effect. Your windows and workspaces are untouched; the bar and the panels reload. Nothing else Plug does restarts anything.

Timers and background work: none that runs on its own. The jobs you start — install, remove, update, restore, on/off — outlive Plug's own window, since the reload that finishes them also closes it. Each writes its result to outcome.json and reopens Plug, which shows the note and deletes it.

Everything runs as your own user.

Handling untrusted input

A plugin's repository, the marketplace catalog, the update diff and the source of a plugin you are considering all come from outside, and Plug runs inside a shell process that stays up for days, so all of it is treated as data:

  • Every file Plug reads is read to a size ceiling, following a symlink only to a real regular file, so an oversized or redirected file cannot be pulled whole into the shell or hang it.
  • Every file Plug writes is staged under an exclusively-created name in a directory it has verified it owns, then renamed into place, so a symlink left at one of those names is never written through.
  • A hotkey is validated against a fixed shape in both the settings view and the helper script, and refused rather than escaped, because it becomes Lua source in bindings.lua.
  • The AI reviewer is handed the code as data, never as instructions, in an empty working directory with an environment trimmed to its own credentials. Claude Code runs with no tools at all. A reviewer that keeps its tools runs in a bubblewrap sandbox — read-only system, a home that exists only in memory, nothing of yours inside it but the reviewer's own program and credentials, editing and shell commands and web fetches denied — and is not offered if that sandbox cannot be built.
  • The reviewer is told that comments in what it reads were written by whoever wrote the code, so a payload labelled "harmless test fixture" is judged by what it does.
  • git runs against each untrusted checkout with the repository's own hooks and config disabled, so inspecting a plugin can never run code from it.
  • A repository address is checked against a plain https shape before git is ever pointed at it, and passed as an argument rather than through a shell, so a catalog entry cannot name a local path or another protocol.
  • A plugin you ask Plug to check before installing is cloned shallow into a throwaway directory, read, and deleted — whether the check succeeds or not. Nothing in it is executed at any point.
  • An install is bound to the commit that was read, not to the repository address: the staging clone is reset to that commit and its HEAD compared before omarchy plugin add reads it, the installed checkout's HEAD is compared again afterwards and removed on a mismatch, and a commit that is no longer in the repository is refused. The repository's current HEAD is never checked out into the plugins directory.
  • Source files are picked by what they are, not what they are called: a script with no extension is opened far enough to read its shebang, since the file that does the most to your machine is often named plainly setup.

Maintenance

If Plug says the catalog is bigger than it accepts. The marketplace catalog is one file that grows as plugins are listed, and Plug refuses one over a set size so a runaway download cannot be held in memory. That size is a single line near the top of plugd.py:

MAX_REGISTRY_BYTES = 32 * 1024 * 1024

Change 32 to 64 and save; your next refresh in the Store uses it. Raise it a step at a time — it is a ceiling on what is held in memory at once. Updating Plug replaces plugd.py, so the edit goes with it.

Dependencies

git, python3, bash and hyprctl, all of which Omarchy already provides. An AI reviewer is optional — without one, Plug uses its offline scan. The Opencode reviewer additionally needs bwrap (the bubblewrap package) for the sandbox it runs in, and Opencode itself installed on the machine (mise use -g opencode). It is simply not offered without both, and Settings says which one is missing.

Licence

MIT — see LICENSE.

Credits

Opencode support was contributed by miguepollo.

Built with Claude Code.