--- name: blockodile-connections description: Connect blockodile to another machine or a VPS over SSH and prove the connection works. Use when the user wants to work on a remote machine, add or edit a connection in ~/.config/blockodile/connections.json, or when a connection shows no panes, fails its Test, or cannot be reached. --- # blockodile connections You are helping someone **use** blockodile, not build it. Writing a module is a separate skill, **blockodile-modules**. blockodile is a desktop shell for [herdr](https://herdr.dev). A **connection** decides which herdr server it drives: this machine by default, or another computer over plain SSH — the same `ssh` the user would type in a terminal, with no agent, bridge or daemon of blockodile's own in between. The machines live in `~/.config/blockodile/connections.json`, which you may write directly — blockodile re-reads it whenever Settings opens, so no restart is needed. ```json [ { "id": "vps", "label": "Hetzner", "target": "root@1.2.3.4" }, { "id": "imac", "label": "iMac", "target": "alek@omarchy" }, { "id": "box", "label": "Build box", "target": "ssh://ci@10.0.0.9:2222" } ] ``` | Field | Rule | |---|---| | `id` | `[A-Za-z0-9_-]`, 1–40 chars. It keys saved layouts, a PTY and an SSH ControlPath, so **never change it** on an existing entry — rename `label` instead | | `label` | Free text, shown in the sidebar and the palette | | `target` | Anything `ssh` accepts as a destination: `user@host`, `ssh://user@host:port`, or a `Host` alias from `~/.ssh/config` | `local` is synthetic: it is always present, is never stored, and any entry claiming that id is dropped. So is any entry whose `id` breaks the rule above — silently, like a bad manifest. Which one a window is on lives in `settings.json` as `activeConnection` (the `id`, or `"local"`). Changing it by hand needs the app restarted; from the UI it is `Cmd/Ctrl+K` → **Switch to ``**, which reloads the window for you. ## Two prerequisites, and how to prove them Everything blockodile does on that machine runs through non-interactive SSH, so a password prompt is a failure, not a question. Check both from a terminal **before** blaming the app: ```bash # 1. SSH without a prompt. Must print ok in well under a second. ssh -o BatchMode=yes -o ConnectTimeout=5 -- 'echo ok' # 2. herdr on that machine. Never use `command -v`: a non-interactive ssh has no useful # PATH, and herdr commonly sits in ~/.local/bin. Probe the paths blockodile probes. ssh -o BatchMode=yes -- 'for p in $HOME/.local/bin/herdr /opt/homebrew/bin/herdr /usr/local/bin/herdr; do [ -x "$p" ] && echo "$p" && "$p" --version && break; done' ``` Needs herdr **0.9.0 or newer**. If the second command prints nothing, install it there: `curl -fsSL https://herdr.dev/install.sh | sh`. ## Reading a failure Settings → Connections → **Test** runs the real setup checks against that machine and prints one actionable sentence per row. The raw SSH errors behind them: | SSH says | Meaning | Fix | |---|---|---| | `Permission denied (publickey)` | Your key is not on that machine | `ssh-copy-id ` once, from this machine | | `Could not resolve hostname` | Name does not resolve | Check it, or bring up the VPN / Tailscale | | `Connection refused` | Nothing listening on SSH | Remote Login (macOS) or `systemctl enable --now sshd` (Linux) | | `Connection closed by ` | Refused **before** key exchange — a ban, a firewall, an allowed-hours rule. Plain `ssh` hides the reason in a banner | `ssh -v `, or `nc 22`, prints the banner | | `herdr ... server_not_running` | Normal on a cold machine: blockodile starts one itself | Nothing; re-run the Test | A connection that looks fine but shows **no panes at all** is usually the other machine running an older blockodile, which has no private herdr server and sits on herdr's default socket. Update it there. ## What does not follow the connection Sessions, agents, the terminal and the folder browser are that machine's. The **Files** module, **Show in folder** and the **Localhost** module still act on the computer blockodile is running on. Do not report that as a bug; it is a known gap. ## Doing the job end to end When asked to add a machine, do all four steps — an entry nobody proved is worth nothing: 1. **Ask for the target** if it is not given: user, host or IP, and a port only when it is not 22. 2. **Prove it** with the two commands above. If SSH fails, fix that first (usually `ssh-copy-id`); if herdr is missing, install it there. Never guess — run them. 3. **Write the entry** into `~/.config/blockodile/connections.json`, keeping every entry already in the file. Create the file with a one-element array if it does not exist. 4. **Tell the user how to reach it**: Settings > Connections shows it immediately (the file is re-read when Settings opens), and `Cmd/Ctrl+K` -> "Switch to