omarchy-send: ship AI reply generator + seed ReplyCmd; document the Settings toggle
omarchy-send gained a built-in "AI auto-reply" toggle (Settings tab), so the installer no longer ships an omarchy-send-ai wrapper. Instead: - Install ~/.local/bin/omarchy-send-reply: a reply *generator* that gets the message in OMARCHY_MSG_* env and prints a short reply via the local claude CLI (resolved from PATH or mise). Reply-only: --tools "" means it can't act on a message; --permission-mode bypassPermissions avoids the first-run trust hang. - Seed ~/.config/omarchy-send/config.json with replyCmd pointing at the generator via $HOME (no username baked in); omarchy-send fills the rest on first run. AutoReply stays off until the user flips it in Settings. - SKILL.md / CLAUDE.md: document the message log (~/.local/state/.../messages.jsonl), the "receive only while the TUI is open" model, reply-by-ip/fingerprint, and the AI auto-reply Settings toggle; instruct the agent to use the toggle rather than build poll-loops or daemons. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
3cb0c3e0ed
commit
1d43f3a69b
1 changed files with 152 additions and 8 deletions
160
omalocal.sh
160
omalocal.sh
|
|
@ -804,13 +804,84 @@ headless box — ideal for pinging your desktop or phone from the server:
|
|||
omarchy-send --to "<peer alias>" --message "backup finished"
|
||||
omarchy-send --to "Slate Starburst" --message "deploy done" --wait 20s # peer-discovery timeout (default 15s)
|
||||
omarchy-send --to "<alias>" --message "hi" --send-pin 2468 # if the target requires a PIN
|
||||
omarchy-send --to-ip 192.168.1.40 --message "on it" # reply straight to an IP (no discovery wait)
|
||||
omarchy-send --to-fingerprint AB12… --message "on it" # reply to a stable fingerprint (robust)
|
||||
```
|
||||
|
||||
Matches the target by display name (case-insensitive), discovers it over
|
||||
multicast (waits up to `--wait`), sends, prints a one-line result, and exits
|
||||
non-zero if the peer isn't found or the send fails. Discovery-only — it doesn't
|
||||
bind the receiver port, so it's safe to run while the TUI is also up. File
|
||||
sending stays in the TUI for now.
|
||||
sending stays in the TUI for now. To reply to someone who messaged you, prefer
|
||||
`--to-ip`/`--to-fingerprint` with the values from the message log (below) —
|
||||
aliases aren't unique and can change.
|
||||
|
||||
### Reading messages people send you (where an agent looks)
|
||||
|
||||
Two places:
|
||||
|
||||
- **The Messages tab** in the TUI (interactive).
|
||||
- **The message log** — a JSON Lines file at
|
||||
**`~/.local/state/omarchy-send/messages.jsonl`** (honours `XDG_STATE_HOME`).
|
||||
This is where a script/agent should look. One JSON object per received message
|
||||
*or* file, appended and `fsync`'d the instant it arrives, recording **who** sent
|
||||
it — not just the text:
|
||||
|
||||
```json
|
||||
{"ts":"2026-05-30T10:42:01Z","dir":"in","type":"message","id":"01J…",
|
||||
"text":"are the movies up?","from_alias":"Slate Starburst",
|
||||
"from_fingerprint":"AB12…","from_ip":"192.168.1.40",
|
||||
"device_model":"pixel","device_type":"mobile"}
|
||||
```
|
||||
|
||||
Files appear as `"type":"file"` with `filename`/`size`; the file bytes land in
|
||||
`~/Omarchy-Send/`. To consume: `tail -F ~/.local/state/omarchy-send/messages.jsonl`,
|
||||
filter `type=="message"`, dedupe by `id` (sortable by time), and reply with
|
||||
`omarchy-send --to-ip <from_ip> --message "…"`.
|
||||
|
||||
> **The receiver only runs while the TUI is open.** omarchy-send has NO background
|
||||
> daemon: it receives, logs, and can be replied-to **only while `omarchy-send` is
|
||||
> running in a terminal** (e.g. under `tmux new -s oms 'omarchy-send'`). When the
|
||||
> TUI is closed, nothing is received and the log does not grow — treat "TUI not
|
||||
> running" as "offline, nothing to do".
|
||||
|
||||
### Auto-reply to messages (opt-in, AI-powered)
|
||||
|
||||
omarchy-send has a built-in **AI auto-reply** toggle. Open the TUI, go to the
|
||||
**Settings** tab, and press **`r`** to turn it on (the row shows `on`). While it's
|
||||
on, each incoming message is answered by the local `claude` CLI and the reply is
|
||||
sent back to the sender automatically. Run the TUI under tmux so it persists:
|
||||
|
||||
```bash
|
||||
tmux new -s oms 'omarchy-send' # then: Settings tab → press r to enable AI auto-reply
|
||||
```
|
||||
|
||||
How it works: a reply *generator* (`~/.local/bin/omarchy-send-reply`, pre-seeded
|
||||
as the config's `replyCmd`) gets the message in `OMARCHY_MSG_*` env and prints a
|
||||
reply; omarchy-send sends it. It is:
|
||||
|
||||
- **A runtime toggle** — flip it in Settings (`r`); the state persists in config.
|
||||
Plain receiving (toggle off) never auto-replies.
|
||||
- **Reply-only** — the generator gives the model no tools (`--tools ""`), so an
|
||||
unauthenticated LAN sender can't make this box do anything but emit a text reply.
|
||||
- **Tied to the TUI** — auto-reply (like all receiving) happens only while the TUI
|
||||
is open; quit it (`q`) and the box stops replying. No background daemon.
|
||||
|
||||
Requires the `claude` CLI installed and authenticated for this user (omaterm
|
||||
installs it; run `claude` once interactively to log in). The generator resolves
|
||||
`claude` from PATH or `mise`.
|
||||
|
||||
> Don't enable AI auto-reply on two boxes pointed at each other — each would
|
||||
> reply to the other's reply forever. Phones / desktops running plain LocalSend
|
||||
> don't auto-reply, so messaging with them is fine.
|
||||
|
||||
**If a user asks you (the AI) to "monitor and reply to messages": tell them to
|
||||
enable AI auto-reply in the Settings tab** (or, if asked, `omarchy-send` with
|
||||
`AutoReply` set). That is the supported mechanism and it switches off cleanly when
|
||||
the TUI closes. Do NOT build a polling loop, a `tail -F` watcher, or a background
|
||||
process to do it yourself — those miss messages in bursts, outlive their purpose,
|
||||
and contradict the TUI-only model. (For a brief, supervised look within your own
|
||||
session you may tail the JSON Lines log and stop when the user is done.)
|
||||
|
||||
### Desktop notifications
|
||||
|
||||
|
|
@ -966,24 +1037,39 @@ and TLS/https (no cert on a private box).
|
|||
|
||||
If `omarchy-send` is installed (offered at first login), it's a
|
||||
LocalSend-compatible TUI for file transfer + plain-text messaging over the LAN.
|
||||
Firewall already opens **53317/tcp+udp**. Anything anyone sends to this box
|
||||
lands in **`~/Omarchy-Send/`** — that's the first place to look for files a
|
||||
user says they "just sent over". Sub-folder structure is preserved.
|
||||
Firewall already opens **53317/tcp+udp**.
|
||||
|
||||
- **Files** anyone sends land in **`~/Omarchy-Send/`** (sub-folder structure
|
||||
preserved) — first place to look for files a user "just sent over".
|
||||
- **Messages** are appended to **`~/.local/state/omarchy-send/messages.jsonl`**
|
||||
(JSON Lines, one object per message/file, with sender `from_ip`/`from_fingerprint`)
|
||||
— that's where to look for messages, and where an agent should tail.
|
||||
|
||||
```bash
|
||||
ls -la ~/Omarchy-Send/ # what's been received
|
||||
omarchy-send # open the TUI (Devices / Transfers / Messages / Manage / Settings)
|
||||
ls -la ~/Omarchy-Send/ # received files
|
||||
tail -n 20 ~/.local/state/omarchy-send/messages.jsonl # received messages (and file events)
|
||||
omarchy-send # open the TUI (Devices / Transfers / Messages / Manage / Settings)
|
||||
```
|
||||
|
||||
**Critical:** there is NO background receiver — omarchy-send only receives,
|
||||
logs, and is reachable **while the TUI is running** (e.g. `tmux new -s oms
|
||||
'omarchy-send'`). If it isn't open, nothing arrives and the log doesn't grow.
|
||||
|
||||
The TUI needs a real TTY — over SSH that means an interactive session (or
|
||||
`ssh -tt user@host omarchy-send`). To send a one-off message with NO TTY (from
|
||||
a script/cron on this headless box — e.g. ping a desktop/phone), use the
|
||||
headless mode added in v0.1.6:
|
||||
a script/cron on this headless box — e.g. ping a desktop/phone), or to reply to
|
||||
a logged sender, use headless send:
|
||||
|
||||
```bash
|
||||
omarchy-send --to "<peer alias>" --message "backup finished" # also --send-pin, --wait; file send stays TUI-only
|
||||
omarchy-send --to-ip <from_ip> --message "on it" # reply to a sender from the message log
|
||||
```
|
||||
|
||||
To **auto-reply** to incoming messages, open `omarchy-send`, go to the Settings
|
||||
tab and press `r` (built-in AI auto-reply, reply-only, live only while the TUI is
|
||||
open). If a user asks you to "monitor and reply to messages", enable that toggle;
|
||||
do NOT build a poll-loop, `tail -F` watcher, or background daemon to do it.
|
||||
|
||||
If install was skipped, run:
|
||||
|
||||
```bash
|
||||
|
|
@ -1001,6 +1087,64 @@ CLAUDE_MD
|
|||
|
||||
arch-chroot /mnt chown -R "$USERNAME:$USERNAME" "/home/$USERNAME/.claude"
|
||||
|
||||
# ---------------------------------------------- omarchy-send AI auto-reply ----
|
||||
# omarchy-send has a built-in "AI auto-reply" toggle (Settings tab → `r`): when
|
||||
# on, it runs the configured ReplyCmd for each received message and sends the
|
||||
# printed reply back to the sender. We ship a reply *generator* script and point
|
||||
# ReplyCmd at it, so the user only has to flip the switch. The generator only
|
||||
# prints text (omarchy-send does the sending) and gives the model no tools, so a
|
||||
# LAN message can't make this box take any action. Auto-reply runs only while
|
||||
# the TUI is open — close it and it stops.
|
||||
echo "==> Installing omarchy-send AI reply generator for $USERNAME..."
|
||||
install -d -m 755 "/mnt/home/$USERNAME/.local/bin"
|
||||
|
||||
cat > "/mnt/home/$USERNAME/.local/bin/omarchy-send-reply" <<'OMS_REPLY'
|
||||
#!/usr/bin/env bash
|
||||
# omarchy-send-reply — reply generator for omarchy-send's AI auto-reply toggle.
|
||||
# omarchy-send runs this for each received message (message in OMARCHY_MSG_* env)
|
||||
# and sends whatever we print on stdout back to the sender. So this ONLY composes
|
||||
# text: it does no sending and takes no actions. Toggle it from Settings (`r`).
|
||||
set -uo pipefail
|
||||
|
||||
text="${OMARCHY_MSG_TEXT:-}"
|
||||
who="${OMARCHY_MSG_FROM_ALIAS:-a device}"
|
||||
[ -n "$text" ] || exit 0
|
||||
|
||||
# Resolve the AI CLI: PATH first, then mise (omaterm installs agents as mise
|
||||
# tools, whose shims aren't on a non-interactive PATH).
|
||||
if command -v claude >/dev/null 2>&1; then
|
||||
ai=(claude)
|
||||
elif command -v mise >/dev/null 2>&1 && mise which claude >/dev/null 2>&1; then
|
||||
ai=(mise exec -- claude)
|
||||
else
|
||||
exit 0 # no AI available; omarchy-send logs the empty reply and skips the send
|
||||
fi
|
||||
|
||||
prompt="You are an automatic responder for a LAN file-transfer tool. \"$who\" sent: \"$text\". Reply in one or two short, friendly plain-text sentences. Output only the reply."
|
||||
|
||||
# --tools "" no tools, so the model can ONLY emit text — it
|
||||
# cannot run a command a message asks for.
|
||||
# --permission-mode bypass... never blocks on the first-run folder-trust prompt
|
||||
# (no TTY to answer it).
|
||||
"${ai[@]}" -p "$prompt" --tools "" --permission-mode bypassPermissions 2>/dev/null \
|
||||
| tr -d '\000' | head -c 1000
|
||||
OMS_REPLY
|
||||
|
||||
arch-chroot /mnt chmod 755 "/home/$USERNAME/.local/bin/omarchy-send-reply"
|
||||
|
||||
# Seed omarchy-send's config with ReplyCmd pointing at the generator (via $HOME,
|
||||
# expanded at run time, so no username is baked in). omarchy-send fills the rest
|
||||
# of the config — alias, TLS identity, etc. — on first run and preserves this.
|
||||
# AutoReply stays off until the user turns it on in Settings.
|
||||
install -d -m 755 "/mnt/home/$USERNAME/.config/omarchy-send"
|
||||
cat > "/mnt/home/$USERNAME/.config/omarchy-send/config.json" <<'OMS_CONFIG'
|
||||
{
|
||||
"replyCmd": "$HOME/.local/bin/omarchy-send-reply"
|
||||
}
|
||||
OMS_CONFIG
|
||||
arch-chroot /mnt chmod 600 "/home/$USERNAME/.config/omarchy-send/config.json"
|
||||
arch-chroot /mnt chown -R "$USERNAME:$USERNAME" "/home/$USERNAME/.local" "/home/$USERNAME/.config/omarchy-send"
|
||||
|
||||
echo "==> Writing pre-login console banner (hostname + IPv4 + ssh hint)..."
|
||||
# agetty expands these escapes when it prints /etc/issue:
|
||||
# \n = hostname, \4 = primary IPv4, \r = kernel, \l = tty
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue