This repo supports “remote over SSH” by keeping a single Gateway (the master) running on a dedicated host (desktop/server) and connecting clients to it.
Think of the Gateway host as “where the agent lives.” It owns sessions, auth profiles, channels, and state. Your laptop/desktop (and nodes) connect to that host.
Run the Gateway on a persistent host and reach it via Tailscale or SSH.
gateway.bind: "loopback" and use Tailscale Serve for the Control UI.This is ideal when your laptop sleeps often but you want the agent always-on.
The laptop does not run the agent. It connects remotely:
Runbook: macOS remote access.
Keep the Gateway local but expose it safely:
Guide: Tailscale and Web overview.
One gateway service owns state + channels. Nodes are peripherals.
Flow example (Telegram → node):
node.* RPC).Notes:
Create a local tunnel to the remote Gateway WS:
ssh -N -L 18789:127.0.0.1:18789 user@host
With the tunnel up:
coderclaw health and coderclaw status --deep now reach the remote gateway via ws://127.0.0.1:18789.coderclaw gateway {status,health,send,agent,call} can also target the forwarded URL via --url when needed.Note: replace 18789 with your configured gateway.port (or --port/CODERCLAW_GATEWAY_PORT).
Note: when you pass --url, the CLI does not fall back to config or environment credentials.
Include --token or --password explicitly. Missing explicit credentials is an error.
You can persist a remote target so CLI commands use it by default:
{
gateway: {
mode: "remote",
remote: {
url: "ws://127.0.0.1:18789",
token: "your-token",
},
},
}
When the gateway is loopback-only, keep the URL at ws://127.0.0.1:18789 and open the SSH tunnel first.
WebChat no longer uses a separate HTTP port. The SwiftUI chat UI connects directly to the Gateway WebSocket.
18789 over SSH (see above), then connect clients to ws://127.0.0.1:18789.The macOS menu bar app can drive the same setup end-to-end (remote status checks, WebChat, and Voice Wake forwarding).
Runbook: macOS remote access.
Short version: keep the Gateway loopback-only unless you’re sure you need a bind.
lan/tailnet/custom, or auto when loopback is unavailable) must use auth tokens/passwords.gateway.remote.token is only for remote CLI calls — it does not enable local auth.gateway.remote.tlsFingerprint pins the remote TLS cert when using wss://.gateway.auth.allowTailscale: true.
Set it to false if you want tokens/passwords instead.Deep dive: Security.