Guides
Remote servers
The same command on a server, its rows reaching your Mac over ssh.
Add a server in Settings → Servers and set up its evlat command. The same evlat watch and evlat signal then work on the server, and their rows reach your Mac, tagged with the machine’s name.
What gets installed
| ~/.local/bin/evlat | A small shell script that sends with curl to the socket ~/.config/evlat/run/evlat.sock on the server, or to $EVLAT_SOCKET when that is set. No key. |
|---|
Evlat does this over ssh, or gives you a block to paste into the server yourself. An evlat on the server that isn’t Evlat’s is never overwritten. Installing or removing the command also takes away ~/.config/evlat/signal.token, the key an older version left there.
How rows reach your Mac
Evlat keeps an ssh connection open to each server, and through it forwards the server’s ~/.config/evlat/run/evlat.sock to Evlat on your Mac. No network port is opened on the server. The socket’s folder is made so that only your user on the server can enter it.
What the server needs
sshdmust let ssh forward a socket. It does unless its config turns that off withAllowStreamLocalForwarding no,AllowTcpForwarding noorDisableForwarding yes. Such a server is not supported, and its row in Settings says the server does not let ssh forward a socket.curl7.40 or newer, which can reach a socket.
Check it from the server
evlat --listOne line, with the command’s version and the socket’s path in brackets at the end:
| It starts with | Means |
|---|---|
ok | Your Mac hears this machine. |
no curl | Install curl on the server. |
curl too old | It cannot reach a socket. Update it to 7.40 or newer. |
no socket | Evlat isn’t running on your Mac, or this machine isn’t connected. |
no route (404) | Evlat on your Mac is older than the command. Update it. |
no answer | The socket is left from an earlier connection. Evlat on your Mac takes it back when it connects. |
unexpected answer | Something else answered on the socket; its status is in brackets. |
Use it
evlat watch --label "nightly import" -- ./import.sh
evlat signal backup --label "Backup" --progress 0.6A server’s rows dim while its tunnel is down, and come back when it reconnects.
Approvals from the bar
Agents on a server ask the bar for approval too, once their hooks are set up in Settings → Servers:
- Claude Code: Allow once or Deny a permission prompt on the session’s card, and answer its questions there.
- Codex CLI: Allow once or Deny a permission prompt. Codex shows Running hook while its card waits on the bar, two minutes at most. Codex runs new or changed hooks only after you trust them in its
/hooks. - Antigravity gets hooks only: its sessions show on the bar, and you answer where it runs.
- OpenCode: Allow once or Deny a permission prompt; a question is answered in OpenCode. Its card puts one plugin file,
~/.config/opencode/plugins/evlat.js, on the server, only where OpenCode’s own folders are. Remove takes that file and nothing else, and a file of yours at that path, or a link, is left alone. OpenCode keeps the plugin it started with until it starts again.
After updating Evlat
Hooks and commands installed by an older version stay silent until they are updated. In Settings → This Mac each such card says Needs update, and one press moves it; for a server, do the same in Settings → Servers. Open Claude Code sessions pick the change up with their next message; Codex asks you to trust the new hooks in /hooks; OpenCode takes a changed plugin the next time it starts.
Differences from the Mac
- The server needs
curl. Without it, or without the socket,evlat watchjust runs the command. - There is no
--capture. - A
TERMsent toevlat watchalone takes effect after the command ends; signals sent to the command itself work as usual.
Shared servers
- A server tells one Mac at a time. If another Mac’s Evlat is connected to it as the same user, your row says another Evlat answers this server, and your Mac takes over once that connection ends.
- Update Evlat on every Mac before you update a shared server’s parts: an older Evlat could undo what a newer one installed.