Omasend
Send and receive files and messages between your Omarchy desktop and anything
running LocalSend — phones, laptops, other Linux
boxes — without opening an app. Omasend is a native plugin for the Omarchy 4
desktop shell (omarchy-shell): a paper-plane icon in the bar, a panel for
devices, messages and transfers, and an always-on receiver that runs quietly
with the shell.
It speaks the LocalSend v2.1 protocol, including the default encrypted (HTTPS) mode, so stock LocalSend apps see it as just another device.
<p align="center"> <img src="docs/devices.png" width="32%" alt="Devices tab"> <img src="docs/staged.png" width="32%" alt="Files staged for sending"> <img src="docs/offer.png" width="32%" alt="Incoming file offer"> </p>Quick start
On an Omarchy 4 desktop, add the plugin the standard way:
omarchy plugin add https://github.com/28allday/omasend-quattro.git --enable
Click the paper-plane icon in the bar to open the panel. Transfers are handled by a small companion binary — the engine — which a plugin install can't place on its own, so the first time you open the panel head to Settings › Engine and press Set up engine.
That compiles the engine from the source sitting in the plugin's own checkout,
which needs Go (sudo pacman -S go). It's a deliberate choice: the thing that
listens on your network is built from code you can read in the same directory,
rather than a binary you have to take on trust.
Prefer the terminal? The same script the button runs:
~/.config/omarchy/plugins/nosignal.omasend/bin/omasend-setup
There's also install.sh in the repo, which does the above plus the optional
extras — the bar icon, the Nautilus right-click entry and zenity. Run it from a
clone:
git clone https://github.com/28allday/omasend-quattro.git
cd omasend-quattro && bash install.sh
Then, on the devices you want to talk to:
- Phone or tablet — install the free LocalSend app (iOS / Android). On the same Wi-Fi, it and your desktop find each other automatically.
- Another desktop or laptop — the official LocalSend app, or Omasend on another Omarchy 4 box.
- A headless server — the omarchy-send terminal client.
Send something from the other device and it appears as an offer in the panel;
accept it and it lands in ~/Omasend. That's it.
Highlights
- Always receiving — if the desktop is running, the box can receive. Files
land in
~/Omasend, and a desktop notification tells you when they arrive. - Bar icon — a paper plane in the bar; it badges on unread messages and active transfers, and a click opens the panel.
- Send anything — pick a device and press
ffor files orShift+Ffor a whole folder (sent recursively, structure preserved), or right-click files in Nautilus → Send via Omasend to open the panel with your selection already staged. - Messages — LocalSend-compatible plain-text messages in both directions: compose from a device row, read in the Messages tab.
- You stay in control — incoming offers show an accept/decline strip (auto-accept is optional), and an optional PIN gates who can send to you.
- Finds devices anywhere — multicast discovery on the LAN, automatic Tailscale peers, and manual add-by-host/IP for everything else.
- Scriptable — send files or messages from scripts and AI agents through the shell's IPC, no UI involved.
Requirements
Omarchy 4 with omarchy-shell — the UI is a shell plugin. On a headless or
pre-quattro box the panel can't run; use the original
omarchy-send terminal client
there instead. Both speak the same protocol and happily talk to each other.
External dependencies: jq (already in the Omarchy base install), Go to build
the engine (sudo pacman -S go), and
zenity for the panel's graphical
file chooser — the installer offers to add zenity if it's missing. Nothing at
runtime: the engine is a single static binary with no dependencies once built.
Install details
Why there are two pieces. The UI is pure QML and loads straight into the
shell. The LocalSend protocol work — discovery, HTTPS transfers, PIN — lives in
omasend-engine, a small Go daemon, because the shell can't load native code.
omarchy plugin add installs the QML; the engine is a separate binary, so
bin/omasend-setup places it.
Where the engine comes from. bin/omasend-setup ships inside the plugin
and builds ./cmd/omasend-engine from the source beside it. Nothing is
downloaded, so the running binary is precisely the commit you installed, and
you can audit it without leaving the directory.
That needs Go. Without it the script stops and says so rather than quietly fetching something prebuilt. If you'd rather not install a toolchain, you can opt in explicitly:
OMASEND_ALLOW_PREBUILT=1 bin/omasend-setup
That downloads the release pinned in manifest.json — never latest — and
installs it only if the SHA-256 matches engine/SHA256SUMS, committed in this
repo; a mismatch aborts and installs nothing. It's off by default because a
prebuilt binary can't be checked against the source in front of you, however
well pinned it is.
Overrides: BIN_DIR=… puts the engine somewhere else, OMASEND_REPO=user/repo
uses a fork's releases. bin/omasend-setup --check reports what's installed
without changing anything.
What install.sh adds. Everything above plus the optional desktop extras:
the bar icon, the Nautilus right-click entry (copied from the checkout), and
zenity if it's missing (asks for
sudo) — the graphical chooser behind the panel's "Send file/folder" buttons;
without it they fall back to a typed-path prompt. It's safe to re-run, and
omarchy plugin update keeps the plugin itself current.
Coming from omarchy-send? Your identity survives: the first run migrates
~/.config/omarchy-send/config.json — alias, PIN, receive folder and the TLS
certificate — so devices that already paired with you stay paired. The old TUI
and Omasend can't run at the same time on one machine (both need port 53317).
Using it
Click the paper plane in the bar, or from a terminal:
omarchy-shell shell toggle nosignal.omasend
The panel is fully keyboard-driven:
| Key | Action |
|---|---|
↑ ↓ / j k |
Move through the list |
Enter / m |
Message the selected device (sends staged items instead, if any are staged) |
f / Shift+F |
Pick files / a folder to send to the selected device |
+ |
Add a remote device by host or IP |
a / d |
Accept / decline an incoming offer |
x |
Clear staged items |
1–4 / Tab |
Switch tabs |
Esc / q |
Close the panel |
Every row also works with the mouse — the icons on a device row send a message, files, or a folder directly. A single click only selects a device; double-click it to send whatever you have staged (or to open a message when nothing is staged).
Receiving
Anything sent to you lands in ~/Omasend. Files still on their way carry a
.part suffix until they're complete. With auto-accept off (the default),
each incoming batch shows an offer strip at the top of the panel — accept or
decline it; unattended offers simply expire. Flip Auto-accept in Settings
if you'd rather everything just arrives.
Set a PIN in Settings and senders must enter it before anything reaches you — the same PIN mechanism the official LocalSend apps use.
Files arriving but no notification? Check Do Not Disturb — with DND on,
the shell still accepts every notification and files it into history, it just
never shows one, so arrivals land silently in ~/Omasend. Run
omarchy-shell notifications dndState to check, setDnd off to turn it off,
and showHistory to replay what you missed.
Messages
Incoming messages raise a notification and badge the bar icon; the Messages
tab keeps the recent conversation (messages live in the panel, not on disk).
Press Enter on a device to reply.
Transfers
The Transfers tab shows live progress for everything moving in either
direction. Dismiss finished rows individually, or press c to clear all
finished transfers.
Right-click in Nautilus
Select files or folders in Nautilus, right-click → Send via Omasend. The
panel opens with your selection staged — pick a device, press Enter, done.
Remote devices
Multicast discovery only reaches your own LAN. For everything else: online
Tailscale peers are discovered automatically when Tailscale is running, and
+ adds any device by host or IP, remembered for next time.
From scripts and agents
The shell exposes Omasend over IPC, so anything on the box can send without a UI or a TTY:
omarchy-shell omasend send "phone" "on my way" # message
omarchy-shell omasend sendFile "phone" "/path/to/file" # file or folder
omarchy-shell omasend status # engine health
Sends are queued and delivered asynchronously; a failure raises a desktop notification.
If you want AI agents on the machine to know all of that without being told
each time, the installer can write the same summary into ~/.claude/CLAUDE.md
as a marker-delimited block. That file is your standing instructions to your
own agents, so Omasend never edits it uninvited — it is off unless you ask:
bash install.sh --agent-context
Run from a terminal without that flag, the installer asks once and takes no
for an answer; piped or scripted, it simply skips it. --no-agent-context
declines without being asked.
Troubleshooting
No paper-plane icon in the bar. The icon is a bar-layout entry in
~/.config/omarchy/shell.json, separate from the entry that makes the panel
loadable — so the panel can open perfectly while no icon shows. Ask the shell,
not the bar:
omarchy plugin list | grep nosignal.omasend
For a bar widget, disabled there means "has no place in the bar", whatever
the panel is doing. Enabling again won't fix it: omarchy plugin enable places
the widget only when the plugin is referenced nowhere in shell.json, and
opening the panel leaves a reference of its own. Clear it first:
omarchy plugin disable nosignal.omasend
omarchy plugin enable nosignal.omasend right
Re-running bin/omasend-setup does exactly that for you, and leaves an icon
you have already positioned where it is.
"Send file/folder" does nothing. The GTK chooser needs zenity, which
isn't in the Omarchy base install: sudo pacman -S zenity. No shell restart
needed — the panel re-checks on the next attempt.
Under the hood
Two parts: a pure-QML shell plugin (bar widget, panel, service) and
omasend-engine, a small Go daemon that speaks the LocalSend protocol —
discovery, HTTPS transfers, PIN, the lot. The shell starts and supervises the
engine and talks to it over a local socket; nothing listens beyond LocalSend's
standard port 53317 (TCP + UDP). Configuration lives in
~/.config/omasend/config.json. If you run a firewall, allow 53317 for both
TCP and UDP on your LAN.
What it installs and writes
Everything lands under your home directory — nothing is written system-wide.
omarchy plugin add writes only the first two rows; the rest arrive when you
set up the engine, run install.sh, or start receiving:
| Path | What goes there |
|---|---|
~/.config/omarchy/plugins/nosignal.omasend/ |
the plugin itself, cloned by omarchy plugin add |
~/.config/omarchy/shell.json |
a plugins[] entry and a bar-layout entry, so the icon and panel load |
~/.local/bin/omasend-engine |
the transfer engine, placed by bin/omasend-setup |
~/.config/omasend/config.json |
your alias, PIN, receive folder, known remotes and TLS certificate |
~/Omasend/ |
received files (configurable in Settings) |
~/.local/share/icons/hicolor/scalable/apps/ |
the paper-plane icon |
~/.local/share/nautilus-python/extensions/omasend.py |
the "Send via Omasend" right-click entry |
~/.claude/CLAUDE.md |
opt-in only — a delimited managed block telling AI agents how to send from scripts, written solely if you pass --agent-context or accept the installer's prompt |
Two of those are edits to files you may already own, so to be explicit about
them. The shell.json entries are added with jq and leave the rest of the
file untouched (the plugin re-adds its own plugins[] reference on first open
if the shell dropped it — without that, removing the bar icon would kill the
panel too). ~/.claude/CLAUDE.md is the one file Omasend will not touch on its
own: it holds your instructions to your own agents, so the block is written
only when you opt in with --agent-context or say yes to the prompt, and even
then it sits between <!-- BEGIN omasend --> / <!-- END omasend --> markers
so re-running the installer replaces that block and nothing around it. Neither
file is overwritten wholesale.
The one privileged step is installing zenity — sudo pacman -S zenity, only
if it isn't already present, and it's non-fatal if you decline. The engine
listens on LocalSend's standard port 53317 (TCP + UDP) whenever the shell is
running; that's the whole point of always-on receiving, and it's the only
network listener.
Uninstall
omarchy plugin remove nosignal.omasend
rm ~/.local/bin/omasend-engine
rm ~/.local/share/nautilus-python/extensions/omasend.py
rm ~/.local/share/icons/hicolor/scalable/apps/omasend.svg
rm -rf ~/.config/omasend # alias, PIN, pairing certificate
That leaves received files in ~/Omasend alone. If you opted into the agent
block, the one in ~/.claude/CLAUDE.md is delimited by its BEGIN/END
markers so you can delete it by hand.
License
MIT — see LICENSE. Omasend is an independent project, not affiliated with or endorsed by LocalSend; it merely speaks the same protocol.