Omahub
← All plugins
Y

Blip

by Yogesh Ojha

Selection-aware actions for Omarchy: decode, format, convert, paste back.

Security review

Review recommended · 8 findings

Deterministic scan — not a security guarantee

Medium
Risk level
Medium
Analyzed commit
bd31c61
Scanned
1 week ago
  • medium external_hosts scripts/whois.sh:25

    Downloads or connects to an external HTTP(S) host.

    curl -sf -m 6 "https://ipinfo.io/${ip}/json") || {
  • Command runs with sudo, elevating the process beyond the plugin environment.

    sudo pacman -S --needed curl" >&2
  • medium sudo scripts/qr.sh:8

    Command runs with sudo, elevating the process beyond the plugin environment.

    sudo pacman -S --needed qrencode" >&2
  • Docs external_hosts README.md:167

    Downloads or connects to an external HTTP(S) host.

    git clone https://github.com/…/blip-pack-… ~/.config/omarchy/blip/packs/devtools
  • Docs external_hosts README.md:250

    Downloads or connects to an external HTTP(S) host.

    git clone https://github.com/yogeshojha/blip.git && cd blip
  • Docs external_hosts ACTIONS.md:78

    Downloads or connects to an external HTTP(S) host.

    curl -sf -m 6 "https://ipinfo.io/${ip}/json" | jq -r \
  • Docs external_hosts ACTIONS.md:232

    Downloads or connects to an external HTTP(S) host.

    git clone https://github.com/someone/blip-pack-devtools ~/.config/omarchy/blip/packs/devtools
  • Docs sudo README.md:37

    Command runs with sudo, elevating the process beyond the plugin environment.

    sudo pacman -S --needed wl-clipboard wtype qrencode jq inotify-tools

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
bd31c61
Reviewed
1 week ago

Blip is a legitimate selection-action bar plugin. The deterministic scan's medium findings stem from documentation (README install commands with sudo) and an opt-in network action (whois.sh calling ipinfo.io) that is disabled by default and requires explicit user consent before sending data. The plugin code itself is clean, with no obfuscation, hidden persistence, or destructive behavior.

  • The whois.sh script sends the selected IP to ipinfo.io, but this action is network-gated (default off) and asks for consent before the first send.
  • The 'Run' action executes the selected text as a shell command, but it requires explicit confirmation and is user-initiated.
  • The README suggests installing dependencies with sudo, but this is documentation only and not executed by the plugin.
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/yogeshojha/blip --enable
System #bar

Blip

Select text anywhere in Omarchy and a small themed bar appears over it with the actions that fit what you selected. It works in a terminal, a browser, an editor, a chat window.

Blip over a JWT in a terminal

Basic Usage

https://github.com/user-attachments/assets/501127b1-cdcd-454e-abed-d953d2d8a6c7

A URL gets Open and QR. A JWT gets Decode with the expiry flagged. Minified JSON gets Format. A file path gets Open, Edit, Reveal, Terminal here. Anything at all gets Search, GitHub and Ask agent, with Copy behind them.

Some selections are answered on the bar itself, before you press anything. A Unix timestamp shows its local time, 23*4+18 shows = 110, #1e88e5 shows rgb(30, 136, 229) next to a live swatch, 100 mi shows → 160.93 km. Click the answer, or press =, to copy it.

The transforms write back. Select helloWorld in your editor, pick snake_case, press Enter, and the buffer now reads hello_world: the result pastes over the selection in the app it came from. Formatted JSON lands back in the file it was minified in, decoded base64 lands where the blob was. c copies instead, Esc walks away, and the result is on the clipboard either way, so a window that cannot take the paste costs you nothing.

Blip is not just an extension for Omarchy. It is an ecosystem of its own. Every action on the bar is a small file, the ones that ship are written exactly the way yours would be, and anyone can build their own and share them.

Install

omarchy plugin add https://github.com/yogeshojha/blip.git --enable --yes
sudo pacman -S --needed wl-clipboard wtype qrencode jq inotify-tools

A keybind, in ~/.config/hypr/bindings.lua:

o.bind("SUPER + ALT + B", "Blip", "omarchy-shell blip trigger")

One key does three things: shows the bar for the current selection, hands it the keyboard if it is already up, closes it if it already has the keyboard.

Use

Select something. The bar fades in just above the pointer, flips below it when there is no room, and never takes focus. Move the pointer well away and it closes; leave it alone and it fades after a few seconds. Click elsewhere and it closes. Right-click and it is gone before the app's own menu is up — the click passes straight through to the app.

Key
a letter on a chip run that action
← → move
↑ ↓ dismiss — in the overflow, move
Enter run the highlighted action
= copy the instant answer, when there is one
Tab show everything, including the overflow
Esc back out one level, then close

Only the letters printed on the chips are taken — and Enter, once ← → have highlighted something. Every other key dismisses the bar and lands in the window you selected in, so ↑ still reaches your shell history, Enter still sends your message, and typing carries on where it was going.

Every action for a plain sentence

In a result (a decoded token, a formatted document, a QR code), Enter copies and Esc closes. When the result rewrites the selection — a case change, formatted JSON, a decode — the card shows the result with Replace and Copy: Enter pastes it back over the text you selected, c copies it instead. A stray Space only ever copies; nothing rewrites your text but a deliberate Enter or a click on Replace.

What ships

Selection Actions
anything Search · GitHub · Ask agent · Copy · Run
url Open · QR
email Mail · QR
ip Whois
jwt Decode, expiry flagged
json Format · Minify
base64 / hex / percent-encoded Decode
epoch Local time
path Open · Edit · Reveal · Terminal here
text Count · UPPER · lower · Title · snake_case · kebab-case · camelCase · To base64 · Percent-encode

Run asks before it runs anything. Whois stays hidden until you allow network actions.

Detection validates rather than guesses: Decode appears only on a JWT whose header and payload really parse, and/or and 24/7 are not paths, a clock is not an IPv6 address, prose that mentions an error is not an error, and a lowercase word that happens to decode is not base64.

A decoded token with its expiry flagged

Add your own

Blip's own actions get no special treatment. They are JSONC files in the same format, read from the same kind of folder, and anything you write beats them. Reuse an id to replace one, or switch it off entirely.

Drop a .jsonc in ~/.config/omarchy/blip/actions/. No code, no restart.

{
  "id": "acme.jira",
  "label": "Ticket",
  "icon": "󰠮",
  "when": { "matches": "^[A-Z]{2,10}-[0-9]+$" },
  "run": { "exec": ["xdg-open", "https://jira.acme.com/browse/${text}"] }
}

An action can open a url, run a script over the selection, or call another plugin over IPC and show whatever comes back.

What ships covers what everyone needs. What makes Blip yours is the file only you would write.

Say you look up domains all day. Blip's Whois fires on an IP only — a bare hostname is plain text to it. So write your own:

{
  "id": "me.whois",
  "label": "Whois",
  "network": true,
  "host": "the domain's registry",
  "when": {
    "notTypes": ["ip", "url", "email"],
    "matches": "^[a-zA-Z0-9-]+(\\.[a-zA-Z0-9-]+)+$",
    "notMatches": "\\.(rs|js|ts|py|go|sh|md|json|toml|lock|css|html?)$"
  },
  "run": { "script": "whois-domain.sh" },
  "output": "show"
}
#!/bin/bash
domain=$(head -c 253 | tr -d '[:space:]')
whois "$domain" | head -40

That notMatches earns its place: main.rs and package.json look exactly like domains until you say they are not.

The rest is the same shape with a different day job. A pod name goes to kubectl describe, a git SHA opens the commit on your host, a customer id opens the account in your admin panel. Select it, press one letter, read the answer without leaving the window.

Bundle a few into a folder and you have a pack, publishable anywhere. You clone it into packs/ yourself, and it loads the moment it lands.

git clone https://github.com/…/blip-pack-… ~/.config/omarchy/blip/packs/devtools

A pack's scripts run as you, so read them first.

A pack can teach Blip to spot things it has never heard of. A regex is enough to turn a bare hostname, a ticket id or an order number into something the bar answers.

ACTIONS.md is the full reference.

Search

Search opens DuckDuckGo by default. The control panel offers Google, Brave and Kagi, or takes a url of your own with %s where the selection goes:

https://lobste.rs/search?q=%s

Blip's own ${enc} works there in place of %s, as do ${text} and ${type}, so a custom search can key off what was detected. A url with no placeholder is refused; Search falls back to DuckDuckGo.

GitHub sits beside it on g and goes straight to GitHub code search, which wants you signed in.

Control panel

The control panel with the Core module open

Click the bar icon and the whole panel fits in one view: the armed switch, the behaviour toggles, the search engine, and a row per module. A module opens into a grid of chips — the same chips the bar shows — and clicking one turns that action off or on, so you can drop the text tools, or just Run, without touching a file; the module's switch, or Space, flips them all at once. Packs list in their own fold, Enter opens a pack's folder and x removes it after asking — see ACTIONS.md — and the sliders sit folded under Fine-tuning, values readable on the closed row. ↑↓ move, ←→ fold and unfold, Enter selects. Right-click the icon to arm and disarm without opening it; middle-click shows the bar for the current selection. A keybind opens it too: omarchy-shell blip-panel toggle.

Setup > Plugins > Blip holds the same settings. Hide the icon with the Show the bar icon setting rather than by removing the widget from the bar: the entry in shell.json is what keeps the plugin enabled.

Remove

omarchy plugin remove io.github.yogeshojha.blip

That takes the plugin and its bar entry. Your actions, your packs and what you allowed live in ~/.config/omarchy/blip/; delete that too if you want nothing left behind.

Privacy

  • Selections are never written to disk and never logged. They go from wl-paste into the shell's memory and no further.
  • Nothing is sent anywhere by default. An action that transmits the selection must declare network: true. Those stay hidden until you allow network actions, and Blip asks before the first send, naming the action and the host. omarchy-shell blip forget clears what you allowed. Handing the selection to an app you can see, such as your browser or your agent, is not gated.
  • Packs are folders you put under ~/.config/omarchy/blip/packs/ yourself. Blip reads what is there and never downloads or updates one.
  • Scripts and the clipboard get the selection on stdin. exec actions expand it into their argv, where it is visible in the process table while the command runs.
  • Password managers are skipped by window class and title, and so is any selection a client marks sensitive.
  • Screen sharing disarms Blip. No bar appears over a recording or a call.
  • Blip binds keys in Hyprland while the bar is up, so an unfocused surface can still hear them, and right-click for as long as it is armed. Every bind passes the press through to the window underneath, and all of them go when you disarm, disable, or remove Blip.

Development

git clone https://github.com/yogeshojha/blip.git && cd blip
node test/run.js
omarchy plugin validate .

Detect.js, Actions.js, and Transforms.js are pure, with no QML and no IO. Service.qml watches and orchestrates, Popup.qml is the layer-shell surface, Runner.qml executes, BarWidget.qml is the indicator and the control panel.

To run a working copy:

rsync -a --delete --exclude .git --exclude test . ~/.config/omarchy/plugins/io.github.yogeshojha.blip/
omarchy-restart-shell

QML changes need that restart. Action files under ~/.config/omarchy/blip/ do not; they reload as you save. Logs are journalctl -t omarchy-shell -f.

Licence

MIT.